]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-ort: fix massive leak
authorElijah Newren <newren@gmail.com>
Sun, 24 Jan 2021 06:01:10 +0000 (22:01 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 24 Jan 2021 07:30:06 +0000 (23:30 -0800)
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>
merge-ort.c

index 05c6b2e0dc86e68419dab3e97cd6e1140670e84d..b5845ff6e93ea48714655114239148544a4eb7ea 100644 (file)
@@ -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 */