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

[PATCH v2 10/10] unique_path: fix unlikely heap overflow

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

When merge-recursive creates a unique filename, it uses a template like:

  path~branch_%d

where the final "_%d" is filled by an incrementing counter until we find a unique name. We allocate 8 characters for the counter, but there is no logic to limit the size of the integer.

Of course, this is extremely unlikely, as you would need a hundred million collisions to trigger the problem. Even if an attacker constructed a specialized repo, it is unlikely that the victim would have the patience to run the merge.

However, we can make it trivially correct (and hopefully more readable) by using a strbuf.

Signed-off-by: Jeff King <peff@peff.net>
---
 merge-recursive.c | 41 ++++++++++++++++++++++++++---------------
 1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index 532a1da..398a734 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -601,25 +601,36 @@ static int remove_file(struct merge_options *o, int clean,
 	return 0;
 }
 
+/* add a string to a strbuf, but converting "/" to "_" */
+static void add_flattened_path(struct strbuf *out, const char *s)
+{
+	size_t i = out->len;
+	strbuf_addstr(out, s);
+	for (; i < out->len; i++)
+		if (out->buf[i] == '/')
+			out->buf[i] = '_';
+}
+
 static char *unique_path(struct merge_options *o, const char *path, const char *branch)
 {
-	char *newpath = xmalloc(strlen(path) + 1 + strlen(branch) + 8 + 1);
+	struct strbuf newpath = STRBUF_INIT;
 	int suffix = 0;
 	struct stat st;
-	char *p = newpath + strlen(path);
-	strcpy(newpath, path);
-	*(p++) = '~';
-	strcpy(p, branch);
-	for (; *p; ++p)
-		if ('/' == *p)
-			*p = '_';
-	while (string_list_has_string(&o->current_file_set, newpath) ||
-	       string_list_has_string(&o->current_directory_set, newpath) ||
-	       lstat(newpath, &st) == 0)
-		sprintf(p, "_%d", suffix++);
-
-	string_list_insert(&o->current_file_set, newpath);
-	return newpath;
+	size_t base_len;
+
+	strbuf_addf(&newpath, "%s~", path);
+	add_flattened_path(&newpath, branch);
+
+	base_len = newpath.len;
+	while (string_list_has_string(&o->current_file_set, newpath.buf) ||
+	       string_list_has_string(&o->current_directory_set, newpath.buf) ||
+	       lstat(newpath.buf, &st) == 0) {
+		strbuf_setlen(&newpath, base_len);
+		strbuf_addf(&newpath, "_%d", suffix++);
+	}
+
+	string_list_insert(&o->current_file_set, newpath.buf);
+	return strbuf_detach(&newpath, NULL);
 }
 
 static int dir_in_way(const char *path, int check_working_copy)
-- 
2.0.0.566.gfe3e6b2
Previous: Jeff KingNext: René Scharfe
Message 25 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.