Skip to content

Commit a452d0f

Browse files
Martin Ågrengitster
authored andcommitted
builtin/merge-base: free commit lists
In several functions, we iterate through a commit list by assigning `result = result->next`. As a consequence, we lose the original pointer and eventually leak the list. Rewrite the loops so that we keep the original pointers, then call `free_commit_list()`. Various alternatives were considered: 1) Use `UNLEAK(result)` before the loop. Simple change, but not very pretty. These would definitely be new lows among our usages of UNLEAK. 2) Use `pop_commit()` when looping. Slightly less simple change, but it feels slightly preferable to first display the list, then free it. 3) As in this patch, but with `UNLEAK()` instead of freeing. We'd still go through all the trouble of refactoring the loop, and because it's not super-obvious that we're about to exit, let's just free the lists -- it probably doesn't affect the runtime much. In `handle_independent()` we can drop `result` while we're here and reuse the `revs`-variable instead. That matches several other users of `reduce_heads()`. The memory-leak that this hides will be addressed in the next commit. Signed-off-by: Martin Ågren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cb5918a commit a452d0f

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

builtin/merge-base.c

Lines changed: 18 additions & 18 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,28 +51,28 @@ 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+
revs = reduce_heads(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--)
@@ -83,13 +83,13 @@ static int handle_octopus(int count, const char **args, int show_all)
8383
if (!result)
8484
return 1;
8585

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

92+
free_commit_list(result);
9393
return 0;
9494
}
9595

0 commit comments

Comments
 (0)