Skip to content

Commit

Permalink
clean up name allocation in prepare_revision_walk
Browse files Browse the repository at this point in the history
When we enter prepare_revision_walk, we have zero or more
entries in our "pending" array. We disconnect that array
from the rev_info, and then process each entry:

  1. If the entry is a commit and the --source option is in
     effect, we keep a pointer to the object name.

  2. Otherwise, we re-add the item to the pending list with
     a blank name.

We then throw away the old array by freeing the array
itself, but do not touch the "name" field of each entry. For
any items of type (2), we leak the memory associated with
the name. This commit fixes that by calling object_array_clear,
which handles the cleanup for us.

That breaks (1), though, because it depends on the memory
pointed to by the name to last forever. We can solve that by
making a copy of the name. This is slightly less efficient,
but it shouldn't matter in practice, as we do it only for
the tip commits of the traversal.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Oct 16, 2014
1 parent 46be823 commit 1da1e07
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ static struct commit *handle_commit(struct rev_info *revs,
revs->limited = 1;
}
if (revs->show_source && !commit->util)
commit->util = (void *) name;
commit->util = xstrdup(name);
return commit;
}

Expand Down Expand Up @@ -2656,26 +2656,26 @@ void reset_revision_walk(void)

int prepare_revision_walk(struct rev_info *revs)
{
int nr = revs->pending.nr;
struct object_array_entry *e, *list;
int i;
struct object_array old_pending;
struct commit_list **next = &revs->commits;

e = list = revs->pending.objects;
memcpy(&old_pending, &revs->pending, sizeof(old_pending));
revs->pending.nr = 0;
revs->pending.alloc = 0;
revs->pending.objects = NULL;
while (--nr >= 0) {
for (i = 0; i < old_pending.nr; i++) {
struct object_array_entry *e = old_pending.objects + i;
struct commit *commit = handle_commit(revs, e->item, e->name);
if (commit) {
if (!(commit->object.flags & SEEN)) {
commit->object.flags |= SEEN;
next = commit_list_append(commit, next);
}
}
e++;
}
if (!revs->leak_pending)
free(list);
object_array_clear(&old_pending);

/* Signal whether we need per-parent treesame decoration */
if (revs->simplify_merges ||
Expand Down

0 comments on commit 1da1e07

Please sign in to comment.