unpack-trees: clear index when not propagating it

When provided a pointer to a destination index, then `unpack_trees()` will end up copying its `o->internal.result` index into the provided pointer. In those cases it is thus not necessary to free the index, as we have transferred ownership of it. There are cases though where we do not end up transferring ownership of the memory, but `clear_unpack_trees_porcelain()` will never discard the index in that case and thus cause a memory leak. And right now it cannot do so in the first place because we have no indicator of whether we did or didn't transfer ownership of the index. Adapt the code to zero out the index in case we transfer its ownership. Like this, we can now unconditionally discard the index when being asked to clear the `unpack_trees_options`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 14, 2024 at 08:52 UTC 4dfd4f1dfe0d3ddbc22392ad7fc124b4820542dd
2 files changed +3
t/t3705-add-sparse-checkout.sh
+1
@@ -2,6 +2,7 @@
2
3 test_description='git add in sparse checked out working trees'
4
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7
8 SPARSE_ENTRY_BLOB=""
unpack-trees.c
+2
@@ -210,6 +210,7 @@ void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
210 {
211 strvec_clear(&opts->internal.msgs_to_free);
212 memset(opts->internal.msgs, 0, sizeof(opts->internal.msgs));
213 + discard_index(&opts->internal.result);
214 }
215
216 static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
@@ -2082,6 +2083,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
2083 o->internal.result.updated_workdir = 1;
2084 discard_index(o->dst_index);
2085 *o->dst_index = o->internal.result;
2086 + memset(&o->internal.result, 0, sizeof(o->internal.result));
2087 } else {
2088 discard_index(&o->internal.result);
2089 }