git: fix leaking argv when handling builtins
In `handle_builtin()` we may end up creating an ad-hoc argv array in case we see that the command line contains the "--help" parameter. In this case we observe two memory leaks though: - We leak the `struct strvec` itself because we directly exit after calling `run_builtin()`, without bothering about any cleanups. - Even if we free'd that vector we'd end up leaking some of its strings because `run_builtin()` will modify the array. Plug both of these leaks. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Sep 26, 2024 at 13:46 UTC
3aef7a05adb2868118181eb5605fffa65a9af2c8
2 files changed
+20
-3
git.c
+19
-3
@@ -711,6 +711,7 @@ static void strip_extension(const char **argv)
711
static void handle_builtin(int argc, const char **argv)
712
{
713
struct strvec args = STRVEC_INIT;
714
+ const char **argv_copy = NULL;
715
const char *cmd;
716
struct cmd_struct *builtin;
717
@@ -731,13 +732,28 @@ static void handle_builtin(int argc, const char **argv)
732
}
733
734
argc++;
734
- argv = args.v;
735
+
736
+ /*
737
+ * `run_builtin()` will modify the argv array, so we need to
738
+ * create a shallow copy such that we can free all of its
739
+ * strings.
740
+ */
741
+ CALLOC_ARRAY(argv_copy, argc + 1);
742
+ COPY_ARRAY(argv_copy, args.v, argc);
743
+
744
+ argv = argv_copy;
745
}
746
747
builtin = get_builtin(cmd);
738
- if (builtin)
739
- exit(run_builtin(builtin, argc, argv));
748
+ if (builtin) {
749
+ int ret = run_builtin(builtin, argc, argv);
750
+ strvec_clear(&args);
751
+ free(argv_copy);
752
+ exit(ret);
753
+ }
754
+
755
strvec_clear(&args);
756
+ free(argv_copy);
757
}
758
759
static void execv_dashed_external(const char **argv)
t/t0012-help.sh
+1
@@ -2,6 +2,7 @@
2
3
test_description='help'
4
5
+TEST_PASSES_SANITIZE_LEAK=true
6
. ./test-lib.sh
7
8
configure_help () {