git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 07a/21] remote: make copy_ref() perform a deep copy

From
Jay Soffian <jaysoffian@gmail.com>
Date
Feb 27, 2009, 19:10 UTC
Message-ID
<45e13cde37f6da8e6c379b5deea81b00148b4355.1235759631.git.jaysoffian@gmail.com>
In-Reply-To
<cover.1235759631.git.jaysoffian@gmail.com>

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>
---
This is a new patch, which should come after 07/21 in the original
series - http://article.gmane.org/gmane.comp.version-control.git/111394
 remote.c |   18 +++++++++++++-----
 1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/remote.c b/remote.c
index aed760e..22203ea 100644
--- a/remote.c
+++ b/remote.c
@@ -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;
 	}
-- 
1.6.2.rc1.309.g5f417
Previous: Jay SoffianNext: Jay Soffian
Message 2 of 5 in “git remote: set-head and new show output (UPDATED)”
  1. 0/3 git remote: set-head and new show output (UPDATED)Jay Soffian, Feb 27, 2009
  2. remote: make copy_ref() perform a deep copyJay Soffian, Feb 27, 2009
  3. 08/21 remote: let guess_remote_head() optionally return all matchesJay Soffian, Feb 27, 2009
  4. 19/21 remote: make guess_remote_head() use exact HEAD lookup if it is availableJay Soffian, Feb 27, 2009
  5. Jeff KingFeb 28, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.