aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2024-08-14 08:52:36 +0200
committerJunio C Hamano <gitster@pobox.com>2024-08-14 10:08:00 -0700
commit2f07d228c3a1c623526ddf38e609dc45c98fb22e (patch)
tree5a42e332ecdadb3c43471281e34be2a303ec31a1
parentmerge-ort: unconditionally release attributes index (diff)
downloadgit-2f07d228c3a1c623526ddf38e609dc45c98fb22e.tar.gz
git-2f07d228c3a1c623526ddf38e609dc45c98fb22e.zip
sequencer: release todo list on error paths
We're not releasing the `todo_list` in `sequencer_pick_revisions()` when hitting an error path. Restructure the function to have a common exit path such that we can easily clean up the list and thus plug this memory leak. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--sequencer.c66
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh1
2 files changed, 48 insertions, 19 deletions
diff --git a/sequencer.c b/sequencer.c
index cade9b0ca8..ea559c31f1 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -5490,8 +5490,10 @@ int sequencer_pick_revisions(struct repository *r,
int i, res;
assert(opts->revs);
- if (read_and_refresh_cache(r, opts))
- return -1;
+ if (read_and_refresh_cache(r, opts)) {
+ res = -1;
+ goto out;
+ }
for (i = 0; i < opts->revs->pending.nr; i++) {
struct object_id oid;
@@ -5506,11 +5508,14 @@ int sequencer_pick_revisions(struct repository *r,
enum object_type type = oid_object_info(r,
&oid,
NULL);
- return error(_("%s: can't cherry-pick a %s"),
- name, type_name(type));
+ res = error(_("%s: can't cherry-pick a %s"),
+ name, type_name(type));
+ goto out;
}
- } else
- return error(_("%s: bad revision"), name);
+ } else {
+ res = error(_("%s: bad revision"), name);
+ goto out;
+ }
}
/*
@@ -5525,14 +5530,23 @@ int sequencer_pick_revisions(struct repository *r,
opts->revs->no_walk &&
!opts->revs->cmdline.rev->flags) {
struct commit *cmit;
- if (prepare_revision_walk(opts->revs))
- return error(_("revision walk setup failed"));
+
+ if (prepare_revision_walk(opts->revs)) {
+ res = error(_("revision walk setup failed"));
+ goto out;
+ }
+
cmit = get_revision(opts->revs);
- if (!cmit)
- return error(_("empty commit set passed"));
+ if (!cmit) {
+ res = error(_("empty commit set passed"));
+ goto out;
+ }
+
if (get_revision(opts->revs))
BUG("unexpected extra commit from walk");
- return single_pick(r, cmit, opts);
+
+ res = single_pick(r, cmit, opts);
+ goto out;
}
/*
@@ -5542,16 +5556,30 @@ int sequencer_pick_revisions(struct repository *r,
*/
if (walk_revs_populate_todo(&todo_list, opts) ||
- create_seq_dir(r) < 0)
- return -1;
- if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT))
- return error(_("can't revert as initial commit"));
- if (save_head(oid_to_hex(&oid)))
- return -1;
- if (save_opts(opts))
- return -1;
+ create_seq_dir(r) < 0) {
+ res = -1;
+ goto out;
+ }
+
+ if (repo_get_oid(r, "HEAD", &oid) && (opts->action == REPLAY_REVERT)) {
+ res = error(_("can't revert as initial commit"));
+ goto out;
+ }
+
+ if (save_head(oid_to_hex(&oid))) {
+ res = -1;
+ goto out;
+ }
+
+ if (save_opts(opts)) {
+ res = -1;
+ goto out;
+ }
+
update_abort_safety_file();
res = pick_commits(r, &todo_list, opts);
+
+out:
todo_list_release(&todo_list);
return res;
}
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 7eb52b12ed..93c725bac3 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -12,6 +12,7 @@ test_description='Test cherry-pick continuation features
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Repeat first match 10 times