@matheusbsbs / matheus-bagliano / commits / 7b3db095d5
Fork 0

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>

Jay Soffian committed Feb 27, 2009 at 14:10 UTC 7b3db095d53d19e08b27114d8706ff3be6693af7
1 file changed +13 -5
remote.c
+13 -5
@@ -779,10 +779,18 @@ struct ref *alloc_ref(const char *name)
779
780 static struct ref *copy_ref(const struct ref *ref)
781 {
782 - struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);
783 - memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1);
784 - ret->next = NULL;
785 - return ret;
782 + struct ref *cpy;
783 + size_t len;
784 + if (!ref)
785 + return NULL;
786 + len = strlen(ref->name);
787 + cpy = xmalloc(sizeof(struct ref) + len + 1);
788 + memcpy(cpy, ref, sizeof(struct ref) + len + 1);
789 + cpy->next = NULL;
790 + cpy->symref = ref->symref ? xstrdup(ref->symref) : NULL;
791 + cpy->remote_status = ref->remote_status ? xstrdup(ref->remote_status) : NULL;
792 + cpy->peer_ref = copy_ref(ref->peer_ref);
793 + return cpy;
794 }
795
796 struct ref *copy_ref_list(const struct ref *ref)
@@ -801,6 +809,7 @@ static void free_ref(struct ref *ref)
809 {
810 if (!ref)
811 return;
812 + free_ref(ref->peer_ref);
813 free(ref->remote_status);
814 free(ref->symref);
815 free(ref);
@@ -811,7 +820,6 @@ void free_refs(struct ref *ref)
820 struct ref *next;
821 while (ref) {
822 next = ref->next;
814 - free(ref->peer_ref);
823 free_ref(ref);
824 ref = next;
825 }