From: Patrick Steinhardt Date: Thu, 1 Aug 2024 10:38:20 +0000 (+0200) Subject: builtin/describe: fix memory leak with `--contains=` X-Git-Tag: v2.47.0-rc0~153^2~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8e2e28799d2353e32c393bd7938c457e5e08fc63;p=thirdparty%2Fgit.git builtin/describe: fix memory leak with `--contains=` 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 Signed-off-by: Junio C Hamano --- diff --git a/builtin/describe.c b/builtin/describe.c index cf8edc4222..739878db85 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -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);