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

[PATCH 14/18] alternates: store scratch buffer as strbuf

From
Jeff King <peff@peff.net>
Date
Oct 3, 2016, 20:36 UTC
Message-ID
<20161003203604.6qwvc226nkgw44d2@sigill.intra.peff.net>
In-Reply-To
<20161003203321.rj5jepviwo57uhqw@sigill.intra.peff.net>

We pre-size the scratch buffer to hold a loose object filename of the form "xx/yyyy...", which leads to allocation code that is hard to verify. We have to use some magic numbers during the initial allocation, and then writers must blindly assume that the buffer is big enough. Using a strbuf makes it more clear that we cannot overflow.

Unfortunately, we do still need some magic numbers to grow our strbuf before calling fill_sha1_path(), but the strbuf growth is much closer to the point of use. This makes it easier to see that it's correct, and opens the possibility of pushing it even further down if fill_sha1_path() learns to work on strbufs.

Signed-off-by: Jeff King <peff@peff.net>
---
 cache.h     | 13 +++++++++++--
 sha1_file.c | 28 ++++++++++++++++++----------
 sha1_name.c |  9 +++------
 3 files changed, 32 insertions(+), 18 deletions(-)
diff --git a/cache.h b/cache.h
index e1996c5..9866e46 100644
--- a/cache.h
+++ b/cache.h
@@ -1383,8 +1383,9 @@ extern void remove_scheduled_dirs(void);
 extern struct alternate_object_database {
 	struct alternate_object_database *next;
 
-	char *name;
-	char *scratch;
+	/* see alt_scratch_buf() */
+	struct strbuf scratch;
+	size_t base_len;
 
 	char path[FLEX_ARRAY];
 } *alt_odb_list;
@@ -1413,6 +1414,14 @@ extern void add_to_alternates_file(const char *dir);
  */
 extern void add_to_alternates_memory(const char *dir);
 
+/*
+ * Returns a scratch strbuf pre-filled with the alternate object directory,
+ * including a trailing slash, which can be used to access paths in the
+ * alternate. Always use this over direct access to alt->scratch, as it
+ * cleans up any previous use of the scratch buffer.
+ */
+extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
+
 struct pack_window {
 	struct pack_window *next;
 	unsigned char *base;
diff --git a/sha1_file.c b/sha1_file.c
index c6308c1..efc8cee 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -204,11 +204,24 @@ const char *sha1_file_name(const unsigned char *sha1)
 	return buf;
 }
 
+struct strbuf *alt_scratch_buf(struct alternate_object_database *alt)
+{
+	strbuf_setlen(&alt->scratch, alt->base_len);
+	return &alt->scratch;
+}
+
 static const char *alt_sha1_path(struct alternate_object_database *alt,
 				 const unsigned char *sha1)
 {
-	fill_sha1_path(alt->name, sha1);
-	return alt->scratch;
+	/* hex sha1 plus internal "/" */
+	size_t len = GIT_SHA1_HEXSZ + 1;
+	struct strbuf *buf = alt_scratch_buf(alt);
+
+	strbuf_grow(buf, len);
+	fill_sha1_path(buf->buf + buf->len, sha1);
+	strbuf_setlen(buf, buf->len + len);
+
+	return buf->buf;
 }
 
 /*
@@ -396,16 +409,11 @@ void read_info_alternates(const char * relative_base, int depth)
 struct alternate_object_database *alloc_alt_odb(const char *dir)
 {
 	struct alternate_object_database *ent;
-	size_t dirlen = strlen(dir);
-	size_t entlen;
 
-	entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
 	FLEX_ALLOC_STR(ent, path, dir);
-	ent->scratch = xmalloc(entlen);
-	xsnprintf(ent->scratch, entlen, "%s/", dir);
-
-	ent->name = ent->scratch + dirlen + 1;
-	ent->scratch[dirlen] = '/';
+	strbuf_init(&ent->scratch, 0);
+	strbuf_addf(&ent->scratch, "%s/", dir);
+	ent->base_len = ent->scratch.len;
 
 	return ent;
 }
diff --git a/sha1_name.c b/sha1_name.c
index 770ea4f..defbb3e 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -92,15 +92,12 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
 
 	xsnprintf(hex, sizeof(hex), "%.2s", hex_pfx);
 	for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
+		struct strbuf *buf = alt_scratch_buf(alt);
 		struct dirent *de;
 		DIR *dir;
 
-		/*
-		 * every alt_odb struct has 42 extra bytes after the base
-		 * for exactly this purpose
-		 */
-		xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
-		dir = opendir(alt->scratch);
+		strbuf_addf(buf, "%.2s/", hex_pfx);
+		dir = opendir(buf->buf);
 		if (!dir)
 			continue;
 
-- 
2.10.0.618.g82cc264
Previous: Junio C HamanoNext: Jeff King
Message 64 of 84 in “alternate object database cleanups”
  1. 0/18 alternate object database cleanupsJeff King, Oct 3, 2016
  2. 01/18 t5613: drop reachable_via functionJeff King, Oct 3, 2016
  3. Jacob KellerOct 4, 2016
  4. Jeff KingOct 4, 2016
  5. 02/18 t5613: drop test_valid_repo functionJeff King, Oct 3, 2016
  6. Jacob KellerOct 4, 2016
  7. 03/18 t5613: use test_must_failJeff King, Oct 3, 2016
  8. Jacob KellerOct 4, 2016
  9. 05/18 t5613: do not chdir in main processJeff King, Oct 3, 2016
  10. Jacob KellerOct 4, 2016
  11. Junio C HamanoOct 4, 2016
  12. 04/18 t5613: whitespace/style cleanupsJeff King, Oct 3, 2016
  13. Jacob KellerOct 4, 2016
  14. Jeff KingOct 4, 2016
  15. Jacob KellerOct 4, 2016
  16. 06/18 t5613: clarify "too deep" recursion testsJeff King, Oct 3, 2016
  17. Jacob KellerOct 4, 2016
  18. Jeff KingOct 4, 2016
  19. Jacob KellerOct 4, 2016
  20. Jeff KingOct 4, 2016
  21. Jacob KellerOct 4, 2016
  22. Jeff KingOct 4, 2016
  23. Stefan BellerOct 4, 2016
  24. Jeff KingOct 4, 2016
  25. Jakub NarębskiOct 5, 2016
  26. Jeff KingOct 5, 2016
  27. Junio C HamanoOct 5, 2016
  28. Jacob KellerOct 5, 2016
  29. Jacob KellerOct 4, 2016
  30. Jeff KingOct 4, 2016
  31. Jacob KellerOct 4, 2016
  32. 07/18 link_alt_odb_entry: handle normalize_path errorsJeff King, Oct 3, 2016
  33. Jacob KellerOct 4, 2016
  34. Junio C HamanoOct 4, 2016
  35. René ScharfeOct 5, 2016
  36. Jeff KingOct 5, 2016
  37. Bryan TurnerNov 7, 2016
  38. Jeff KingNov 8, 2016
  39. Bryan TurnerNov 8, 2016
  40. Jeff KingNov 8, 2016
  41. Bryan TurnerNov 8, 2016
  42. 08/18 link_alt_odb_entry: refactor string handlingJeff King, Oct 3, 2016
  43. Jacob KellerOct 4, 2016
  44. Jeff KingOct 4, 2016
  45. Jacob KellerOct 4, 2016
  46. Junio C HamanoOct 4, 2016
  47. 09/18 alternates: provide helper for adding to alternates listJeff King, Oct 3, 2016
  48. Jacob KellerOct 4, 2016
  49. 10/18 alternates: provide helper for allocating alternateJeff King, Oct 3, 2016
  50. Jacob KellerOct 4, 2016
  51. 11/18 alternates: encapsulate alt->base mungingJeff King, Oct 3, 2016
  52. 12/18 alternates: use a separate scratch spaceJeff King, Oct 3, 2016
  53. Jacob KellerOct 4, 2016
  54. Junio C HamanoOct 4, 2016
  55. Jeff KingOct 4, 2016
  56. Junio C HamanoOct 4, 2016
  57. Jeff KingOct 4, 2016
  58. 13/18 fill_sha1_file: write "boring" charactersJeff King, Oct 3, 2016
  59. Jacob KellerOct 4, 2016
  60. Junio C HamanoOct 4, 2016
  61. Jeff KingOct 4, 2016
  62. Jacob KellerOct 4, 2016
  63. Junio C HamanoOct 5, 2016
  64. 14/18 alternates: store scratch buffer as strbufJeff King, Oct 3, 2016
  65. 15/18 fill_sha1_file: write into a strbufJeff King, Oct 3, 2016
  66. Jacob KellerOct 4, 2016
  67. 16/18 count-objects: report alternates via verbose modeJeff King, Oct 3, 2016
  68. Jacob KellerOct 4, 2016
  69. Jeff KingOct 4, 2016
  70. Jakub NarębskiOct 5, 2016
  71. René ScharfeOct 5, 2016
  72. 17/18 sha1_file: always allow relative paths to alternatesJeff King, Oct 3, 2016
  73. Jacob KellerOct 4, 2016
  74. Jeff KingOct 4, 2016
  75. 18/18 alternates: use fspathcmp to detect duplicatesJeff King, Oct 3, 2016
  76. Jacob KellerOct 4, 2016
  77. Jeff KingOct 4, 2016
  78. Junio C HamanoOct 4, 2016
  79. Aaron SchrabOct 5, 2016
  80. Jeff KingOct 5, 2016
  81. Jacob KellerOct 4, 2016
  82. Jeff KingOct 4, 2016
  83. Jacob KellerOct 4, 2016
  84. René ScharfeOct 5, 2016

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.