Fixing runtime flag string lists to not grow exponentially. (#12007)

Not noticable when there's a handful of repeated flags but when there
are 100+ things get sad.
diff --git a/runtime/src/iree/base/internal/flags.c b/runtime/src/iree/base/internal/flags.c
index 1dd3246..ed35a5f 100644
--- a/runtime/src/iree/base/internal/flags.c
+++ b/runtime/src/iree/base/internal/flags.c
@@ -34,8 +34,6 @@
   return status;
 }
 
-static void iree_flags_leaky_free(void* self, void* ptr) { free(ptr); }
-
 // Allocates heap memory that is leaked without triggering leak checkers.
 // We do this so that we have valid memory for the lifetime of the process.
 // The memory may still be freed but if not will not hurt anything (besides the
@@ -155,26 +153,29 @@
                                           iree_string_view_t value) {
   iree_flag_string_list_storage_t* flag =
       (iree_flag_string_list_storage_t*)storage;
-  if (flag->count == 0) {
+  if (flag->count == 0) {  // currently empty
     // Inline storage (common case).
     flag->count = 1;
     flag->inline_value = value;
-  } else if (flag->count == 1) {
+  } else if (flag->count == 1) {  // currently inline
     // Switching from inline storage to external storage.
     iree_host_size_t new_capacity = 4;
     iree_string_view_t* values = NULL;
     IREE_RETURN_IF_ERROR(iree_allocator_malloc(
-        iree_allocator_system(), sizeof(iree_string_view_t*) * new_capacity,
+        iree_flags_leaky_allocator(), sizeof(iree_string_view_t) * new_capacity,
         (void**)&values));
     values[0] = flag->inline_value;
     flag->capacity = new_capacity;
     flag->values = values;
     flag->values[flag->count++] = value;
-  } else {
+  } else if (flag->count < flag->capacity) {  // external storage available
+    // Stash in external storage list.
+    flag->values[flag->count++] = value;
+  } else {  // external storage full
     // Growing external storage list.
     iree_host_size_t new_capacity = iree_max(4, flag->capacity * 2);
     IREE_RETURN_IF_ERROR(iree_allocator_realloc(
-        iree_allocator_system(), sizeof(iree_string_view_t*) * new_capacity,
+        iree_flags_leaky_allocator(), sizeof(iree_string_view_t) * new_capacity,
         (void**)&flag->values));
     flag->capacity = new_capacity;
     flag->values[flag->count++] = value;
diff --git a/runtime/src/iree/base/internal/flags_test.txt b/runtime/src/iree/base/internal/flags_test.txt
index d292d5b..2fb0ac9 100644
--- a/runtime/src/iree/base/internal/flags_test.txt
+++ b/runtime/src/iree/base/internal/flags_test.txt
@@ -74,6 +74,12 @@
 // FLAG-LIST-1: FLAG[test_strings] = 1: a
 // RUN: ( flags_demo --test_strings=a --test_strings=b ) | FileCheck --check-prefix=FLAG-LIST-2 %s
 // FLAG-LIST-2: FLAG[test_strings] = 2: a, b
+// RUN: ( flags_demo --test_strings=a --test_strings=b --test_strings=c ) | FileCheck --check-prefix=FLAG-LIST-3 %s
+// FLAG-LIST-3: FLAG[test_strings] = 3: a, b, c
+// RUN: ( flags_demo --test_strings=a --test_strings=b --test_strings=c --test_strings=d ) | FileCheck --check-prefix=FLAG-LIST-4 %s
+// FLAG-LIST-4: FLAG[test_strings] = 4: a, b, c, d
+// RUN: ( flags_demo --test_strings=a --test_strings=b --test_strings=c --test_strings=d --test_strings=e ) | FileCheck --check-prefix=FLAG-LIST-5 %s
+// FLAG-LIST-5: FLAG[test_strings] = 5: a, b, c, d, e
 
 // RUN: ( flags_demo arg1 ) | FileCheck --check-prefix=FLAG-POSITIONAL-1 %s
 // FLAG-POSITIONAL-1: ARG(1) = arg1
diff --git a/tests/transform_dialect/cpu/matmul.mlir b/tests/transform_dialect/cpu/matmul.mlir
index c6cb04b..1a99cf9 100644
--- a/tests/transform_dialect/cpu/matmul.mlir
+++ b/tests/transform_dialect/cpu/matmul.mlir
@@ -64,7 +64,7 @@
 // RUN: iree-run-module --entry_function=matmul_static \
 // RUN:   --function_input="3x5xf32=1" \
 // RUN:   --function_input="5x3xf32=2" \
-// RUN:   --function_input="3x3xf32=42"| \
+// RUN:   --function_input="3x3xf32=42" | \
 // RUN: FileCheck %s --check-prefixes=EXEC
 
 // EXEC: 3x3xf32=[52 52 52][52 52 52][52 52 52]