diff options
author | Elijah Newren <newren@gmail.com> | 2021-01-24 07:01:10 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2021-01-24 08:30:06 +0100 |
commit | cf8937acdedc80e636587f5fc2f495ea38bd5fe0 (patch) | |
tree | 341d785060fb62d6be8746a8b959ddd4488fb806 /merge-ort.c | |
parent | Merge branch 'en/ort-directory-rename' into en/merge-ort-perf (diff) | |
download | git-cf8937acdedc80e636587f5fc2f495ea38bd5fe0.tar.xz git-cf8937acdedc80e636587f5fc2f495ea38bd5fe0.zip |
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.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/merge-ort.c b/merge-ort.c index 05c6b2e0dc..b5845ff6e9 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 */ |