diff: fix leaking orderfile option

The `orderfile` diff option is being assigned via `OPT_FILENAME()`, which assigns an allocated string to the variable. We never free it though, causing a memory leak. Change the type of the string to `char *` and free it to plug the leak. This also requires us to use `xstrdup()` to assign the global config to it in case it is set. This leak is being hit in t7621, but plugging it alone does not make the test suite pass. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Sep 26, 2024 at 13:46 UTC 76c7e708bbd6b19856d1ffa58f720e8da0c9eb0f
3 files changed +7 -5
combine-diff.c
+1 -2
@@ -1393,9 +1393,8 @@ static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
1393 {
1394 struct combine_diff_path *paths = NULL;
1395 int i, num_parent = parents->nr;
1396 -
1396 int output_format = opt->output_format;
1398 - const char *orderfile = opt->orderfile;
1397 + char *orderfile = opt->orderfile;
1398
1399 opt->output_format = DIFF_FORMAT_NO_OUTPUT;
1400 /* tell diff_tree to emit paths in sorted (=tree) order */
diff.c
+5 -2
@@ -441,8 +441,10 @@ int git_diff_ui_config(const char *var, const char *value,
441 }
442 if (!strcmp(var, "diff.wordregex"))
443 return git_config_string(&diff_word_regex_cfg, var, value);
444 - if (!strcmp(var, "diff.orderfile"))
444 + if (!strcmp(var, "diff.orderfile")) {
445 + FREE_AND_NULL(diff_order_file_cfg);
446 return git_config_pathname(&diff_order_file_cfg, var, value);
447 + }
448
449 if (!strcmp(var, "diff.ignoresubmodules")) {
450 if (!value)
@@ -4775,7 +4777,7 @@ void repo_diff_setup(struct repository *r, struct diff_options *options)
4777 if (diff_indent_heuristic)
4778 DIFF_XDL_SET(options, INDENT_HEURISTIC);
4779
4778 - options->orderfile = diff_order_file_cfg;
4780 + options->orderfile = xstrdup_or_null(diff_order_file_cfg);
4781
4782 if (!options->flags.ignore_submodule_set)
4783 options->flags.ignore_untracked_in_submodules = 1;
@@ -6727,6 +6729,7 @@ void diff_free(struct diff_options *options)
6729 FREE_AND_NULL(options->objfind);
6730 }
6731
6732 + FREE_AND_NULL(options->orderfile);
6733 for (size_t i = 0; i < options->anchors_nr; i++)
6734 free(options->anchors[i]);
6735 FREE_AND_NULL(options->anchors);
diff.h
+1 -1
@@ -235,7 +235,7 @@ enum diff_submodule_format {
235 * diffcore library with.
236 */
237 struct diff_options {
238 - const char *orderfile;
238 + char *orderfile;
239
240 /*
241 * "--rotate-to=<file>" would start showing at <file> and when