Subject: [PATCH 2/5] remote.c: don't pass copies of refspecs to add_{fetch,push}_refspec()

From: SZEDER Gábor <[email-masked]>
Date: Fri, 16 Jun 2017 21:28:34 +0200

Currently neither add_fetch_refspec() nor add_push_refspec() duplicate
the refspecs before appending them to an array of refspecs, therefore
all their callers pass them copies of refspecs.  Soon we won't store
refspecs as strings, therefore passing duplicated strings to these
functions will not be necessary.

Perform the copying inside these functions and modify their callers to
either not pass duplicates or free() them to avoid leaks.

Signed-off-by: SZEDER Gábor <[email-masked]>
---
 builtin/clone.c |  3 +--
 remote.c        | 21 ++++++++++++++-------
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 869e093ff..5b72d853f 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1054,8 +1054,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	remote = remote_get(option_origin);
 	strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix,
 		    branch_top.buf);
-	add_and_parse_fetch_refspec(remote,
-				    strbuf_detach(&default_refspec, NULL));
+	add_and_parse_fetch_refspec(remote, default_refspec.buf);
 
 	transport = transport_get(remote, remote->url[0]);
 	transport_set_verbosity(transport, option_verbosity, option_progress);
diff --git a/remote.c b/remote.c
index a021decee..d23518afd 100644
--- a/remote.c
+++ b/remote.c
@@ -91,7 +91,7 @@ static void add_push_refspec(struct remote *remote, const char *ref)
 	ALLOC_GROW(remote->push_refspec,
 		   remote->push_refspec_nr + 1,
 		   remote->push_refspec_alloc);
-	remote->push_refspec[remote->push_refspec_nr++] = ref;
+	remote->push_refspec[remote->push_refspec_nr++] = strdup(ref);
 }
 
 static void add_fetch_refspec(struct remote *remote, const char *ref)
@@ -99,7 +99,7 @@ static void add_fetch_refspec(struct remote *remote, const char *ref)
 	ALLOC_GROW(remote->fetch_refspec,
 		   remote->fetch_refspec_nr + 1,
 		   remote->fetch_refspec_alloc);
-	remote->fetch_refspec[remote->fetch_refspec_nr++] = ref;
+	remote->fetch_refspec[remote->fetch_refspec_nr++] = strdup(ref);
 }
 
 static void add_url(struct remote *remote, const char *url)
@@ -265,9 +265,9 @@ static void read_remotes_file(struct remote *remote)
 		if (skip_prefix(buf.buf, "URL:", &v))
 			add_url_alias(remote, xstrdup(skip_spaces(v)));
 		else if (skip_prefix(buf.buf, "Push:", &v))
-			add_push_refspec(remote, xstrdup(skip_spaces(v)));
+			add_push_refspec(remote, skip_spaces(v));
 		else if (skip_prefix(buf.buf, "Pull:", &v))
-			add_fetch_refspec(remote, xstrdup(skip_spaces(v)));
+			add_fetch_refspec(remote, skip_spaces(v));
 	}
 	strbuf_release(&buf);
 	fclose(f);
@@ -306,15 +306,20 @@ static void read_branches_file(struct remote *remote)
 		frag = "master";
 
 	add_url_alias(remote, strbuf_detach(&buf, NULL));
-	add_fetch_refspec(remote, xstrfmt("refs/heads/%s:refs/heads/%s",
-					  frag, remote->name));
+
+	strbuf_addf(&buf, "refs/heads/%s:refs/heads/%s", frag, remote->name);
+	add_fetch_refspec(remote, buf.buf);
+	strbuf_reset(&buf);
 
 	/*
 	 * Cogito compatible push: push current HEAD to remote #branch
 	 * (master if missing)
 	 */
-	add_push_refspec(remote, xstrfmt("HEAD:refs/heads/%s", frag));
+	strbuf_addf(&buf, "HEAD:refs/heads/%s", frag);
+	add_push_refspec(remote, buf.buf);
 	remote->fetch_tags = 1; /* always auto-follow */
+
+	strbuf_release(&buf);
 }
 
 static int handle_config(const char *key, const char *value, void *cb)
@@ -398,11 +403,13 @@ static int handle_config(const char *key, const char *value, void *cb)
 		if (git_config_string(&v, key, value))
 			return -1;
 		add_push_refspec(remote, v);
+		free((char*)v);
 	} else if (!strcmp(subkey, "fetch")) {
 		const char *v;
 		if (git_config_string(&v, key, value))
 			return -1;
 		add_fetch_refspec(remote, v);
+		free((char*)v);
 	} else if (!strcmp(subkey, "receivepack")) {
 		const char *v;
 		if (git_config_string(&v, key, value))
-- 
2.13.1.505.g7cc9fcafb