builtin/commit: fix leaking cleanup config

The cleanup string set by the config is leaking when it is being overridden by an option. Fix this by tracking these via two separate variables such that we can free the old value. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 5, 2024 at 07:17 UTC 6ef9f77a15fcb198b59840a9ed3a8f88da5ad53d
2 files changed +13 -5
builtin/commit.c
+12 -5
@@ -135,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT;
135 * is specified explicitly.
136 */
137 static enum commit_msg_cleanup_mode cleanup_mode;
138 -static char *cleanup_arg;
138 +static char *cleanup_config;
139
140 static enum commit_whence whence;
141 static int use_editor = 1, include_status = 1;
@@ -1387,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
1387 if (0 <= edit_flag)
1388 use_editor = edit_flag;
1389
1390 - cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
1391 -
1390 handle_untracked_files_arg(s);
1391
1392 if (all && argc > 0)
@@ -1636,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v,
1634 include_status = git_config_bool(k, v);
1635 return 0;
1636 }
1639 - if (!strcmp(k, "commit.cleanup"))
1640 - return git_config_string(&cleanup_arg, k, v);
1637 + if (!strcmp(k, "commit.cleanup")) {
1638 + FREE_AND_NULL(cleanup_config);
1639 + return git_config_string(&cleanup_config, k, v);
1640 + }
1641 if (!strcmp(k, "commit.gpgsign")) {
1642 sign_commit = git_config_bool(k, v) ? "" : NULL;
1643 return 0;
@@ -1658,6 +1658,7 @@ int cmd_commit(int argc,
1658 struct repository *repo UNUSED)
1659 {
1660 static struct wt_status s;
1661 + static const char *cleanup_arg = NULL;
1662 static struct option builtin_commit_options[] = {
1663 OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
1664 OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
@@ -1757,6 +1758,12 @@ int cmd_commit(int argc,
1758 if (verbose == -1)
1759 verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
1760
1761 + if (cleanup_arg) {
1762 + free(cleanup_config);
1763 + cleanup_config = xstrdup(cleanup_arg);
1764 + }
1765 + cleanup_mode = get_cleanup_mode(cleanup_config, use_editor);
1766 +
1767 if (dry_run)
1768 return dry_run_commit(argv, prefix, current_head, &s);
1769 index_file = prepare_index(argv, prefix, current_head, 0);
t/t7502-commit-porcelain.sh
+1
@@ -5,6 +5,7 @@ test_description='git commit porcelain-ish'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 +TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
10
11 commit_msg_is () {