]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/merge: fix leaking `struct cmdnames` in `get_strategy()`
authorPatrick Steinhardt <ps@pks.im>
Tue, 11 Jun 2024 09:21:06 +0000 (11:21 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 Jun 2024 20:15:07 +0000 (13:15 -0700)
In "builtin/merge.c" we use the helper infrastructure to figure out what
merge strategies there are. We never free contents of the `cmdnames`
structures though and thus leak their memory.

Fix this by exposing the already existing `clean_cmdnames()` function to
release their memory. As this name isn't quite idiomatic, rename it to
`cmdnames_release()` while at it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/merge.c
help.c
help.h
t/t7606-merge-custom.sh

index 50b0c87a95f0e8ad7ceed355aabc6e7c7b7b6bc5..682c6ed868e8fb95c69d00ddc8c7883450e212da 100644 (file)
@@ -164,7 +164,7 @@ static struct strategy *get_strategy(const char *name)
 {
        int i;
        struct strategy *ret;
-       static struct cmdnames main_cmds, other_cmds;
+       static struct cmdnames main_cmds = {0}, other_cmds = {0};
        static int loaded;
        char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
 
@@ -182,10 +182,9 @@ static struct strategy *get_strategy(const char *name)
                        return &all_strategy[i];
 
        if (!loaded) {
-               struct cmdnames not_strategies;
+               struct cmdnames not_strategies = {0};
                loaded = 1;
 
-               memset(&not_strategies, 0, sizeof(struct cmdnames));
                load_command_list("git-merge-", &main_cmds, &other_cmds);
                for (i = 0; i < main_cmds.cnt; i++) {
                        int j, found = 0;
@@ -197,6 +196,8 @@ static struct strategy *get_strategy(const char *name)
                                add_cmdname(&not_strategies, ent->name, ent->len);
                }
                exclude_cmds(&main_cmds, &not_strategies);
+
+               cmdnames_release(&not_strategies);
        }
        if (!is_in_cmdlist(&main_cmds, name) && !is_in_cmdlist(&other_cmds, name)) {
                fprintf(stderr, _("Could not find merge strategy '%s'.\n"), name);
@@ -216,6 +217,9 @@ static struct strategy *get_strategy(const char *name)
        CALLOC_ARRAY(ret, 1);
        ret->name = xstrdup(name);
        ret->attr = NO_TRIVIAL;
+
+       cmdnames_release(&main_cmds);
+       cmdnames_release(&other_cmds);
        return ret;
 }
 
diff --git a/help.c b/help.c
index 1d057aa6073eef2d5b83640986b6eab564130a2f..3686285ca3d3a9b9a492be461f924fae22f53694 100644 (file)
--- a/help.c
+++ b/help.c
@@ -157,7 +157,7 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len)
        cmds->names[cmds->cnt++] = ent;
 }
 
-static void clean_cmdnames(struct cmdnames *cmds)
+void cmdnames_release(struct cmdnames *cmds)
 {
        int i;
        for (i = 0; i < cmds->cnt; ++i)
@@ -359,8 +359,8 @@ void list_all_main_cmds(struct string_list *list)
        for (i = 0; i < main_cmds.cnt; i++)
                string_list_append(list, main_cmds.names[i]->name);
 
-       clean_cmdnames(&main_cmds);
-       clean_cmdnames(&other_cmds);
+       cmdnames_release(&main_cmds);
+       cmdnames_release(&other_cmds);
 }
 
 void list_all_other_cmds(struct string_list *list)
@@ -375,8 +375,8 @@ void list_all_other_cmds(struct string_list *list)
        for (i = 0; i < other_cmds.cnt; i++)
                string_list_append(list, other_cmds.names[i]->name);
 
-       clean_cmdnames(&main_cmds);
-       clean_cmdnames(&other_cmds);
+       cmdnames_release(&main_cmds);
+       cmdnames_release(&other_cmds);
 }
 
 void list_cmds_by_category(struct string_list *list,
@@ -689,7 +689,7 @@ const char *help_unknown_cmd(const char *cmd)
        if (autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) {
                const char *assumed = main_cmds.names[0]->name;
                main_cmds.names[0] = NULL;
-               clean_cmdnames(&main_cmds);
+               cmdnames_release(&main_cmds);
                fprintf_ln(stderr,
                           _("WARNING: You called a Git command named '%s', "
                             "which does not exist."),
diff --git a/help.h b/help.h
index af073a7a0263e7bdacf6dd01f13235b2a655f360..e716ee27ea174c4dfc3b941619bf361972894212 100644 (file)
--- a/help.h
+++ b/help.h
@@ -13,6 +13,8 @@ struct cmdnames {
        } **names;
 };
 
+void cmdnames_release(struct cmdnames *cmds);
+
 static inline void mput_char(char c, unsigned int num)
 {
        while (num--)
index 81fb7c474c14c1d615be9de76e2bd2a032fefac8..135cb2308565337afb25fbef9730972b7bac09f0 100755 (executable)
@@ -14,6 +14,7 @@ Testing a custom strategy.
 * (tag: c0) c0
 "
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up custom strategy' '