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@xxxxxx> --- builtin/describe.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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); -- 2.46.0.dirty
Attachment:
signature.asc
Description: PGP signature