Skip to content

Commit 1dd7c32

Browse files
pks-tgitster
authored andcommitted
git: refactor builtin handling to use a struct strvec
Similar as with the preceding commit, `handle_builtin()` does not properly track lifetimes of the `argv` array and its strings. As it may end up modifying the array this can lead to memory leaks in case it contains allocated strings. Refactor the function to use a `struct strvec` instead. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ffc5c04 commit 1dd7c32

File tree

2 files changed

+32
-36
lines changed

2 files changed

+32
-36
lines changed

git.c

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -696,63 +696,57 @@ void load_builtin_commands(const char *prefix, struct cmdnames *cmds)
696696
}
697697

698698
#ifdef STRIP_EXTENSION
699-
static void strip_extension(const char **argv)
699+
static void strip_extension(struct strvec *args)
700700
{
701701
size_t len;
702702

703-
if (strip_suffix(argv[0], STRIP_EXTENSION, &len))
704-
argv[0] = xmemdupz(argv[0], len);
703+
if (strip_suffix(args->v[0], STRIP_EXTENSION, &len)) {
704+
char *stripped = xmemdupz(args->v[0], len);
705+
strvec_replace(args, 0, stripped);
706+
free(stripped);
707+
}
705708
}
706709
#else
707710
#define strip_extension(cmd)
708711
#endif
709712

710-
static void handle_builtin(int argc, const char **argv)
713+
static void handle_builtin(struct strvec *args)
711714
{
712-
struct strvec args = STRVEC_INIT;
713-
const char **argv_copy = NULL;
714715
const char *cmd;
715716
struct cmd_struct *builtin;
716717

717-
strip_extension(argv);
718-
cmd = argv[0];
718+
strip_extension(args);
719+
cmd = args->v[0];
719720

720721
/* Turn "git cmd --help" into "git help --exclude-guides cmd" */
721-
if (argc > 1 && !strcmp(argv[1], "--help")) {
722-
int i;
723-
724-
argv[1] = argv[0];
725-
argv[0] = cmd = "help";
726-
727-
for (i = 0; i < argc; i++) {
728-
strvec_push(&args, argv[i]);
729-
if (!i)
730-
strvec_push(&args, "--exclude-guides");
731-
}
722+
if (args->nr > 1 && !strcmp(args->v[1], "--help")) {
723+
const char *exclude_guides_arg[] = { "--exclude-guides" };
724+
725+
strvec_replace(args, 1, args->v[0]);
726+
strvec_replace(args, 0, "help");
727+
cmd = "help";
728+
strvec_splice(args, 2, 0, exclude_guides_arg,
729+
ARRAY_SIZE(exclude_guides_arg));
730+
}
732731

733-
argc++;
732+
builtin = get_builtin(cmd);
733+
if (builtin) {
734+
const char **argv_copy = NULL;
735+
int ret;
734736

735737
/*
736738
* `run_builtin()` will modify the argv array, so we need to
737739
* create a shallow copy such that we can free all of its
738740
* strings.
739741
*/
740-
CALLOC_ARRAY(argv_copy, argc + 1);
741-
COPY_ARRAY(argv_copy, args.v, argc);
742+
if (args->nr)
743+
DUP_ARRAY(argv_copy, args->v, args->nr + 1);
742744

743-
argv = argv_copy;
744-
}
745-
746-
builtin = get_builtin(cmd);
747-
if (builtin) {
748-
int ret = run_builtin(builtin, argc, argv, the_repository);
749-
strvec_clear(&args);
745+
ret = run_builtin(builtin, args->nr, argv_copy, the_repository);
746+
strvec_clear(args);
750747
free(argv_copy);
751748
exit(ret);
752749
}
753-
754-
strvec_clear(&args);
755-
free(argv_copy);
756750
}
757751

758752
static void execv_dashed_external(const char **argv)
@@ -815,7 +809,7 @@ static int run_argv(struct strvec *args)
815809
* process.
816810
*/
817811
if (!done_alias)
818-
handle_builtin(args->nr, args->v);
812+
handle_builtin(args);
819813
else if (get_builtin(args->v[0])) {
820814
struct child_process cmd = CHILD_PROCESS_INIT;
821815
int i;
@@ -916,8 +910,10 @@ int cmd_main(int argc, const char **argv)
916910
* that one cannot handle it.
917911
*/
918912
if (skip_prefix(cmd, "git-", &cmd)) {
919-
argv[0] = cmd;
920-
handle_builtin(argc, argv);
913+
strvec_push(&args, cmd);
914+
strvec_pushv(&args, argv + 1);
915+
handle_builtin(&args);
916+
strvec_clear(&args);
921917
die(_("cannot handle %s as a builtin"), cmd);
922918
}
923919

t/t0211-trace2-perf.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
test_description='test trace2 facility (perf target)'
44

5-
TEST_PASSES_SANITIZE_LEAK=false
5+
TEST_PASSES_SANITIZE_LEAK=true
66
. ./test-lib.sh
77

88
# Turn off any inherited trace2 settings for this test.

0 commit comments

Comments
 (0)