From 0c52cf8e00f65bb198800a08caaadc95eaf4419a Mon Sep 17 00:00:00 2001 From: Ævar Arnfjörð Bjarmason Date: Wed, 13 Oct 2021 15:23:54 +0200 Subject: sequencer: add a "goto cleanup" to do_reset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure code that's mostly added in 9055e401dd6 (sequencer: introduce new commands to reset the revision, 2018-04-25) to avoid code duplication, and to make freeing other resources easier in a subsequent commit. It's safe to initialize "tree_desc" to be zero'd out in order to unconditionally free desc.buffer, it won't be initialized on the first couple of "goto"'s. There are three earlier "return"'s in this function which should probably be made to use this new "cleanup" too, per [1] it looks like they're leaving behind stale locks. But let's not try to fix every potential bug here now, I'm just trying to narrowly plug a memory leak. 1. https://lore.kernel.org/git/CABPp-BH=3DP-dXRCphY53-3eZd1TU8h5GY_M12nnbEGm-UYB9Q@mail.gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- sequencer.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 64b1f2e681..36e6a3cd22 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3644,7 +3644,7 @@ static int do_reset(struct repository *r, struct strbuf ref_name = STRBUF_INIT; struct object_id oid; struct lock_file lock = LOCK_INIT; - struct tree_desc desc; + struct tree_desc desc = { 0 }; struct tree *tree; struct unpack_trees_options unpack_tree_opts; int ret = 0; @@ -3678,10 +3678,8 @@ static int do_reset(struct repository *r, strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name); if (get_oid(ref_name.buf, &oid) && get_oid(ref_name.buf + strlen("refs/rewritten/"), &oid)) { - error(_("could not read '%s'"), ref_name.buf); - rollback_lock_file(&lock); - strbuf_release(&ref_name); - return -1; + ret = error(_("could not read '%s'"), ref_name.buf); + goto cleanup; } } @@ -3696,24 +3694,18 @@ static int do_reset(struct repository *r, init_checkout_metadata(&unpack_tree_opts.meta, name, &oid, NULL); if (repo_read_index_unmerged(r)) { - rollback_lock_file(&lock); - strbuf_release(&ref_name); - return error_resolve_conflict(_(action_name(opts))); + ret = error_resolve_conflict(_(action_name(opts))); + goto cleanup; } if (!fill_tree_descriptor(r, &desc, &oid)) { - error(_("failed to find tree of %s"), oid_to_hex(&oid)); - rollback_lock_file(&lock); - free((void *)desc.buffer); - strbuf_release(&ref_name); - return -1; + ret = error(_("failed to find tree of %s"), oid_to_hex(&oid)); + goto cleanup; } if (unpack_trees(1, &desc, &unpack_tree_opts)) { - rollback_lock_file(&lock); - free((void *)desc.buffer); - strbuf_release(&ref_name); - return -1; + ret = -1; + goto cleanup; } tree = parse_tree_indirect(&oid); @@ -3721,13 +3713,15 @@ static int do_reset(struct repository *r, if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) ret = error(_("could not write index")); - free((void *)desc.buffer); if (!ret) ret = update_ref(reflog_message(opts, "reset", "'%.*s'", len, name), "HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR); - +cleanup: + free((void *)desc.buffer); + if (ret < 0) + rollback_lock_file(&lock); strbuf_release(&ref_name); return ret; } -- cgit v1.3 From 6e658547d35515da6ba55d285d6699b7f04cb939 Mon Sep 17 00:00:00 2001 From: Ævar Arnfjörð Bjarmason Date: Wed, 13 Oct 2021 15:23:55 +0200 Subject: sequencer: fix a memory leak in do_reset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a memory leak introduced in 9055e401dd6 (sequencer: introduce new commands to reset the revision, 2018-04-25), which called setup_unpack_trees_porcelain() without a corresponding call to clear_unpack_trees_porcelain(). This introduces a change in behavior in that we now start calling clear_unpack_trees_porcelain() even without having called the setup_unpack_trees_porcelain(). That's OK, that clear function, like most others, will accept a zero'd out struct. This inches us closer to passing various tests in "t34*.sh" (e.g. "t3434-rebase-i18n.sh"), but because they have so many other memory leaks in revisions.c this doesn't make any test file or even a single test pass. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sequencer.c') diff --git a/sequencer.c b/sequencer.c index 36e6a3cd22..e88c4b00c3 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3646,7 +3646,7 @@ static int do_reset(struct repository *r, struct lock_file lock = LOCK_INIT; struct tree_desc desc = { 0 }; struct tree *tree; - struct unpack_trees_options unpack_tree_opts; + struct unpack_trees_options unpack_tree_opts = { 0 }; int ret = 0; if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) @@ -3683,7 +3683,6 @@ static int do_reset(struct repository *r, } } - memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts)); setup_unpack_trees_porcelain(&unpack_tree_opts, "reset"); unpack_tree_opts.head_idx = 1; unpack_tree_opts.src_index = r->index; @@ -3723,6 +3722,7 @@ cleanup: if (ret < 0) rollback_lock_file(&lock); strbuf_release(&ref_name); + clear_unpack_trees_porcelain(&unpack_tree_opts); return ret; } -- cgit v1.3