summaryrefslogtreecommitdiff
path: root/merge-ort.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2021-01-24 06:01:10 (GMT)
committerJunio C Hamano <gitster@pobox.com>2021-01-24 07:30:06 (GMT)
commitcf8937acdedc80e636587f5fc2f495ea38bd5fe0 (patch)
tree341d785060fb62d6be8746a8b959ddd4488fb806 /merge-ort.c
parentfe2f4d0031efea524163d63888c010fc6a8201e1 (diff)
downloadgit-cf8937acdedc80e636587f5fc2f495ea38bd5fe0.zip
git-cf8937acdedc80e636587f5fc2f495ea38bd5fe0.tar.gz
git-cf8937acdedc80e636587f5fc2f495ea38bd5fe0.tar.bz2
merge-ort: fix massive leak
When a series of merges was performed (such as for a rebase or series of cherry-picks), only the data structures allocated by the final merge operation were being freed. The problem was that while picking out pieces of merge-ort to upstream, I previously misread a certain section of merge_start() and assumed it was associated with a later optimization. Include that section now, which ensures that if there was a previous merge operation, that we clear out result->priv and then re-use it for opt->priv, and otherwise we allocate opt->priv. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-ort.c')
-rw-r--r--merge-ort.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/merge-ort.c b/merge-ort.c
index 05c6b2e..b5845ff 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -3227,11 +3227,28 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
assert(opt->obuf.len == 0);
assert(opt->priv == NULL);
+ if (result->priv) {
+ opt->priv = result->priv;
+ result->priv = NULL;
+ /*
+ * opt->priv non-NULL means we had results from a previous
+ * run; do a few sanity checks that user didn't mess with
+ * it in an obvious fashion.
+ */
+ assert(opt->priv->call_depth == 0);
+ assert(!opt->priv->toplevel_dir ||
+ 0 == strlen(opt->priv->toplevel_dir));
+ }
/* Default to histogram diff. Actually, just hardcode it...for now. */
opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF);
/* Initialization of opt->priv, our internal merge data */
+ if (opt->priv) {
+ clear_or_reinit_internal_opts(opt->priv, 1);
+ trace2_region_leave("merge", "allocate/init", opt->repo);
+ return;
+ }
opt->priv = xcalloc(1, sizeof(*opt->priv));
/* Initialization of various renames fields */