Skip to content

Commit 34968e5

Browse files
pks-tgitster
authored andcommitted
builtin/replay: plug leaking advance_name variable
The `advance_name` variable can either contain a static string when parsed via the `--advance` command line option or it may be an allocated string when set via `determine_replay_mode()`. Because we cannot be sure whether it is allocated or not we just didn't free it at all, resulting in a memory leak. Split up the variables such that we can track the static and allocated strings separately and then free the allocated one to fix the memory leak. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ad57f14 commit 34968e5

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

builtin/replay.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info,
151151

152152
static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
153153
const char *onto_name,
154-
const char **advance_name,
154+
char **advance_name,
155155
struct commit **onto,
156156
struct strset **update_refs)
157157
{
@@ -174,6 +174,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
174174
*onto = peel_committish(*advance_name);
175175
if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name),
176176
&oid, &fullname, 0) == 1) {
177+
free(*advance_name);
177178
*advance_name = fullname;
178179
} else {
179180
die(_("argument to --advance must be a reference"));
@@ -197,6 +198,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
197198
if (negative_refs_complete) {
198199
struct hashmap_iter iter;
199200
struct strmap_entry *entry;
201+
const char *last_key = NULL;
200202

201203
if (rinfo.negative_refexprs == 0)
202204
die(_("all positive revisions given must be references"));
@@ -208,8 +210,11 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
208210
/* Only one entry, but we have to loop to get it */
209211
strset_for_each_entry(&rinfo.negative_refs,
210212
&iter, entry) {
211-
*advance_name = entry->key;
213+
last_key = entry->key;
212214
}
215+
216+
free(*advance_name);
217+
*advance_name = xstrdup_or_null(last_key);
213218
} else { /* positive_refs_complete */
214219
if (rinfo.negative_refexprs > 1)
215220
die(_("cannot implicitly determine correct base for --onto"));
@@ -271,7 +276,8 @@ static struct commit *pick_regular_commit(struct commit *pickme,
271276

272277
int cmd_replay(int argc, const char **argv, const char *prefix)
273278
{
274-
const char *advance_name = NULL;
279+
const char *advance_name_opt = NULL;
280+
char *advance_name = NULL;
275281
struct commit *onto = NULL;
276282
const char *onto_name = NULL;
277283
int contained = 0;
@@ -292,7 +298,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
292298
NULL
293299
};
294300
struct option replay_options[] = {
295-
OPT_STRING(0, "advance", &advance_name,
301+
OPT_STRING(0, "advance", &advance_name_opt,
296302
N_("branch"),
297303
N_("make replay advance given branch")),
298304
OPT_STRING(0, "onto", &onto_name,
@@ -306,14 +312,15 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
306312
argc = parse_options(argc, argv, prefix, replay_options, replay_usage,
307313
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT);
308314

309-
if (!onto_name && !advance_name) {
315+
if (!onto_name && !advance_name_opt) {
310316
error(_("option --onto or --advance is mandatory"));
311317
usage_with_options(replay_usage, replay_options);
312318
}
313319

314-
if (advance_name && contained)
320+
if (advance_name_opt && contained)
315321
die(_("options '%s' and '%s' cannot be used together"),
316322
"--advance", "--contained");
323+
advance_name = xstrdup_or_null(advance_name_opt);
317324

318325
repo_init_revisions(the_repository, &revs, prefix);
319326

@@ -441,6 +448,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
441448

442449
cleanup:
443450
release_revisions(&revs);
451+
free(advance_name);
444452

445453
/* Return */
446454
if (ret < 0)

t/t3650-replay-basics.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='basic git replay tests'
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
GIT_AUTHOR_NAME=author@name

0 commit comments

Comments
 (0)