Skip to content

Commit

Permalink
remote: make copy_ref() perform a deep copy
Browse files Browse the repository at this point in the history
To ensure that copied refs can always be freed w/o causing a
double-free, make copy_ref() perform a deep copy.

Also have copy_ref() return NULL if asked to copy NULL to simplify
things for the caller.

Background: currently copy_ref() performs a shallow copy. This is fine
for current callers who never free the result and/or only copy refs
which contain NULL pointers. But copy_ref() is about to gain a new
caller (guess_remote_head()) which copies refs where peer_ref is not
NULL and the caller of guess_remote_head() will want to free the result.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jay Soffian authored and Junio C Hamano committed Feb 27, 2009
1 parent 6cb4e6c commit 7b3db09
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,10 +779,18 @@ struct ref *alloc_ref(const char *name)

static struct ref *copy_ref(const struct ref *ref)
{
struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);
memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1);
ret->next = NULL;
return ret;
struct ref *cpy;
size_t len;
if (!ref)
return NULL;
len = strlen(ref->name);
cpy = xmalloc(sizeof(struct ref) + len + 1);
memcpy(cpy, ref, sizeof(struct ref) + len + 1);
cpy->next = NULL;
cpy->symref = ref->symref ? xstrdup(ref->symref) : NULL;
cpy->remote_status = ref->remote_status ? xstrdup(ref->remote_status) : NULL;
cpy->peer_ref = copy_ref(ref->peer_ref);
return cpy;
}

struct ref *copy_ref_list(const struct ref *ref)
Expand All @@ -801,6 +809,7 @@ static void free_ref(struct ref *ref)
{
if (!ref)
return;
free_ref(ref->peer_ref);
free(ref->remote_status);
free(ref->symref);
free(ref);
Expand All @@ -811,7 +820,6 @@ void free_refs(struct ref *ref)
struct ref *next;
while (ref) {
next = ref->next;
free(ref->peer_ref);
free_ref(ref);
ref = next;
}
Expand Down

0 comments on commit 7b3db09

Please sign in to comment.