From: "Kevin Backhouse via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Kevin Backhouse <kevinbackhouse@github.com>
Subject: [PATCH v2 0/2] This fixes a minor memory leak (detected by LeakSanitizer) in git merge
Date: Thu, 24 Aug 2023 14:12:43 +0000 [thread overview]
Message-ID: <pull.1577.v2.git.1692886365.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1577.git.1692389061490.gitgitgadget@gmail.com>
Hi Junio,
Thank you for your comments. As you suggested, I have added similar fixes in
merge-recursive.c and updated the commit message. I have also added a test.
Thanks,
Kev
Kevin Backhouse (2):
Regression test for https://github.com/gitgitgadget/git/pull/1577
Fix minor memory leak found by LeakSanitizer.
merge-ort-wrappers.c | 4 +++-
merge-ort.c | 4 +++-
merge-recursive.c | 32 ++++++++++++++++++++++----------
t/t9904-merge-leak.sh | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 68 insertions(+), 12 deletions(-)
create mode 100755 t/t9904-merge-leak.sh
base-commit: f9972720e9a405e4f6924a7cde0ed5880687f4d0
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1577%2Fkevinbackhouse%2Ffree-merge-bases-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1577/kevinbackhouse/free-merge-bases-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1577
Range-diff vs v1:
-: ----------- > 1: f940104a781 Regression test for https://github.com/gitgitgadget/git/pull/1577
1: 64b00e4448d ! 2: 353e1960b44 This fixes a minor memory leak (detected by LeakSanitizer) in git merge.
@@ Metadata
Author: Kevin Backhouse <kevinbackhouse@github.com>
## Commit message ##
- This fixes a minor memory leak (detected by LeakSanitizer) in git merge.
+ Fix minor memory leak found by LeakSanitizer.
- To reproduce (with an ASAN build):
+ The callers of merge_recursive() and merge_ort_recursive() expects the
+ commit list passed in as the merge_bases parameter to be fully
+ consumed by the function and does not free it when the function
+ returns. In normal cases, the commit list does get consumed, but when
+ the function returns early upon encountering an error, it forgets to
+ clean it up.
- ```
- mkdir test
- cd test
- git init
- echo x > x.txt
- git add .
- git commit -m "WIP"
- git checkout -b dev
- echo y > x.txt
- git add .
- git commit -m "WIP"
- git checkout main
- echo z > x.txt
- git add .
- git commit -m "WIP"
- echo a > x.txt
- git add .
- git merge dev
- ```
-
- The fix is to call free_commit_list(merge_bases) when an error occurs.
+ Fix this by freeing the list in the code paths for error returns.
Signed-off-by: Kevin Backhouse <kevinbackhouse@github.com>
@@ merge-ort.c: static void merge_ort_internal(struct merge_options *opt,
opt->branch1 = saved_b1;
opt->branch2 = saved_b2;
opt->priv->call_depth--;
+
+ ## merge-recursive.c ##
+@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
+ opt->branch1 = "Temporary merge branch 1";
+ opt->branch2 = "Temporary merge branch 2";
+ if (merge_recursive_internal(opt, merged_merge_bases, iter->item,
+- NULL, &merged_merge_bases) < 0)
+- return -1;
++ NULL, &merged_merge_bases) < 0) {
++ clean = -1;
++ goto out;
++ }
+ opt->branch1 = saved_b1;
+ opt->branch2 = saved_b2;
+ opt->priv->call_depth--;
+
+- if (!merged_merge_bases)
+- return err(opt, _("merge returned no commit"));
++ if (!merged_merge_bases) {
++ clean = err(opt, _("merge returned no commit"));
++ goto out;
++ }
+ }
+
+ /*
+@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
+ repo_get_commit_tree(opt->repo,
+ merged_merge_bases),
+ &result_tree);
++
++out:
+ strbuf_release(&merge_base_abbrev);
+ opt->ancestor = NULL; /* avoid accidental re-use of opt->ancestor */
++ free_commit_list(merge_bases);
+ if (clean < 0) {
+ flush_output(opt);
+ return clean;
+@@ merge-recursive.c: static int merge_start(struct merge_options *opt, struct tree *head)
+ assert(!opt->record_conflict_msgs_as_headers);
+ assert(!opt->msg_header_prefix);
+
++ CALLOC_ARRAY(opt->priv, 1);
++ string_list_init_dup(&opt->priv->df_conflict_file_set);
++
+ /* Sanity check on repo state; index must match head */
+ if (repo_index_has_changes(opt->repo, head, &sb)) {
+ err(opt, _("Your local changes to the following files would be overwritten by merge:\n %s"),
+@@ merge-recursive.c: static int merge_start(struct merge_options *opt, struct tree *head)
+ return -1;
+ }
+
+- CALLOC_ARRAY(opt->priv, 1);
+- string_list_init_dup(&opt->priv->df_conflict_file_set);
+ return 0;
+ }
+
+ static void merge_finalize(struct merge_options *opt)
+ {
+ flush_output(opt);
+- if (!opt->priv->call_depth && opt->buffer_output < 2)
+- strbuf_release(&opt->obuf);
++ strbuf_release(&opt->obuf);
+ if (show(opt, 2))
+ diff_warn_rename_limit("merge.renamelimit",
+ opt->priv->needed_rename_limit, 0);
+@@ merge-recursive.c: int merge_trees(struct merge_options *opt,
+
+ assert(opt->ancestor != NULL);
+
+- if (merge_start(opt, head))
++ if (merge_start(opt, head)) {
++ merge_finalize(opt);
+ return -1;
++ }
+ clean = merge_trees_internal(opt, head, merge, merge_base, &ignored);
+ merge_finalize(opt);
+
+@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
+ prepare_repo_settings(opt->repo);
+ opt->repo->settings.command_requires_full_index = 1;
+
+- if (merge_start(opt, repo_get_commit_tree(opt->repo, h1)))
++ if (merge_start(opt, repo_get_commit_tree(opt->repo, h1))) {
++ free_commit_list(merge_bases);
++ merge_finalize(opt);
+ return -1;
++ }
+ clean = merge_recursive_internal(opt, h1, h2, merge_bases, result);
+ merge_finalize(opt);
+
--
gitgitgadget
next prev parent reply other threads:[~2023-08-24 14:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-18 20:04 [PATCH] This fixes a minor memory leak (detected by LeakSanitizer) in git merge Kevin Backhouse via GitGitGadget
2023-08-18 21:41 ` Junio C Hamano
2023-09-12 15:06 ` Elijah Newren
2023-08-24 14:12 ` Kevin Backhouse via GitGitGadget [this message]
2023-08-24 14:12 ` [PATCH v2 1/2] Regression test for https://github.com/gitgitgadget/git/pull/1577 Kevin Backhouse via GitGitGadget
2023-08-24 15:11 ` Junio C Hamano
2023-08-24 14:12 ` [PATCH v2 2/2] Fix minor memory leak found by LeakSanitizer Kevin Backhouse via GitGitGadget
2023-08-24 15:56 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1577.v2.git.1692886365.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=kevinbackhouse@github.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).