builtin/stash: fix various trivial memory leaks

There are multiple trivial memory leaks in git-stash(1). Fix those. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 1, 2024 at 12:40 UTC 2e875b6cb408351c07919efb024ee1b52e0a3ac3
6 files changed +22 -2
builtin/stash.c
+16 -2
@@ -1521,6 +1521,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
1521 struct strbuf patch = STRBUF_INIT;
1522 struct strbuf stash_msg_buf = STRBUF_INIT;
1523 struct strbuf untracked_files = STRBUF_INIT;
1524 + struct strbuf out = STRBUF_INIT;
1525
1526 if (patch_mode && keep_index == -1)
1527 keep_index = 1;
@@ -1626,7 +1627,6 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
1627 struct child_process cp_add = CHILD_PROCESS_INIT;
1628 struct child_process cp_diff = CHILD_PROCESS_INIT;
1629 struct child_process cp_apply = CHILD_PROCESS_INIT;
1629 - struct strbuf out = STRBUF_INIT;
1630
1631 cp_add.git_cmd = 1;
1632 strvec_push(&cp_add.args, "add");
@@ -1718,6 +1718,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
1718
1719 done:
1720 strbuf_release(&patch);
1721 + strbuf_release(&out);
1722 free_stash_info(&info);
1723 strbuf_release(&stash_msg_buf);
1724 strbuf_release(&untracked_files);
@@ -1869,6 +1870,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
1870 OPT_SUBCOMMAND_F("save", &fn, save_stash, PARSE_OPT_NOCOMPLETE),
1871 OPT_END()
1872 };
1873 + const char **args_copy;
1874 + int ret;
1875
1876 git_config(git_stash_config, NULL);
1877
@@ -1892,5 +1895,16 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
1895 /* Assume 'stash push' */
1896 strvec_push(&args, "push");
1897 strvec_pushv(&args, argv);
1895 - return !!push_stash(args.nr, args.v, prefix, 1);
1898 +
1899 + /*
1900 + * `push_stash()` ends up modifying the array, which causes memory
1901 + * leaks if we didn't copy the array here.
1902 + */
1903 + DUP_ARRAY(args_copy, args.v, args.nr);
1904 +
1905 + ret = !!push_stash(args.nr, args_copy, prefix, 1);
1906 +
1907 + strvec_clear(&args);
1908 + free(args_copy);
1909 + return ret;
1910 }
t/t2501-cwd-empty.sh
+1
@@ -2,6 +2,7 @@
2
3 test_description='Test handling of the current working directory becoming empty'
4
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7
8 test_expect_success setup '
t/t3903-stash.sh
+1
@@ -8,6 +8,7 @@ test_description='Test git stash'
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 +TEST_PASSES_SANITIZE_LEAK=true
12 . ./test-lib.sh
13 . "$TEST_DIRECTORY"/lib-unique-files.sh
14
t/t3904-stash-patch.sh
+2
@@ -1,6 +1,8 @@
1 #!/bin/sh
2
3 test_description='stash -p'
4 +
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./lib-patch-mode.sh
7
8 test_expect_success 'setup' '
t/t3905-stash-include-untracked.sh
+1
@@ -5,6 +5,7 @@
5
6 test_description='Test git stash --include-untracked'
7
8 +TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
10
11 test_expect_success 'stash save --include-untracked some dirty working directory' '
t/t7064-wtstatus-pv2.sh
+1
@@ -4,6 +4,7 @@ test_description='git status --porcelain=v2
4
5 This test exercises porcelain V2 output for git status.'
6
7 +TEST_PASSES_SANITIZE_LEAK=true
8 . ./test-lib.sh
9
10