diff options
author | Jay Soffian <jaysoffian@gmail.com> | 2009-02-27 14:10:04 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2009-02-27 15:08:08 -0800 |
commit | 7b3db095d53d19e08b27114d8706ff3be6693af7 (patch) | |
tree | 60231bbfbede85ab1672129b7ca3f375c982a421 /remote.c | |
parent | 6cb4e6cc0f5b2de1998492b0178eeb0f99d4a800 (diff) | |
download | git-7b3db095d53d19e08b27114d8706ff3be6693af7.tar.gz git-7b3db095d53d19e08b27114d8706ff3be6693af7.tar.xz |
remote: make copy_ref() perform a deep copy
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>
Diffstat (limited to 'remote.c')
-rw-r--r-- | remote.c | 18 |
1 files changed, 13 insertions, 5 deletions
@@ -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) @@ -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); @@ -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; } |