@matheusbsbs / matheus-bagliano / commits / cdf690e53b
Fork 0

remote: make match_refs() copy src ref before assigning to peer_ref

In some instances, match_refs() sets the peer_ref field of refs in the dst list such that it points to a ref in the src list. This prevents callers from freeing both the src and dst lists, as doing so would cause a double-free since free_refs() frees the peer_ref. As well, the following configuration causes two refs in the dst list to have the same peer_ref, which can also lead to a double-free: push = refs/heads/master:refs/heads/backup push = refs/heads/master:refs/heads/master Existing callers of match_heads() call it only once and then terminate, w/o ever bothering to free the src or dst lists, so this is not currently a problem. This patch modifies match_refs() to first copy any refs it plucks from the src list before assigning them as a peer_ref. This allows builtin-remote, a future caller, to free the src and dst lists. Signed-off-by: Jay Soffian <jaysoffian@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jay Soffian committed Feb 25, 2009 at 03:32 UTC cdf690e53b5f5af1ca8679b3f3e47ea198692c18
1 file changed +5 -2
remote.c
+5 -2
@@ -936,6 +936,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
936 struct refspec *rs)
937 {
938 struct ref *matched_src, *matched_dst;
939 + int copy_src;
940
941 const char *dst_value = rs->dst;
942 char *dst_guess;
@@ -946,6 +947,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
947 matched_src = matched_dst = NULL;
948 switch (count_refspec_match(rs->src, src, &matched_src)) {
949 case 1:
950 + copy_src = 1;
951 break;
952 case 0:
953 /* The source could be in the get_sha1() format
@@ -955,6 +957,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
957 matched_src = try_explicit_object_name(rs->src);
958 if (!matched_src)
959 return error("src refspec %s does not match any.", rs->src);
960 + copy_src = 0;
961 break;
962 default:
963 return error("src refspec %s matches more than one.", rs->src);
@@ -1000,7 +1003,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
1003 return error("dst ref %s receives from more than one src.",
1004 matched_dst->name);
1005 else {
1003 - matched_dst->peer_ref = matched_src;
1006 + matched_dst->peer_ref = copy_src ? copy_ref(matched_src) : matched_src;
1007 matched_dst->force = rs->force;
1008 }
1009 return 0;
@@ -1108,7 +1111,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
1111 dst_peer = make_linked_ref(dst_name, dst_tail);
1112 hashcpy(dst_peer->new_sha1, src->new_sha1);
1113 }
1111 - dst_peer->peer_ref = src;
1114 + dst_peer->peer_ref = copy_ref(src);
1115 dst_peer->force = pat->force;
1116 free_name:
1117 free(dst_name);