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

[PATCH 08/18] link_alt_odb_entry: refactor string handling

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

The string handling in link_alt_odb_entry() is mostly an artifact of the original version, which took the path as a ptr/len combo, and did not have a NUL-terminated string until we created one in the alternate_object_database struct. But since 5bdf0a8 (sha1_file: normalize alt_odb path before comparing and storing, 2011-09-07), the first thing we do is put the path into a strbuf, which gives us some easy opportunities for cleanup.

In particular:
  - we call strlen(pathbuf.buf), which is silly; we can look
    at pathbuf.len.
  - even though we have a strbuf, we don't maintain its
    "len" field when chomping extra slashes from the
    end, and instead keep a separate "pfxlen" variable. We
    can fix this and then drop "pfxlen" entirely.
  - we don't check whether the path is usable until after we
    allocate the new struct, making extra cleanup work for
    ourselves. Since we have a NUL-terminated string, we can
    bump the "is it usable" checks higher in the function.
    While we're at it, we can move that logic to its own
    helper, which makes the flow of link_alt_odb_entry()
    easier to follow.
Signed-off-by: Jeff King <peff@peff.net>
---
And you can probably guess now how I found the issue in the last patch
where pathbuf.len is totally bogus after calling normalize_path_copy. :)
 sha1_file.c | 83 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 45 insertions(+), 38 deletions(-)
diff --git a/sha1_file.c b/sha1_file.c
index 68571bd..f396823 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -234,6 +234,36 @@ char *sha1_pack_index_name(const unsigned char *sha1)
 struct alternate_object_database *alt_odb_list;
 static struct alternate_object_database **alt_odb_tail;
 
+/*
+ * Return non-zero iff the path is usable as an alternate object database.
+ */
+static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
+{
+	struct alternate_object_database *alt;
+
+	/* Detect cases where alternate disappeared */
+	if (!is_directory(path->buf)) {
+		error("object directory %s does not exist; "
+		      "check .git/objects/info/alternates.",
+		      path->buf);
+		return 0;
+	}
+
+	/*
+	 * Prevent the common mistake of listing the same
+	 * thing twice, or object directory itself.
+	 */
+	for (alt = alt_odb_list; alt; alt = alt->next) {
+		if (path->len == alt->name - alt->base - 1 &&
+		    !memcmp(path->buf, alt->base, path->len))
+			return 0;
+	}
+	if (!fspathcmp(path->buf, normalized_objdir))
+		return 0;
+
+	return 1;
+}
+
 /*
  * Prepare alternate object database registry.
  *
@@ -253,8 +283,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
 	int depth, const char *normalized_objdir)
 {
 	struct alternate_object_database *ent;
-	struct alternate_object_database *alt;
-	size_t pfxlen, entlen;
+	size_t entlen;
 	struct strbuf pathbuf = STRBUF_INIT;
 
 	if (!is_absolute_path(entry) && relative_base) {
@@ -270,47 +299,26 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
 		return -1;
 	}
 
-	pfxlen = strlen(pathbuf.buf);
-
 	/*
 	 * The trailing slash after the directory name is given by
 	 * this function at the end. Remove duplicates.
 	 */
-	while (pfxlen && pathbuf.buf[pfxlen-1] == '/')
-		pfxlen -= 1;
-
-	entlen = st_add(pfxlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
-	ent = xmalloc(st_add(sizeof(*ent), entlen));
-	memcpy(ent->base, pathbuf.buf, pfxlen);
-	strbuf_release(&pathbuf);
-
-	ent->name = ent->base + pfxlen + 1;
-	ent->base[pfxlen + 3] = '/';
-	ent->base[pfxlen] = ent->base[entlen-1] = 0;
+	while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/')
+		strbuf_setlen(&pathbuf, pathbuf.len - 1);
 
-	/* Detect cases where alternate disappeared */
-	if (!is_directory(ent->base)) {
-		error("object directory %s does not exist; "
-		      "check .git/objects/info/alternates.",
-		      ent->base);
-		free(ent);
+	if (!alt_odb_usable(&pathbuf, normalized_objdir)) {
+		strbuf_release(&pathbuf);
 		return -1;
 	}
 
-	/* Prevent the common mistake of listing the same
-	 * thing twice, or object directory itself.
-	 */
-	for (alt = alt_odb_list; alt; alt = alt->next) {
-		if (pfxlen == alt->name - alt->base - 1 &&
-		    !memcmp(ent->base, alt->base, pfxlen)) {
-			free(ent);
-			return -1;
-		}
-	}
-	if (!fspathcmp(ent->base, normalized_objdir)) {
-		free(ent);
-		return -1;
-	}
+	entlen = st_add(pathbuf.len, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
+	ent = xmalloc(st_add(sizeof(*ent), entlen));
+	memcpy(ent->base, pathbuf.buf, pathbuf.len);
+
+	ent->name = ent->base + pathbuf.len + 1;
+	ent->base[pathbuf.len] = '/';
+	ent->base[pathbuf.len + 3] = '/';
+	ent->base[entlen-1] = 0;
 
 	/* add the alternate entry */
 	*alt_odb_tail = ent;
@@ -318,10 +326,9 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
 	ent->next = NULL;
 
 	/* recursively add alternates */
-	read_info_alternates(ent->base, depth + 1);
-
-	ent->base[pfxlen] = '/';
+	read_info_alternates(pathbuf.buf, depth + 1);
 
+	strbuf_release(&pathbuf);
 	return 0;
 }
 
-- 
2.10.0.618.g82cc264
Previous: Bryan TurnerNext: Jacob Keller
Message 42 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.