reduce_heads: fix memory leaks
We currently have seven callers of `reduce_heads(foo)`. Six of them do not use the original list `foo` again, and actually, all six of those end up leaking it. Introduce and use `reduce_heads_replace(&foo)` as a leak-free version of `foo = reduce_heads(foo)` to fix several of these. Fix the remaining leaks using `free_commit_list()`. While we're here, document `reduce_heads()` and mark it as `extern`. Signed-off-by: Martin Ågren <martin.agren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Martin Ågren committed
Nov 7, 2017 at 21:39 UTC
4da72644b768b0491110a8ba0aa84d32b6bde41c
7 files changed
+35
-6
builtin/commit.c
+1
-1
@@ -1728,7 +1728,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1728
allow_fast_forward = 0;
1729
}
1730
if (allow_fast_forward)
1731
- parents = reduce_heads(parents);
1731
+ reduce_heads_replace(&parents);
1732
} else {
1733
if (!reflog_msg)
1734
reflog_msg = (whence == FROM_CHERRY_PICK)
builtin/fmt-merge-msg.c
+1
-1
@@ -571,7 +571,7 @@ static void find_merge_parents(struct merge_parents *result,
571
head_commit = lookup_commit(head);
572
if (head_commit)
573
commit_list_insert(head_commit, &parents);
574
- parents = reduce_heads(parents);
574
+ reduce_heads_replace(&parents);
575
576
while (parents) {
577
struct commit *cmit = pop_commit(&parents);
builtin/merge-base.c
+4
-2
@@ -57,7 +57,7 @@ static int handle_independent(int count, const char **args)
57
for (i = count - 1; i >= 0; i--)
58
commit_list_insert(get_commit_reference(args[i]), &revs);
59
60
- revs = reduce_heads(revs);
60
+ reduce_heads_replace(&revs);
61
62
if (!revs)
63
return 1;
@@ -78,7 +78,9 @@ static int handle_octopus(int count, const char **args, int show_all)
78
for (i = count - 1; i >= 0; i--)
79
commit_list_insert(get_commit_reference(args[i]), &revs);
80
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);
84
85
if (!result)
86
return 1;
builtin/merge.c
+1
@@ -999,6 +999,7 @@ static struct commit_list *reduce_parents(struct commit *head_commit,
999
1000
/* Find what parents to record by checking independent ones. */
1001
parents = reduce_heads(remoteheads);
1002
+ free_commit_list(remoteheads);
1003
1004
remoteheads = NULL;
1005
remotes = &remoteheads;
builtin/pull.c
+4
-1
@@ -745,12 +745,15 @@ static int get_octopus_merge_base(struct object_id *merge_base,
745
if (!is_null_oid(fork_point))
746
commit_list_insert(lookup_commit_reference(fork_point), &revs);
747
748
- result = reduce_heads(get_octopus_merge_bases(revs));
748
+ result = get_octopus_merge_bases(revs);
749
free_commit_list(revs);
750
+ reduce_heads_replace(&result);
751
+
752
if (!result)
753
return 1;
754
755
oidcpy(merge_base, &result->item->object.oid);
756
+ free_commit_list(result);
757
return 0;
758
}
759
commit.c
+7
@@ -1090,6 +1090,13 @@ struct commit_list *reduce_heads(struct commit_list *heads)
1090
return result;
1091
}
1092
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
+
1100
static const char gpg_sig_header[] = "gpgsig";
1101
static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
1102
commit.h
+17
-1
@@ -313,7 +313,23 @@ extern int interactive_add(int argc, const char **argv, const char *prefix, int
313
extern int run_add_interactive(const char *revision, const char *patch_mode,
314
const struct pathspec *pathspec);
315
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);
333
334
struct commit_extra_header {
335
struct commit_extra_header *next;