Skip to content

Commit a232de5

Browse files
committed
Merge branch 'ab/sequencer-unleak'
Plug leaks in sequencer subsystem and its users. * ab/sequencer-unleak: commit.c: free() revs.commit in get_fork_point() builtin/rebase.c: free() "options.strategy_opts" sequencer.c: always free() the "msgbuf" in do_pick_commit() builtin/rebase.c: fix "options.onto_name" leak builtin/revert.c: move free-ing of "revs" to replay_opts_release() sequencer API users: fix get_replay_opts() leaks sequencer.c: split up sequencer_remove_state() rebase: use "cleanup" pattern in do_interactive_rebase()
2 parents 4f59836 + 0c10ed1 commit a232de5

23 files changed

+61
-33
lines changed

builtin/rebase.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,24 +254,20 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name,
254254

255255
static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
256256
{
257-
int ret;
257+
int ret = -1;
258258
char *revisions = NULL, *shortrevisions = NULL;
259259
struct strvec make_script_args = STRVEC_INIT;
260260
struct todo_list todo_list = TODO_LIST_INIT;
261261
struct replay_opts replay = get_replay_opts(opts);
262262

263263
if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head->object.oid,
264264
&revisions, &shortrevisions))
265-
return -1;
265+
goto cleanup;
266266

267267
if (init_basic_state(&replay,
268268
opts->head_name ? opts->head_name : "detached HEAD",
269-
opts->onto, &opts->orig_head->object.oid)) {
270-
free(revisions);
271-
free(shortrevisions);
272-
273-
return -1;
274-
}
269+
opts->onto, &opts->orig_head->object.oid))
270+
goto cleanup;
275271

276272
if (!opts->upstream && opts->squash_onto)
277273
write_file(path_squash_onto(), "%s\n",
@@ -300,6 +296,8 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
300296
opts->autosquash, opts->update_refs, &todo_list);
301297
}
302298

299+
cleanup:
300+
replay_opts_release(&replay);
303301
free(revisions);
304302
free(shortrevisions);
305303
todo_list_release(&todo_list);
@@ -341,6 +339,7 @@ static int run_sequencer_rebase(struct rebase_options *opts)
341339
struct replay_opts replay_opts = get_replay_opts(opts);
342340

343341
ret = sequencer_continue(the_repository, &replay_opts);
342+
replay_opts_release(&replay_opts);
344343
break;
345344
}
346345
case ACTION_EDIT_TODO:
@@ -556,6 +555,7 @@ static int finish_rebase(struct rebase_options *opts)
556555

557556
replay.action = REPLAY_INTERACTIVE_REBASE;
558557
ret = sequencer_remove_state(&replay);
558+
replay_opts_release(&replay);
559559
} else {
560560
strbuf_addstr(&dir, opts->state_dir);
561561
if (remove_dir_recursively(&dir, 0))
@@ -1039,6 +1039,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
10391039
struct string_list strategy_options = STRING_LIST_INIT_NODUP;
10401040
struct object_id squash_onto;
10411041
char *squash_onto_name = NULL;
1042+
char *keep_base_onto_name = NULL;
10421043
int reschedule_failed_exec = -1;
10431044
int allow_preemptive_ff = 1;
10441045
int preserve_merges_selected = 0;
@@ -1327,6 +1328,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
13271328

13281329
replay.action = REPLAY_INTERACTIVE_REBASE;
13291330
ret = sequencer_remove_state(&replay);
1331+
replay_opts_release(&replay);
13301332
} else {
13311333
strbuf_reset(&buf);
13321334
strbuf_addstr(&buf, options.state_dir);
@@ -1674,7 +1676,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
16741676
strbuf_addstr(&buf, options.upstream_name);
16751677
strbuf_addstr(&buf, "...");
16761678
strbuf_addstr(&buf, branch_name);
1677-
options.onto_name = xstrdup(buf.buf);
1679+
options.onto_name = keep_base_onto_name = xstrdup(buf.buf);
16781680
} else if (!options.onto_name)
16791681
options.onto_name = options.upstream_name;
16801682
if (strstr(options.onto_name, "...")) {
@@ -1848,8 +1850,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
18481850
free(options.gpg_sign_opt);
18491851
string_list_clear(&options.exec, 0);
18501852
free(options.strategy);
1853+
free(options.strategy_opts);
18511854
strbuf_release(&options.git_format_patch_opt);
18521855
free(squash_onto_name);
1856+
free(keep_base_onto_name);
18531857
string_list_clear(&strategy_options, 0);
18541858
return !!ret;
18551859
}

builtin/revert.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,7 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
248248
res = run_sequencer(argc, argv, &opts);
249249
if (res < 0)
250250
die(_("revert failed"));
251-
if (opts.revs)
252-
release_revisions(opts.revs);
253-
free(opts.revs);
251+
replay_opts_release(&opts);
254252
return res;
255253
}
256254

@@ -262,10 +260,8 @@ int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
262260
opts.action = REPLAY_PICK;
263261
sequencer_init_config(&opts);
264262
res = run_sequencer(argc, argv, &opts);
265-
if (opts.revs)
266-
release_revisions(opts.revs);
267-
free(opts.revs);
268263
if (res < 0)
269264
die(_("cherry-pick failed"));
265+
replay_opts_release(&opts);
270266
return res;
271267
}

commit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
10331033
ret = bases->item;
10341034

10351035
cleanup_return:
1036+
free(revs.commit);
10361037
free_commit_list(bases);
10371038
free(full_refname);
10381039
return ret;

sequencer.c

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,25 @@ static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
351351
return buf.buf;
352352
}
353353

354+
void replay_opts_release(struct replay_opts *opts)
355+
{
356+
free(opts->gpg_sign);
357+
free(opts->reflog_action);
358+
free(opts->default_strategy);
359+
free(opts->strategy);
360+
for (size_t i = 0; i < opts->xopts_nr; i++)
361+
free(opts->xopts[i]);
362+
free(opts->xopts);
363+
strbuf_release(&opts->current_fixups);
364+
if (opts->revs)
365+
release_revisions(opts->revs);
366+
free(opts->revs);
367+
}
368+
354369
int sequencer_remove_state(struct replay_opts *opts)
355370
{
356371
struct strbuf buf = STRBUF_INIT;
357-
int i, ret = 0;
372+
int ret = 0;
358373

359374
if (is_rebase_i(opts) &&
360375
strbuf_read_file(&buf, rebase_path_refs_to_delete(), 0) > 0) {
@@ -373,15 +388,6 @@ int sequencer_remove_state(struct replay_opts *opts)
373388
}
374389
}
375390

376-
free(opts->gpg_sign);
377-
free(opts->reflog_action);
378-
free(opts->default_strategy);
379-
free(opts->strategy);
380-
for (i = 0; i < opts->xopts_nr; i++)
381-
free(opts->xopts[i]);
382-
free(opts->xopts);
383-
strbuf_release(&opts->current_fixups);
384-
385391
strbuf_reset(&buf);
386392
strbuf_addstr(&buf, get_dir(opts));
387393
if (remove_dir_recursively(&buf, 0))
@@ -2271,8 +2277,10 @@ static int do_pick_commit(struct repository *r,
22712277
reword = 1;
22722278
else if (is_fixup(command)) {
22732279
if (update_squash_messages(r, command, commit,
2274-
opts, item->flags))
2275-
return -1;
2280+
opts, item->flags)) {
2281+
res = -1;
2282+
goto leave;
2283+
}
22762284
flags |= AMEND_MSG;
22772285
if (!final_fixup)
22782286
msg_file = rebase_path_squash_msg();
@@ -2282,9 +2290,11 @@ static int do_pick_commit(struct repository *r,
22822290
} else {
22832291
const char *dest = git_path_squash_msg(r);
22842292
unlink(dest);
2285-
if (copy_file(dest, rebase_path_squash_msg(), 0666))
2286-
return error(_("could not rename '%s' to '%s'"),
2287-
rebase_path_squash_msg(), dest);
2293+
if (copy_file(dest, rebase_path_squash_msg(), 0666)) {
2294+
res = error(_("could not rename '%s' to '%s'"),
2295+
rebase_path_squash_msg(), dest);
2296+
goto leave;
2297+
}
22882298
unlink(git_path_merge_msg(r));
22892299
msg_file = dest;
22902300
flags |= EDIT_MSG;
@@ -2322,7 +2332,6 @@ static int do_pick_commit(struct repository *r,
23222332
free_commit_list(common);
23232333
free_commit_list(remotes);
23242334
}
2325-
strbuf_release(&msgbuf);
23262335

23272336
/*
23282337
* If the merge was clean or if it failed due to conflict, we write
@@ -2396,6 +2405,7 @@ static int do_pick_commit(struct repository *r,
23962405
leave:
23972406
free_message(commit, &msg);
23982407
free(author);
2408+
strbuf_release(&msgbuf);
23992409
update_abort_safety_file();
24002410

24012411
return res;

sequencer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ int sequencer_pick_revisions(struct repository *repo,
158158
int sequencer_continue(struct repository *repo, struct replay_opts *opts);
159159
int sequencer_rollback(struct repository *repo, struct replay_opts *opts);
160160
int sequencer_skip(struct repository *repo, struct replay_opts *opts);
161+
void replay_opts_release(struct replay_opts *opts);
161162
int sequencer_remove_state(struct replay_opts *opts);
162163

163164
#define TODO_LIST_KEEP_EMPTY (1U << 0)

t/t3405-rebase-malformed.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='rebase should handle arbitrary git message'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910
. "$TEST_DIRECTORY"/lib-rebase.sh
1011

t/t3412-rebase-root.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Tests if git rebase --root --onto <newparent> can rebase the root commit.
77
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
88
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
99

10+
TEST_PASSES_SANITIZE_LEAK=true
1011
. ./test-lib.sh
1112

1213
log_with_names () {

t/t3416-rebase-onto-threedots.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='git rebase --onto A...B'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910
. "$TEST_DIRECTORY/lib-rebase.sh"
1011

t/t3419-rebase-patch-id.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='git rebase - test patch id computation'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910

1011
scramble () {

t/t3423-rebase-reword.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
test_description='git rebase interactive with rewording'
44

5+
TEST_PASSES_SANITIZE_LEAK=true
56
. ./test-lib.sh
67

78
. "$TEST_DIRECTORY"/lib-rebase.sh

0 commit comments

Comments
 (0)