]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/describe: fix memory leak with `--contains=`
authorPatrick Steinhardt <ps@pks.im>
Thu, 1 Aug 2024 10:38:20 +0000 (12:38 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 1 Aug 2024 15:47:35 +0000 (08:47 -0700)
When calling `git describe --contains=`, we end up invoking
`cmd_name_rev()` with some munged argv array. This array may contain
allocated strings and furthermore will likely be modified by the called
function. This results in two memory leaks:

  - First, we leak the array that we use to assemble the arguments.

  - Second, we leak the allocated strings that we may have put into the
    array.

Fix those leaks by creating a separate copy of the array that we can
hand over to `cmd_name_rev()`. This allows us to free all strings
contained in the `strvec`, as the original vector will not be modified
anymore.

Furthermore, free both the `strvec` and the copied array to fix the
first memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/describe.c

index cf8edc422262c25d46c701e64d6cbc885a977a3f..739878db85bc29a81db63f7bb29983cd380cf850 100644 (file)
@@ -619,6 +619,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
        if (contains) {
                struct string_list_item *item;
                struct strvec args;
+               const char **argv_copy;
+               int ret;
 
                strvec_init(&args);
                strvec_pushl(&args, "name-rev",
@@ -637,7 +639,21 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                        strvec_pushv(&args, argv);
                else
                        strvec_push(&args, "HEAD");
-               return cmd_name_rev(args.nr, args.v, prefix);
+
+               /*
+                * `cmd_name_rev()` modifies the array, so we'd leak its
+                * contained strings if we didn't do a copy here.
+                */
+               ALLOC_ARRAY(argv_copy, args.nr + 1);
+               for (size_t i = 0; i < args.nr; i++)
+                       argv_copy[i] = args.v[i];
+               argv_copy[args.nr] = NULL;
+
+               ret = cmd_name_rev(args.nr, argv_copy, prefix);
+
+               strvec_clear(&args);
+               free(argv_copy);
+               return ret;
        }
 
        hashmap_init(&names, commit_name_neq, NULL, 0);