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

[PATCH v2 05/10] use xstrfmt to replace xmalloc + strcpy/strcat

From
Jeff King <peff@peff.net>
Date
Jun 19, 2014, 21:26 UTC
Message-ID
<20140619212656.GE28474@sigill.intra.peff.net>
In-Reply-To
<20140619211659.GA32412@sigill.intra.peff.net>

It's easy to get manual allocation calculations wrong, and the use of strcpy/strcat raise red flags for people looking for buffer overflows (though in this case each site was fine).

It's also shorter to use xstrfmt, and the printf-format tends to be easier for a reader to see what the final string will look like.

Signed-off-by: Jeff King <peff@peff.net>
---
By the way, I think that the tip_name allocation in name_rev leaks
badly, but it's a little tricky to fix (we sometimes hand off ownership
of the variable, and sometimes not). However, this patch does not make
it any worse, and nobody is complaining, so I left it for now.
 builtin/apply.c    | 4 +---
 builtin/fetch.c    | 9 ++-------
 builtin/name-rev.c | 5 +----
 sha1_name.c        | 5 +----
 shell.c            | 6 +-----
 5 files changed, 6 insertions(+), 23 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 9c5724e..b796910 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1281,9 +1281,7 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct
 	 */
 	patch->def_name = git_header_name(line, len);
 	if (patch->def_name && root) {
-		char *s = xmalloc(root_len + strlen(patch->def_name) + 1);
-		strcpy(s, root);
-		strcpy(s + root_len, patch->def_name);
+		char *s = xstrfmt("%s%s", root, patch->def_name);
 		free(patch->def_name);
 		patch->def_name = s;
 	}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 55f457c..40d989f 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1053,16 +1053,11 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
 		refs = xcalloc(argc + 1, sizeof(const char *));
 		for (i = 0; i < argc; i++) {
 			if (!strcmp(argv[i], "tag")) {
-				char *ref;
 				i++;
 				if (i >= argc)
 					die(_("You need to specify a tag name."));
-				ref = xmalloc(strlen(argv[i]) * 2 + 22);
-				strcpy(ref, "refs/tags/");
-				strcat(ref, argv[i]);
-				strcat(ref, ":refs/tags/");
-				strcat(ref, argv[i]);
-				refs[j++] = ref;
+				refs[j++] = xstrfmt("refs/tags/%s:refs/tags/%s",
+						    argv[i], argv[i]);
 			} else
 				refs[j++] = argv[i];
 		}
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index c824d4e..3c8f319 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -33,10 +33,7 @@ static void name_rev(struct commit *commit,
 		return;
 
 	if (deref) {
-		char *new_name = xmalloc(strlen(tip_name)+3);
-		strcpy(new_name, tip_name);
-		strcat(new_name, "^0");
-		tip_name = new_name;
+		tip_name = xstrfmt("%s^0", tip_name);
 
 		if (generation)
 			die("generation: %d, but deref?", generation);
diff --git a/sha1_name.c b/sha1_name.c
index 2b6322f..5e95690 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1252,10 +1252,7 @@ static void diagnose_invalid_sha1_path(const char *prefix,
 		die("Path '%s' exists on disk, but not in '%.*s'.",
 		    filename, object_name_len, object_name);
 	if (errno == ENOENT || errno == ENOTDIR) {
-		char *fullname = xmalloc(strlen(filename)
-					     + strlen(prefix) + 1);
-		strcpy(fullname, prefix);
-		strcat(fullname, filename);
+		char *fullname = xstrfmt("%s%s", prefix, filename);
 
 		if (!get_tree_entry(tree_sha1, fullname,
 				    sha1, &mode)) {
diff --git a/shell.c b/shell.c
index 5c0d47a..ace62e4 100644
--- a/shell.c
+++ b/shell.c
@@ -46,11 +46,7 @@ static int is_valid_cmd_name(const char *cmd)
 
 static char *make_cmd(const char *prog)
 {
-	char *prefix = xmalloc((strlen(prog) + strlen(COMMAND_DIR) + 2));
-	strcpy(prefix, COMMAND_DIR);
-	strcat(prefix, "/");
-	strcat(prefix, prog);
-	return prefix;
+	return xstrfmt("%s/%s", COMMAND_DIR, prog);
 }
 
 static void cd_to_homedir(void)
-- 
2.0.0.566.gfe3e6b2
Previous: Jeff KingNext: Jeff King
Message 11 of 27 in “dropping manual malloc calculations”
  1. 0/2 dropping manual malloc calculationsJeff King, Jun 18, 2014
  2. 1/2 strbuf: add xstrdup_fmt helperJeff King, Jun 18, 2014
  3. Junio C HamanoJun 18, 2014
  4. Jeff KingJun 19, 2014
  5. Junio C HamanoJun 19, 2014
  6. dropping manual malloc calculationsJeff King, Jun 19, 2014
  7. 01/10 strbuf: add xstrfmt helperJeff King, Jun 19, 2014
  8. 02/10 use xstrfmt in favor of manual size calculationsJeff King, Jun 19, 2014
  9. 03/10 use xstrdup instead of xmalloc + strcpyJeff King, Jun 19, 2014
  10. 04/10 use xstrfmt to replace xmalloc + sprintfJeff King, Jun 19, 2014
  11. 05/10 use xstrfmt to replace xmalloc + strcpy/strcatJeff King, Jun 19, 2014
  12. 06/10 setup_git_env: use git_pathdup instead of xmalloc + sprintfJeff King, Jun 19, 2014
  13. Eric SunshineJun 23, 2014
  14. Junio C HamanoJun 23, 2014
  15. Duy NguyenJun 24, 2014
  16. Duy NguyenJun 24, 2014
  17. Jeff KingJun 24, 2014
  18. Duy NguyenJun 25, 2014
  19. Junio C HamanoJun 25, 2014
  20. Jeff KingJun 25, 2014
  21. Junio C HamanoJun 25, 2014
  22. 07/10 sequencer: use argv_array_pushfJeff King, Jun 19, 2014
  23. 08/10 merge: use argv_array when spawning merge strategyJeff King, Jun 19, 2014
  24. 09/10 walker_fetch: fix minor memory leakJeff King, Jun 19, 2014
  25. 10/10 unique_path: fix unlikely heap overflowJeff King, Jun 19, 2014
  26. René ScharfeJun 19, 2014
  27. 2/2 use xstrdup_fmt in favor of manual size calculationsJeff King, Jun 18, 2014

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.