grep: fix a "path_list" memory leak

Free the "path_list" used in builtin/grep.c, it was declared as STRING_LIST_INIT_NODUP, let's change it to a STRING_LIST_INIT_DUP since an early user in cmd_grep() appends a string passed via parse-options.c to it, which needs to be duplicated. Let's then convert the remaining callers to use string_list_append_nodup() instead, allowing us to free the list. This makes all the tests in t7811-grep-open.sh pass, 6/10 would fail before this change. The only remaining failure would have been due to a stray "git checkout" (which still leaks memory). In this case we can use a "git reset --hard" instead, so let's do that, and move the test_when_finished() above the code that would modify the relevant file. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Oct 22, 2021 at 10:55 UTC b202e51b15401207667261f2cb384e6faa6ed5c3
2 files changed +7 -5
builtin/grep.c
+5 -4
@@ -401,7 +401,7 @@ static void append_path(struct grep_opt *opt, const void *data, size_t len)
401
402 if (len == 1 && *(const char *)data == '\0')
403 return;
404 - string_list_append(path_list, xstrndup(data, len));
404 + string_list_append_nodup(path_list, xstrndup(data, len));
405 }
406
407 static void run_pager(struct grep_opt *opt, const char *prefix)
@@ -839,7 +839,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
839 struct grep_opt opt;
840 struct object_array list = OBJECT_ARRAY_INIT;
841 struct pathspec pathspec;
842 - struct string_list path_list = STRING_LIST_INIT_NODUP;
842 + struct string_list path_list = STRING_LIST_INIT_DUP;
843 int i;
844 int dummy;
845 int use_index = 1;
@@ -1159,8 +1159,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1159 strbuf_addf(&buf, "+/%s%s",
1160 strcmp("less", pager) ? "" : "*",
1161 opt.pattern_list->pattern);
1162 - string_list_append(&path_list,
1163 - strbuf_detach(&buf, NULL));
1162 + string_list_append_nodup(&path_list,
1163 + strbuf_detach(&buf, NULL));
1164 }
1165 }
1166
@@ -1195,6 +1195,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1195 if (hit && show_in_pager)
1196 run_pager(&opt, prefix);
1197 clear_pathspec(&pathspec);
1198 + string_list_clear(&path_list, 0);
1199 free_grep_patterns(&opt);
1200 object_array_clear(&list);
1201 free_repos();
t/t7811-grep-open.sh
+2 -1
@@ -3,6 +3,7 @@
3 test_description='git grep --open-files-in-pager
4 '
5
6 +TEST_PASSES_SANITIZE_LEAK=true
7 . ./test-lib.sh
8 . "$TEST_DIRECTORY"/lib-pager.sh
9 unset PAGER GIT_PAGER
@@ -114,8 +115,8 @@ test_expect_success 'modified file' '
115 unrelated
116 EOF
117
118 + test_when_finished "git reset --hard" &&
119 echo "enum grep_pat_token" >unrelated &&
118 - test_when_finished "git checkout HEAD unrelated" &&
120 GIT_PAGER=./less git grep -F -O "enum grep_pat_token" >out &&
121 test_cmp expect actual &&
122 test_must_be_empty out