Skip to content

Commit 80a0e0f

Browse files
committed
Merge branch 'ma/reduce-heads-leakfix' into maint
Leak fixes. * ma/reduce-heads-leakfix: reduce_heads: fix memory leaks builtin/merge-base: free commit lists
2 parents 03e8004 + 4da7264 commit 80a0e0f

File tree

7 files changed

+52
-23
lines changed

7 files changed

+52
-23
lines changed

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1730,7 +1730,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
17301730
allow_fast_forward = 0;
17311731
}
17321732
if (allow_fast_forward)
1733-
parents = reduce_heads(parents);
1733+
reduce_heads_replace(&parents);
17341734
} else {
17351735
if (!reflog_msg)
17361736
reflog_msg = (whence == FROM_CHERRY_PICK)

builtin/fmt-merge-msg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ static void find_merge_parents(struct merge_parents *result,
571571
head_commit = lookup_commit(head);
572572
if (head_commit)
573573
commit_list_insert(head_commit, &parents);
574-
parents = reduce_heads(parents);
574+
reduce_heads_replace(&parents);
575575

576576
while (parents) {
577577
struct commit *cmit = pop_commit(&parents);

builtin/merge-base.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@
99

1010
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
1111
{
12-
struct commit_list *result;
12+
struct commit_list *result, *r;
1313

1414
result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1);
1515

1616
if (!result)
1717
return 1;
1818

19-
while (result) {
20-
printf("%s\n", oid_to_hex(&result->item->object.oid));
19+
for (r = result; r; r = r->next) {
20+
printf("%s\n", oid_to_hex(&r->item->object.oid));
2121
if (!show_all)
22-
return 0;
23-
result = result->next;
22+
break;
2423
}
2524

25+
free_commit_list(result);
2626
return 0;
2727
}
2828

@@ -51,45 +51,47 @@ static struct commit *get_commit_reference(const char *arg)
5151

5252
static int handle_independent(int count, const char **args)
5353
{
54-
struct commit_list *revs = NULL;
55-
struct commit_list *result;
54+
struct commit_list *revs = NULL, *rev;
5655
int i;
5756

5857
for (i = count - 1; i >= 0; i--)
5958
commit_list_insert(get_commit_reference(args[i]), &revs);
6059

61-
result = reduce_heads(revs);
62-
if (!result)
60+
reduce_heads_replace(&revs);
61+
62+
if (!revs)
6363
return 1;
6464

65-
while (result) {
66-
printf("%s\n", oid_to_hex(&result->item->object.oid));
67-
result = result->next;
68-
}
65+
for (rev = revs; rev; rev = rev->next)
66+
printf("%s\n", oid_to_hex(&rev->item->object.oid));
67+
68+
free_commit_list(revs);
6969
return 0;
7070
}
7171

7272
static int handle_octopus(int count, const char **args, int show_all)
7373
{
7474
struct commit_list *revs = NULL;
75-
struct commit_list *result;
75+
struct commit_list *result, *rev;
7676
int i;
7777

7878
for (i = count - 1; i >= 0; i--)
7979
commit_list_insert(get_commit_reference(args[i]), &revs);
8080

81-
result = reduce_heads(get_octopus_merge_bases(revs));
81+
result = get_octopus_merge_bases(revs);
82+
free_commit_list(revs);
83+
reduce_heads_replace(&result);
8284

8385
if (!result)
8486
return 1;
8587

86-
while (result) {
87-
printf("%s\n", oid_to_hex(&result->item->object.oid));
88+
for (rev = result; rev; rev = rev->next) {
89+
printf("%s\n", oid_to_hex(&rev->item->object.oid));
8890
if (!show_all)
89-
return 0;
90-
result = result->next;
91+
break;
9192
}
9293

94+
free_commit_list(result);
9395
return 0;
9496
}
9597

builtin/merge.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,7 @@ static struct commit_list *reduce_parents(struct commit *head_commit,
999999

10001000
/* Find what parents to record by checking independent ones. */
10011001
parents = reduce_heads(remoteheads);
1002+
free_commit_list(remoteheads);
10021003

10031004
remoteheads = NULL;
10041005
remotes = &remoteheads;

builtin/pull.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,12 +745,15 @@ static int get_octopus_merge_base(struct object_id *merge_base,
745745
if (!is_null_oid(fork_point))
746746
commit_list_insert(lookup_commit_reference(fork_point), &revs);
747747

748-
result = reduce_heads(get_octopus_merge_bases(revs));
748+
result = get_octopus_merge_bases(revs);
749749
free_commit_list(revs);
750+
reduce_heads_replace(&result);
751+
750752
if (!result)
751753
return 1;
752754

753755
oidcpy(merge_base, &result->item->object.oid);
756+
free_commit_list(result);
754757
return 0;
755758
}
756759

commit.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,13 @@ struct commit_list *reduce_heads(struct commit_list *heads)
10901090
return result;
10911091
}
10921092

1093+
void reduce_heads_replace(struct commit_list **heads)
1094+
{
1095+
struct commit_list *result = reduce_heads(*heads);
1096+
free_commit_list(*heads);
1097+
*heads = result;
1098+
}
1099+
10931100
static const char gpg_sig_header[] = "gpgsig";
10941101
static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
10951102

commit.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,23 @@ extern int interactive_add(int argc, const char **argv, const char *prefix, int
313313
extern int run_add_interactive(const char *revision, const char *patch_mode,
314314
const struct pathspec *pathspec);
315315

316-
struct commit_list *reduce_heads(struct commit_list *heads);
316+
/*
317+
* Takes a list of commits and returns a new list where those
318+
* have been removed that can be reached from other commits in
319+
* the list. It is useful for, e.g., reducing the commits
320+
* randomly thrown at the git-merge command and removing
321+
* redundant commits that the user shouldn't have given to it.
322+
*
323+
* This function destroys the STALE bit of the commit objects'
324+
* flags.
325+
*/
326+
extern struct commit_list *reduce_heads(struct commit_list *heads);
327+
328+
/*
329+
* Like `reduce_heads()`, except it replaces the list. Use this
330+
* instead of `foo = reduce_heads(foo);` to avoid memory leaks.
331+
*/
332+
extern void reduce_heads_replace(struct commit_list **heads);
317333

318334
struct commit_extra_header {
319335
struct commit_extra_header *next;

0 commit comments

Comments
 (0)