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

[PATCH 15/67] convert trivial sprintf / strcpy calls to xsnprintf

From
Jeff King <peff@peff.net>
Date
Sep 15, 2015, 15:36 UTC
Message-ID
<20150915153637.GO29753@sigill.intra.peff.net>
In-Reply-To
<20150915152125.GA27504@sigill.intra.peff.net>

We sometimes sprintf into static buffers when we know that the size of the buffer is large enough to fit the input (either because it's a constant, or because it's numeric input that is bounded in size). Likewise with strcpy of constant strings.

However, these sites make it hard to audit sprintf and strcpy calls for buffer overflows, as a reader has to cross-reference the size of the array with the input. Let's use xsnprintf instead, which communicates to a reader that we don't expect this to overflow (and catches the mistake in case we do).

Signed-off-by: Jeff King <peff@peff.net>
---
These are all pretty trivial; the obvious thing to get wrong is that
"sizeof(buf)" is not the correct length if "buf" is a pointer. I
considered a macro wrapper like:
  #define xsnprintf_array(dst, fmt, ...) \
	xsnprintf(dst, sizeof(dst) + BARF_UNLESS_AN_ARRAY(dst), \
		  fmt, __VA_ARGS__)
but obviously that requires variadic macro support.
 archive-tar.c             |  2 +-
 builtin/gc.c              |  2 +-
 builtin/init-db.c         | 11 ++++++-----
 builtin/ls-tree.c         |  9 +++++----
 builtin/merge-index.c     |  2 +-
 builtin/merge-recursive.c |  2 +-
 builtin/read-tree.c       |  2 +-
 builtin/unpack-file.c     |  2 +-
 compat/mingw.c            |  8 +++++---
 compat/winansi.c          |  2 +-
 connect.c                 |  2 +-
 convert.c                 |  3 ++-
 daemon.c                  |  4 ++--
 diff.c                    | 12 ++++++------
 http-push.c               |  2 +-
 http.c                    |  6 +++---
 ll-merge.c                | 12 ++++++------
 refs.c                    |  8 ++++----
 sideband.c                |  4 ++--
 strbuf.c                  |  4 ++--
 20 files changed, 52 insertions(+), 47 deletions(-)
diff --git a/archive-tar.c b/archive-tar.c
index b6b30bb..d543f93 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -301,7 +301,7 @@ static int write_global_extended_header(struct archiver_args *args)
 	memset(&header, 0, sizeof(header));
 	*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
 	mode = 0100666;
-	strcpy(header.name, "pax_global_header");
+	xsnprintf(header.name, sizeof(header.name), "pax_global_header");
 	prepare_header(args, &header, mode, ext_header.len);
 	write_blocked(&header, sizeof(header));
 	write_blocked(ext_header.buf, ext_header.len);
diff --git a/builtin/gc.c b/builtin/gc.c
index 0ad8d30..57584bc 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -194,7 +194,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
 		return NULL;
 
 	if (gethostname(my_host, sizeof(my_host)))
-		strcpy(my_host, "unknown");
+		xsnprintf(my_host, sizeof(my_host), "unknown");
 
 	pidfile_path = git_pathdup("gc.pid");
 	fd = hold_lock_file_for_update(&lock, pidfile_path,
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 69323e1..e7d0e31 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -262,7 +262,8 @@ static int create_default_files(const char *template_path)
 	}
 
 	/* This forces creation of new config file */
-	sprintf(repo_version_string, "%d", GIT_REPO_VERSION);
+	xsnprintf(repo_version_string, sizeof(repo_version_string),
+		  "%d", GIT_REPO_VERSION);
 	git_config_set("core.repositoryformatversion", repo_version_string);
 
 	path[len] = 0;
@@ -414,13 +415,13 @@ int init_db(const char *template_dir, unsigned int flags)
 		 */
 		if (shared_repository < 0)
 			/* force to the mode value */
-			sprintf(buf, "0%o", -shared_repository);
+			xsnprintf(buf, sizeof(buf), "0%o", -shared_repository);
 		else if (shared_repository == PERM_GROUP)
-			sprintf(buf, "%d", OLD_PERM_GROUP);
+			xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
 		else if (shared_repository == PERM_EVERYBODY)
-			sprintf(buf, "%d", OLD_PERM_EVERYBODY);
+			xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
 		else
-			die("oops");
+			die("BUG: invalid value for shared_repository");
 		git_config_set("core.sharedrepository", buf);
 		git_config_set("receive.denyNonFastforwards", "true");
 	}
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 3b04a0f..0e30d86 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -96,12 +96,13 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base,
 			if (!strcmp(type, blob_type)) {
 				unsigned long size;
 				if (sha1_object_info(sha1, &size) == OBJ_BAD)
-					strcpy(size_text, "BAD");
+					xsnprintf(size_text, sizeof(size_text),
+						  "BAD");
 				else
-					snprintf(size_text, sizeof(size_text),
-						 "%lu", size);
+					xsnprintf(size_text, sizeof(size_text),
+						  "%lu", size);
 			} else
-				strcpy(size_text, "-");
+				xsnprintf(size_text, sizeof(size_text), "-");
 			printf("%06o %s %s %7s\t", mode, type,
 			       find_unique_abbrev(sha1, abbrev),
 			       size_text);
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 1a1eafa..1d66111 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -23,7 +23,7 @@ static int merge_entry(int pos, const char *path)
 			break;
 		found++;
 		strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
-		sprintf(ownbuf[stage], "%o", ce->ce_mode);
+		xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
 		arguments[stage] = hexbuf[stage];
 		arguments[stage + 4] = ownbuf[stage];
 	} while (++pos < active_nr);
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index a90f28f..491efd5 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -14,7 +14,7 @@ static const char *better_branch_name(const char *branch)
 
 	if (strlen(branch) != 40)
 		return branch;
-	sprintf(githead_env, "GITHEAD_%s", branch);
+	xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
 	name = getenv(githead_env);
 	return name ? name : branch;
 }
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 2379e11..8c693e7 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -90,7 +90,7 @@ static int debug_merge(const struct cache_entry * const *stages,
 	debug_stage("index", stages[0], o);
 	for (i = 1; i <= o->merge_size; i++) {
 		char buf[24];
-		sprintf(buf, "ent#%d", i);
+		xsnprintf(buf, sizeof(buf), "ent#%d", i);
 		debug_stage(buf, stages[i], o);
 	}
 	return 0;
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 1920029..6fc6bcd 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -12,7 +12,7 @@ static char *create_temp_file(unsigned char *sha1)
 	if (!buf || type != OBJ_BLOB)
 		die("unable to read blob object %s", sha1_to_hex(sha1));
 
-	strcpy(path, ".merge_file_XXXXXX");
+	xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
 	fd = xmkstemp(path);
 	if (write_in_full(fd, buf, size) != size)
 		die_errno("unable to write temp-file");
diff --git a/compat/mingw.c b/compat/mingw.c
index f74da23..a168800 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2133,9 +2133,11 @@ int uname(struct utsname *buf)
 {
 	DWORD v = GetVersion();
 	memset(buf, 0, sizeof(*buf));
-	strcpy(buf->sysname, "Windows");
-	sprintf(buf->release, "%u.%u", v & 0xff, (v >> 8) & 0xff);
+	xsnprintf(buf->sysname, sizeof(buf->sysname), "Windows");
+	xsnprintf(buf->release, sizeof(buf->release),
+		 "%u.%u", v & 0xff, (v >> 8) & 0xff);
 	/* assuming NT variants only.. */
-	sprintf(buf->version, "%u", (v >> 16) & 0x7fff);
+	xsnprintf(buf->version, sizeof(buf->version),
+		  "%u", (v >> 16) & 0x7fff);
 	return 0;
 }
diff --git a/compat/winansi.c b/compat/winansi.c
index efc5bb3..ceff55b 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -539,7 +539,7 @@ void winansi_init(void)
 		return;
 
 	/* create a named pipe to communicate with the console thread */
-	sprintf(name, "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
+	xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId());
 	hwrite = CreateNamedPipe(name, PIPE_ACCESS_OUTBOUND,
 		PIPE_TYPE_BYTE | PIPE_WAIT, 1, BUFFER_SIZE, 0, 0, NULL);
 	if (hwrite == INVALID_HANDLE_VALUE)
diff --git a/connect.c b/connect.c
index c0144d8..1d5c5e0 100644
--- a/connect.c
+++ b/connect.c
@@ -332,7 +332,7 @@ static const char *ai_name(const struct addrinfo *ai)
 	static char addr[NI_MAXHOST];
 	if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
 			NI_NUMERICHOST) != 0)
-		strcpy(addr, "(unknown)");
+		xsnprintf(addr, sizeof(addr), "(unknown)");
 
 	return addr;
 }
diff --git a/convert.c b/convert.c
index f3bd3e9..814e814 100644
--- a/convert.c
+++ b/convert.c
@@ -1289,7 +1289,8 @@ static struct stream_filter *ident_filter(const unsigned char *sha1)
 {
 	struct ident_filter *ident = xmalloc(sizeof(*ident));
 
-	sprintf(ident->ident, ": %s $", sha1_to_hex(sha1));
+	xsnprintf(ident->ident, sizeof(ident->ident),
+		  ": %s $", sha1_to_hex(sha1));
 	strbuf_init(&ident->left, 0);
 	ident->filter.vtbl = &ident_vtbl;
 	ident->state = 0;
diff --git a/daemon.c b/daemon.c
index f9eb296..5218a3f 100644
--- a/daemon.c
+++ b/daemon.c
@@ -901,7 +901,7 @@ static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
 		inet_ntop(family, &((struct sockaddr_in*)sin)->sin_addr, ip, len);
 		break;
 	default:
-		strcpy(ip, "<unknown>");
+		xsnprintf(ip, sizeof(ip), "<unknown>");
 	}
 	return ip;
 }
@@ -916,7 +916,7 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
 	int gai;
 	long flags;
 
-	sprintf(pbuf, "%d", listen_port);
+	xsnprintf(pbuf, sizeof(pbuf), "%d", listen_port);
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = AF_UNSPEC;
 	hints.ai_socktype = SOCK_STREAM;
diff --git a/diff.c b/diff.c
index 08508f6..788e371 100644
--- a/diff.c
+++ b/diff.c
@@ -2880,7 +2880,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
 	temp->name = get_tempfile_path(&temp->tempfile);
 	strcpy(temp->hex, sha1_to_hex(sha1));
 	temp->hex[40] = 0;
-	sprintf(temp->mode, "%06o", mode);
+	xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
 	strbuf_release(&buf);
 	strbuf_release(&template);
 	free(path_dup);
@@ -2897,8 +2897,8 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
 		 * a '+' entry produces this for file-1.
 		 */
 		temp->name = "/dev/null";
-		strcpy(temp->hex, ".");
-		strcpy(temp->mode, ".");
+		xsnprintf(temp->hex, sizeof(temp->hex), ".");
+		xsnprintf(temp->mode, sizeof(temp->mode), ".");
 		return temp;
 	}
 
@@ -2935,7 +2935,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
 			 * !(one->sha1_valid), as long as
 			 * DIFF_FILE_VALID(one).
 			 */
-			sprintf(temp->mode, "%06o", one->mode);
+			xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode);
 		}
 		return temp;
 	}
@@ -4081,9 +4081,9 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
 	if (abblen < 37) {
 		static char hex[41];
 		if (len < abblen && abblen <= len + 2)
-			sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
+			xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, "..");
 		else
-			sprintf(hex, "%s...", abbrev);
+			xsnprintf(hex, sizeof(hex), "%s...", abbrev);
 		return hex;
 	}
 	return sha1_to_hex(sha1);
diff --git a/http-push.c b/http-push.c
index c98dad2..154e67b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -881,7 +881,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
 	strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped);
 	free(escaped);
 
-	sprintf(timeout_header, "Timeout: Second-%ld", timeout);
+	xsnprintf(timeout_header, sizeof(timeout_header), "Timeout: Second-%ld", timeout);
 	dav_headers = curl_slist_append(dav_headers, timeout_header);
 	dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
 
diff --git a/http.c b/http.c
index 9dce380..7b02259 100644
--- a/http.c
+++ b/http.c
@@ -1104,7 +1104,7 @@ static void write_accept_language(struct strbuf *buf)
 		     decimal_places++, max_q *= 10)
 			;
 
-		sprintf(q_format, ";q=0.%%0%dd", decimal_places);
+		xsnprintf(q_format, sizeof(q_format), ";q=0.%%0%dd", decimal_places);
 
 		strbuf_addstr(buf, "Accept-Language: ");
 
@@ -1601,7 +1601,7 @@ struct http_pack_request *new_http_pack_request(
 			fprintf(stderr,
 				"Resuming fetch of pack %s at byte %ld\n",
 				sha1_to_hex(target->sha1), prev_posn);
-		sprintf(range, "Range: bytes=%ld-", prev_posn);
+		xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
 		preq->range_header = curl_slist_append(NULL, range);
 		curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
 			preq->range_header);
@@ -1761,7 +1761,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
 			fprintf(stderr,
 				"Resuming fetch of object %s at byte %ld\n",
 				hex, prev_posn);
-		sprintf(range, "Range: bytes=%ld-", prev_posn);
+		xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
 		range_header = curl_slist_append(range_header, range);
 		curl_easy_setopt(freq->slot->curl,
 				 CURLOPT_HTTPHEADER, range_header);
diff --git a/ll-merge.c b/ll-merge.c
index fc3c049..56f73b3 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -142,11 +142,11 @@ static struct ll_merge_driver ll_merge_drv[] = {
 	{ "union", "built-in union merge", ll_union_merge },
 };
 
-static void create_temp(mmfile_t *src, char *path)
+static void create_temp(mmfile_t *src, char *path, size_t len)
 {
 	int fd;
 
-	strcpy(path, ".merge_file_XXXXXX");
+	xsnprintf(path, len, ".merge_file_XXXXXX");
 	fd = xmkstemp(path);
 	if (write_in_full(fd, src->ptr, src->size) != src->size)
 		die_errno("unable to write temp-file");
@@ -187,10 +187,10 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 
 	result->ptr = NULL;
 	result->size = 0;
-	create_temp(orig, temp[0]);
-	create_temp(src1, temp[1]);
-	create_temp(src2, temp[2]);
-	sprintf(temp[3], "%d", marker_size);
+	create_temp(orig, temp[0], sizeof(temp[0]));
+	create_temp(src1, temp[1], sizeof(temp[1]));
+	create_temp(src2, temp[2], sizeof(temp[2]));
+	xsnprintf(temp[3], sizeof(temp[3]), "%d", marker_size);
 
 	strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
 
diff --git a/refs.c b/refs.c
index 4e15f60..d5c8b2f 100644
--- a/refs.c
+++ b/refs.c
@@ -3326,10 +3326,10 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
 	msglen = msg ? strlen(msg) : 0;
 	maxlen = strlen(committer) + msglen + 100;
 	logrec = xmalloc(maxlen);
-	len = sprintf(logrec, "%s %s %s\n",
-		      sha1_to_hex(old_sha1),
-		      sha1_to_hex(new_sha1),
-		      committer);
+	len = xsnprintf(logrec, maxlen, "%s %s %s\n",
+			sha1_to_hex(old_sha1),
+			sha1_to_hex(new_sha1),
+			committer);
 	if (msglen)
 		len += copy_msg(logrec + len - 1, msg) - 1;
 
diff --git a/sideband.c b/sideband.c
index 7f9dc22..fde8adc 100644
--- a/sideband.c
+++ b/sideband.c
@@ -137,11 +137,11 @@ ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet
 		if (packet_max - 5 < n)
 			n = packet_max - 5;
 		if (0 <= band) {
-			sprintf(hdr, "%04x", n + 5);
+			xsnprintf(hdr, sizeof(hdr), "%04x", n + 5);
 			hdr[4] = band;
 			write_or_die(fd, hdr, 5);
 		} else {
-			sprintf(hdr, "%04x", n + 4);
+			xsnprintf(hdr, sizeof(hdr), "%04x", n + 4);
 			write_or_die(fd, hdr, 4);
 		}
 		write_or_die(fd, p, n);
diff --git a/strbuf.c b/strbuf.c
index 6c1b577..46a3d20 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -245,8 +245,8 @@ void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size
 	static char prefix2[2];
 
 	if (prefix1[0] != comment_line_char) {
-		sprintf(prefix1, "%c ", comment_line_char);
-		sprintf(prefix2, "%c", comment_line_char);
+		xsnprintf(prefix1, sizeof(prefix1), "%c ", comment_line_char);
+		xsnprintf(prefix2, sizeof(prefix2), "%c", comment_line_char);
 	}
 	add_lines(out, prefix1, prefix2, buf, size);
 }
-- 
2.6.0.rc2.408.ga2926b9
Previous: Jeff KingNext: Ramsay Jones
Message 41 of 154 in “war on sprintf, strcpy, etc”
  1. 0/67 war on sprintf, strcpy, etcJeff King, Sep 15, 2015
  2. 01/67 show-branch: avoid segfault with --reflog of unborn branchJeff King, Sep 15, 2015
  3. 02/67 mailsplit: fix FILE* leak in split_maildirJeff King, Sep 15, 2015
  4. 03/67 archive-tar: fix minor indentation violationJeff King, Sep 15, 2015
  5. 04/67 fsck: don't fsck alternates for connectivity-only checkJeff King, Sep 15, 2015
  6. Johannes SchindelinSep 15, 2015
  7. Junio C HamanoSep 16, 2015
  8. Jeff KingSep 16, 2015
  9. Junio C HamanoSep 16, 2015
  10. Eric SunshineSep 16, 2015
  11. Jeff KingSep 16, 2015
  12. 05/67 add xsnprintf helper functionJeff King, Sep 15, 2015
  13. 06/67 add git_path_buf helper functionJeff King, Sep 15, 2015
  14. 07/67 strbuf: make strbuf_complete_line more genericJeff King, Sep 15, 2015
  15. Eric SunshineSep 16, 2015
  16. Junio C HamanoSep 16, 2015
  17. Jeff KingSep 16, 2015
  18. Eric SunshineSep 16, 2015
  19. 08/67 add reentrant variants of sha1_to_hex and find_unique_abbrevJeff King, Sep 15, 2015
  20. Ramsay JonesSep 15, 2015
  21. Jeff KingSep 15, 2015
  22. Junio C HamanoSep 16, 2015
  23. Johannes SchindelinSep 16, 2015
  24. Jeff KingSep 16, 2015
  25. Junio C HamanoSep 16, 2015
  26. Jeff KingSep 16, 2015
  27. 09/67 fsck: use strbuf to generate alternate directoriesJeff King, Sep 15, 2015
  28. 10/67 mailsplit: make PATH_MAX buffers dynamicJeff King, Sep 15, 2015
  29. Eric SunshineSep 16, 2015
  30. Jeff KingSep 16, 2015
  31. Jeff KingSep 16, 2015
  32. Junio C HamanoSep 16, 2015
  33. Jeff KingSep 16, 2015
  34. 11/67 trace: use strbuf for quote_crnl outputJeff King, Sep 15, 2015
  35. Eric SunshineSep 16, 2015
  36. Jeff KingSep 16, 2015
  37. Eric SunshineSep 16, 2015
  38. 12/67 progress: store throughput display in a strbufJeff King, Sep 15, 2015
  39. 13/67 test-dump-cache-tree: avoid overflow of cache-tree nameJeff King, Sep 15, 2015
  40. 14/67 compat/inet_ntop: fix off-by-one in inet_ntop4Jeff King, Sep 15, 2015
  41. 15/67 convert trivial sprintf / strcpy calls to xsnprintfJeff King, Sep 15, 2015
  42. Ramsay JonesSep 15, 2015
  43. Jeff KingSep 15, 2015
  44. Ramsay JonesSep 15, 2015
  45. Stefan BellerSep 15, 2015
  46. Jeff KingSep 16, 2015
  47. Junio C HamanoSep 16, 2015
  48. Junio C HamanoSep 16, 2015
  49. Eric SunshineSep 16, 2015
  50. Jeff KingSep 16, 2015
  51. Junio C HamanoSep 16, 2015
  52. Jeff KingSep 16, 2015
  53. Junio C HamanoSep 16, 2015
  54. Stefan BellerSep 16, 2015
  55. Jeff KingSep 16, 2015
  56. Jeff KingSep 16, 2015
  57. 16/67 archive-tar: use xsnprintf for trivial formattingJeff King, Sep 15, 2015
  58. 17/67 use xsnprintf for generating git object headersJeff King, Sep 15, 2015
  59. Junio C HamanoSep 16, 2015
  60. 18/67 find_short_object_filename: convert sprintf to xsnprintfJeff King, Sep 15, 2015
  61. 19/67 stop_progress_msg: convert sprintf to xsnprintfJeff King, Sep 15, 2015
  62. 20/67 compat/hstrerror: convert sprintf to snprintfJeff King, Sep 15, 2015
  63. 21/67 grep: use xsnprintf to format failure messageJeff King, Sep 15, 2015
  64. 22/67 entry.c: convert strcpy to xsnprintfJeff King, Sep 15, 2015
  65. Ramsay JonesSep 15, 2015
  66. Stefan BellerSep 15, 2015
  67. 23/67 add_packed_git: convert strcpy into xsnprintfJeff King, Sep 15, 2015
  68. Junio C HamanoSep 16, 2015
  69. Jeff KingSep 16, 2015
  70. 24/67 http-push: replace strcat with xsnprintfJeff King, Sep 15, 2015
  71. 25/67 receive-pack: convert strncpy to xsnprintfJeff King, Sep 15, 2015
  72. 26/67 replace trivial malloc + sprintf /strcpy calls to xstrfmtJeff King, Sep 15, 2015
  73. Eric SunshineSep 16, 2015
  74. Jeff KingSep 16, 2015
  75. 27/67 config: use xstrfmt in normalize_valueJeff King, Sep 15, 2015
  76. 28/67 fetch: replace static buffer with xstrfmtJeff King, Sep 15, 2015
  77. 29/67 use strip_suffix and xstrfmt to replace suffixJeff King, Sep 15, 2015
  78. Eric SunshineSep 16, 2015
  79. Jeff KingSep 16, 2015
  80. Eric SunshineSep 16, 2015
  81. 30/67 ref-filter: drop sprintf and strcpy callsJeff King, Sep 15, 2015
  82. Junio C HamanoSep 16, 2015
  83. 31/67 help: drop prepend function in favor of xstrfmtJeff King, Sep 15, 2015
  84. 32/67 mailmap: replace strcpy with xstrdupJeff King, Sep 15, 2015
  85. 33/67 read_branches_file: replace strcpy with xstrdupJeff King, Sep 15, 2015
  86. Junio C HamanoSep 16, 2015
  87. Jeff KingSep 16, 2015
  88. Jeff KingSep 17, 2015
  89. Jeff KingSep 17, 2015
  90. Jeff KingSep 17, 2015
  91. Junio C HamanoSep 17, 2015
  92. Jeff KingSep 17, 2015
  93. Junio C HamanoSep 17, 2015
  94. 34/67 resolve_ref: use strbufs for internal buffersJeff King, Sep 15, 2015
  95. 35/67 upload-archive: convert sprintf to strbufJeff King, Sep 15, 2015
  96. 36/67 remote-ext: simplify git pkt-line generationJeff King, Sep 15, 2015
  97. Junio C HamanoSep 16, 2015
  98. Jeff KingSep 16, 2015
  99. 37/67 http-push: use strbuf instead of fwrite_bufferJeff King, Sep 15, 2015
  100. 38/67 http-walker: store url in a strbufJeff King, Sep 15, 2015
  101. 39/67 sha1_get_pack_name: use a strbufJeff King, Sep 15, 2015
  102. 40/67 init: use strbufs to store pathsJeff King, Sep 15, 2015
  103. 41/67 apply: convert root string to strbufJeff King, Sep 15, 2015
  104. 42/67 transport: use strbufs for status table "quickref" stringsJeff King, Sep 15, 2015
  105. 43/67 merge-recursive: convert malloc / strcpy to strbufJeff King, Sep 15, 2015
  106. 44/67 enter_repo: convert fixed-size buffers to strbufsJeff King, Sep 15, 2015
  107. 45/67 remove_leading_path: use a strbuf for internal storageJeff King, Sep 15, 2015
  108. 46/67 write_loose_object: convert to strbufJeff King, Sep 15, 2015
  109. Junio C HamanoSep 16, 2015
  110. Jeff KingSep 16, 2015
  111. 47/67 diagnose_invalid_index_path: use strbuf to avoid strcpy/strcatJeff King, Sep 15, 2015
  112. 48/67 fetch-pack: use argv_array for index-pack / unpack-objectsJeff King, Sep 15, 2015
  113. 49/67 http-push: use an argv_array for setup_revisionsJeff King, Sep 15, 2015
  114. 50/67 stat_tracking_info: convert to argv_arrayJeff King, Sep 15, 2015
  115. 51/67 daemon: use cld->env_array when re-spawningJeff King, Sep 15, 2015
  116. 52/67 use sha1_to_hex_to() instead of strcpyJeff King, Sep 15, 2015
  117. Junio C HamanoSep 16, 2015
  118. Jeff KingSep 16, 2015
  119. Junio C HamanoSep 16, 2015
  120. 53/67 drop strcpy in favor of raw sha1_to_hexJeff King, Sep 15, 2015
  121. Eric SunshineSep 18, 2015
  122. Jeff KingSep 18, 2015
  123. 54/67 color: add overflow checks for parsing colorsJeff King, Sep 15, 2015
  124. Eric SunshineSep 18, 2015
  125. Jeff KingSep 18, 2015
  126. Junio C HamanoSep 21, 2015
  127. 55/67 use alloc_ref rather than hand-allocating "struct ref"Jeff King, Sep 15, 2015
  128. 56/67 avoid sprintf and strcpy with flex arraysJeff King, Sep 15, 2015
  129. Eric SunshineSep 20, 2015
  130. Jeff KingSep 21, 2015
  131. Eric SunshineSep 21, 2015
  132. Jeff KingSep 21, 2015
  133. 57/67 receive-pack: simplify keep_arg computationJeff King, Sep 15, 2015
  134. Eric SunshineSep 18, 2015
  135. Jeff KingSep 18, 2015
  136. 58/67 help: clean up kfmclient mungingJeff King, Sep 15, 2015
  137. 59/67 prefer memcpy to strcpyJeff King, Sep 15, 2015
  138. 60/67 color: add color_set helper for copying raw colorsJeff King, Sep 15, 2015
  139. 61/67 notes: document length of fanout path with a constantJeff King, Sep 15, 2015
  140. 62/67 convert strncpy to memcpyJeff King, Sep 15, 2015
  141. 63/67 fsck: drop inode-sorting codeJeff King, Sep 15, 2015
  142. 64/67 Makefile: drop D_INO_IN_DIRENT build knobJeff King, Sep 15, 2015
  143. 65/67 fsck: use for_each_loose_file_in_objdirJeff King, Sep 15, 2015
  144. 66/67 use strbuf_complete to conditionally append slashJeff King, Sep 15, 2015
  145. Junio C HamanoSep 16, 2015
  146. Jeff KingSep 16, 2015
  147. Junio C HamanoSep 16, 2015
  148. Jeff KingSep 16, 2015
  149. Junio C HamanoSep 17, 2015
  150. Eric SunshineSep 21, 2015
  151. Jeff KingSep 21, 2015
  152. 67/67 name-rev: use strip_suffix to avoid magic numbersJeff King, Sep 15, 2015
  153. Junio C HamanoSep 16, 2015
  154. Jeff KingSep 16, 2015

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.