Skip to content

Commit ba08570

Browse files
pks-tgitster
authored andcommitted
help: fix leaking struct cmdnames
We're populating multiple `struct cmdnames`, but don't ever free them. Create a common exit path where we do so. Note that this also requires us to use `FREE_AND_NULL()` when freeing `cmdnames::names`, as we may otherwise try to free it multiple times. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b7d02df commit ba08570

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

help.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ void cmdnames_release(struct cmdnames *cmds)
169169
int i;
170170
for (i = 0; i < cmds->cnt; ++i)
171171
free(cmds->names[i]);
172-
free(cmds->names);
172+
FREE_AND_NULL(cmds->names);
173173
cmds->cnt = 0;
174174
cmds->alloc = 0;
175175
}
@@ -619,6 +619,7 @@ const char *help_unknown_cmd(const char *cmd)
619619
struct cmdnames main_cmds = { 0 };
620620
struct cmdnames other_cmds = { 0 };
621621
struct cmdname_help *common_cmds;
622+
const char *assumed = NULL;
622623

623624
read_early_config(the_repository, git_unknown_cmd_config, &cfg);
624625

@@ -630,7 +631,7 @@ const char *help_unknown_cmd(const char *cmd)
630631

631632
if (cfg.autocorrect == AUTOCORRECT_NEVER) {
632633
fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
633-
exit(1);
634+
goto out;
634635
}
635636

636637
load_command_list("git-", &main_cmds, &other_cmds);
@@ -695,7 +696,7 @@ const char *help_unknown_cmd(const char *cmd)
695696
; /* still counting */
696697
}
697698
if (cfg.autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) {
698-
const char *assumed = main_cmds.names[0]->name;
699+
assumed = main_cmds.names[0]->name;
699700
main_cmds.names[0] = NULL;
700701
cmdnames_release(&main_cmds);
701702
fprintf_ln(stderr,
@@ -714,16 +715,19 @@ const char *help_unknown_cmd(const char *cmd)
714715
answer = git_prompt(msg.buf, PROMPT_ECHO);
715716
strbuf_release(&msg);
716717
if (!(starts_with(answer, "y") ||
717-
starts_with(answer, "Y")))
718-
exit(1);
718+
starts_with(answer, "Y"))) {
719+
assumed = NULL;
720+
goto out;
721+
}
719722
} else {
720723
fprintf_ln(stderr,
721724
_("Continuing in %0.1f seconds, "
722725
"assuming that you meant '%s'."),
723726
(float)cfg.autocorrect/10.0, assumed);
724727
sleep_millisec(cfg.autocorrect * 100);
725728
}
726-
return assumed;
729+
730+
goto out;
727731
}
728732

729733
fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
@@ -738,7 +742,13 @@ const char *help_unknown_cmd(const char *cmd)
738742
fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
739743
}
740744

741-
exit(1);
745+
out:
746+
cmdnames_release(&cfg.aliases);
747+
cmdnames_release(&main_cmds);
748+
cmdnames_release(&other_cmds);
749+
if (!assumed)
750+
exit(1);
751+
return assumed;
742752
}
743753

744754
void get_version_info(struct strbuf *buf, int show_build_options)

0 commit comments

Comments
 (0)