In 7e2619d8ff (list_objects_filter_options: plug leak of filter_spec
strings, 2022-09-08), we noted that the filter_spec string_list was
inconsistent in how it handled memory ownership of strings stored in the
list. The fix there was a bit of a band-aid to set the "strdup_strings"
variable right before adding anything.
That works OK, and it lets the users of the API continue to
zero-initialize the struct. But it makes the code a bit hard to follow
and accident-prone, as any other spots appending the filter_spec need to
think about whether to set the strdup_strings value, too (there's one
such spot in partial_clone_get_default_filter_spec(), which is probably
a possible memory leak).
So let's do that full cleanup now. We'll introduce a
LIST_OBJECTS_FILTER_INIT macro and matching function, and use them as
appropriate (though it is for the "_options" struct, this matches the
corresponding list_objects_filter_release() function).
This is harder than it seems! Many other structs, like
git_transport_data, embed the filter struct. So they need to initialize
it themselves even if the rest of the enclosing struct is OK with
zero-initialization. I found all of the relevant spots by grepping
manually for declarations of list_objects_filter_options. And then doing
so recursively for structs which embed it, and ones which embed those,
and so on.
I'm pretty sure I got everything, but there's no change that would alert
the compiler if any topics in flight added new declarations. To catch
this case, we now double-check in the parsing function that things were
initialized as expected and BUG() if appropriate.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committedSep 11, 2022 at 01:03 UTC2a01bdedf87d7cbfc4411ff5059cfe406e1637db
index 18c51001dc..56a1933a50 100644--- a/list-objects-filter-options.c+++ b/list-objects-filter-options.c@@ -108,7 +108,7 @@ int gently_parse_list_objects_filter( strbuf_addf(errbuf, _("invalid filter-spec '%s'"), arg);- memset(filter_options, 0, sizeof(*filter_options));+ list_objects_filter_init(filter_options); return 1; }@@ -223,8 +223,7 @@ static void transform_to_combine_type( struct list_objects_filter_options *sub_array = xcalloc(initial_sub_alloc, sizeof(*sub_array)); sub_array[0] = *filter_options;- memset(filter_options, 0, sizeof(*filter_options));- string_list_init_dup(&filter_options->filter_spec);+ list_objects_filter_init(filter_options); filter_options->sub = sub_array; filter_options->sub_alloc = initial_sub_alloc; }@@ -255,11 +254,8 @@ void parse_list_objects_filter( struct strbuf errbuf = STRBUF_INIT; int parse_error;- if (!filter_options->filter_spec.strdup_strings) {- if (filter_options->filter_spec.nr)- BUG("unexpected non-allocated string in filter_spec");- filter_options->filter_spec.strdup_strings = 1;- }+ if (!filter_options->filter_spec.strdup_strings)+ BUG("filter_options not properly initialized"); if (!filter_options->choice) { string_list_append(&filter_options->filter_spec, arg);@@ -346,7 +342,7 @@ void list_objects_filter_release( for (sub = 0; sub < filter_options->sub_nr; sub++) list_objects_filter_release(&filter_options->sub[sub]); free(filter_options->sub);- memset(filter_options, 0, sizeof(*filter_options));+ list_objects_filter_init(filter_options); } void partial_clone_register(@@ -429,3 +425,9 @@ void list_objects_filter_copy( for (i = 0; i < src->sub_nr; i++) list_objects_filter_copy(&dest->sub[i], &src->sub[i]); }++void list_objects_filter_init(struct list_objects_filter_options *filter_options)+{+ struct list_objects_filter_options blank = LIST_OBJECTS_FILTER_INIT;+ memcpy(filter_options, &blank, sizeof(*filter_options));+}
list-objects-filter-options.h
+3
index ffc02d77e7..2720f7dba8 100644--- a/list-objects-filter-options.h+++ b/list-objects-filter-options.h@@ -69,6 +69,9 @@ struct list_objects_filter_options { */ };+#define LIST_OBJECTS_FILTER_INIT { .filter_spec = STRING_LIST_INIT_DUP }+void list_objects_filter_init(struct list_objects_filter_options *filter_options);+ /* * Parse value of the argument to the "filter" keyword. * On the command line this looks like: