builtin/format-patch: fix various trivial memory leaks

There are various memory leaks hit by git-format-patch(1). Basically all of them are trivial, except that un-setting `diffopt.no_free` requires us to unset the `diffopt.file` because we manually close it already. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 14, 2024 at 08:52 UTC 1bc158e7509851d9cb007273c9f75a238f295d2e
2 files changed +11 -3
builtin/log.c
+10 -3
@@ -1827,12 +1827,14 @@ static struct commit *get_base_commit(const struct format_config *cfg,
1827 if (die_on_failure) {
1828 die(_("failed to find exact merge base"));
1829 } else {
1830 + free_commit_list(merge_base);
1831 free(rev);
1832 return NULL;
1833 }
1834 }
1835
1836 rev[i] = merge_base->item;
1837 + free_commit_list(merge_base);
1838 }
1839
1840 if (rev_nr % 2)
@@ -2023,6 +2025,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
2025 const char *rfc = NULL;
2026 int creation_factor = -1;
2027 const char *signature = git_version_string;
2028 + char *signature_to_free = NULL;
2029 char *signature_file_arg = NULL;
2030 struct keep_callback_data keep_callback_data = {
2031 .cfg = &cfg,
@@ -2443,7 +2446,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
2446
2447 if (strbuf_read_file(&buf, signature_file, 128) < 0)
2448 die_errno(_("unable to read signature file '%s'"), signature_file);
2446 - signature = strbuf_detach(&buf, NULL);
2449 + signature = signature_to_free = strbuf_detach(&buf, NULL);
2450 } else if (cfg.signature) {
2451 signature = cfg.signature;
2452 }
@@ -2548,12 +2551,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
2551 else
2552 print_signature(signature, rev.diffopt.file);
2553 }
2551 - if (output_directory)
2554 + if (output_directory) {
2555 fclose(rev.diffopt.file);
2556 + rev.diffopt.file = NULL;
2557 + }
2558 }
2559 stop_progress(&progress);
2560 free(list);
2556 - free(branch_name);
2561 if (ignore_if_in_upstream)
2562 free_patch_ids(&ids);
2563
@@ -2565,11 +2569,14 @@ done:
2569 strbuf_release(&rdiff_title);
2570 free(description_file);
2571 free(signature_file_arg);
2572 + free(signature_to_free);
2573 + free(branch_name);
2574 free(to_free);
2575 free(rev.message_id);
2576 if (rev.ref_message_ids)
2577 string_list_clear(rev.ref_message_ids, 0);
2578 free(rev.ref_message_ids);
2579 + rev.diffopt.no_free = 0;
2580 release_revisions(&rev);
2581 format_config_release(&cfg);
2582 return 0;
t/t4014-format-patch.sh
+1
@@ -8,6 +8,7 @@ test_description='various format-patch tests'
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-terminal.sh
14