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

[PATCH 13/16] fast-import: refactor parsing of spaces

From
Jeff King <peff@peff.net>
Date
Jun 18, 2014, 19:51 UTC
Message-ID
<20140618195157.GM22622@sigill.intra.peff.net>
In-Reply-To
<20140618194117.GA22269@sigill.intra.peff.net>
When we see a file change in a commit, we expect one of:
  1. A mark.
  2. An "inline" keyword.
  3. An object sha1.

The handling of spaces is inconsistent between the three options. Option 1 calls a sub-function which checks for the space, but doesn't parse past it. Option 2 parses the space, then deliberately avoids moving the pointer past it. Option 3 detects the space locally but doesn't move past it.

This is confusing, because it looks like option 1 forgets to check for the space (it's just buried). And option 2 checks for "inline ", but only moves strlen("inline") characters forward, which looks like a bug but isn't.

We can make this more clear by just having each branch move past the space as it is checked (and we can replace the doubled use of "inline" with a call to skip_prefix).

Signed-off-by: Jeff King <peff@peff.net>
---
 fast-import.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index 5f17adb..55ca7d8 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2269,7 +2269,7 @@ static uintmax_t parse_mark_ref_space(const char **p)
 	char *end;
 
 	mark = parse_mark_ref(*p, &end);
-	if (*end != ' ')
+	if (*end++ != ' ')
 		die("Missing space after mark: %s", command_buf.buf);
 	*p = end;
 	return mark;
@@ -2304,20 +2304,17 @@ static void file_change_m(const char *p, struct branch *b)
 	if (*p == ':') {
 		oe = find_mark(parse_mark_ref_space(&p));
 		hashcpy(sha1, oe->idx.sha1);
-	} else if (starts_with(p, "inline ")) {
+	} else if (skip_prefix(p, "inline ", &p)) {
 		inline_data = 1;
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
-		p += strlen("inline");  /* advance to space */
 	} else {
 		if (get_sha1_hex(p, sha1))
 			die("Invalid dataref: %s", command_buf.buf);
 		oe = find_object(sha1);
 		p += 40;
-		if (*p != ' ')
+		if (*p++ != ' ')
 			die("Missing space after SHA1: %s", command_buf.buf);
 	}
-	assert(*p == ' ');
-	p++;  /* skip space */
 
 	strbuf_reset(&uq);
 	if (!unquote_c_style(&uq, p, &endp)) {
@@ -2474,20 +2471,17 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
 	if (*p == ':') {
 		oe = find_mark(parse_mark_ref_space(&p));
 		hashcpy(sha1, oe->idx.sha1);
-	} else if (starts_with(p, "inline ")) {
+	} else if (skip_prefix(p, "inline ", &p)) {
 		inline_data = 1;
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
-		p += strlen("inline");  /* advance to space */
 	} else {
 		if (get_sha1_hex(p, sha1))
 			die("Invalid dataref: %s", command_buf.buf);
 		oe = find_object(sha1);
 		p += 40;
-		if (*p != ' ')
+		if (*p++ != ' ')
 			die("Missing space after SHA1: %s", command_buf.buf);
 	}
-	assert(*p == ' ');
-	p++;  /* skip space */
 
 	/* <commit-ish> */
 	s = lookup_branch(p);
@@ -3005,6 +2999,8 @@ static struct object_entry *parse_treeish_dataref(const char **p)
 			die("Invalid dataref: %s", command_buf.buf);
 		e = find_object(sha1);
 		*p += 40;
+		if (*(*p)++ != ' ')
+			die("Missing space after tree-ish: %s", command_buf.buf);
 	}
 
 	while (!e || e->type != OBJ_TREE)
@@ -3056,8 +3052,6 @@ static void parse_ls(const char *p, struct branch *b)
 		if (!is_null_sha1(root->versions[1].sha1))
 			root->versions[1].mode = S_IFDIR;
 		load_tree(root);
-		if (*p++ != ' ')
-			die("Missing space after tree-ish: %s", command_buf.buf);
 	}
 	if (*p == '"') {
 		static struct strbuf uq = STRBUF_INIT;
-- 
2.0.0.566.gfe3e6b2
Previous: Jeff KingNext: Jeff King
Message 26 of 33 in “skip_prefix refactoring and cleanups”
  1. 0/16 skip_prefix refactoring and cleanupsJeff King, Jun 18, 2014
  2. 01/16 parse_diff_color_slot: drop ofs parameterJeff King, Jun 18, 2014
  3. 02/16 daemon: mark some strings as constJeff King, Jun 18, 2014
  4. 03/16 avoid using skip_prefix as a booleanJeff King, Jun 18, 2014
  5. 04/16 refactor skip_prefix to return a booleanJeff King, Jun 18, 2014
  6. Eric SunshineJun 20, 2014
  7. Jeff KingJun 20, 2014
  8. Eric SunshineJun 20, 2014
  9. Jeff KingJun 20, 2014
  10. Junio C HamanoJun 23, 2014
  11. Jeff KingJun 23, 2014
  12. builtin/clone.c: detect a clone starting at a tag correctlyJunio C Hamano, Jun 23, 2014
  13. 05/16 apply: use skip_prefix instead of raw additionJeff King, Jun 18, 2014
  14. 06/16 fast-import: fix read of uninitialized argv memoryJeff King, Jun 18, 2014
  15. 07/16 transport-helper: avoid reading past end-of-stringJeff King, Jun 18, 2014
  16. 08/16 use skip_prefix to avoid magic numbersJeff King, Jun 18, 2014
  17. Junio C HamanoJun 23, 2014
  18. Jeff KingJul 1, 2014
  19. 09/16 use skip_prefix to avoid repeating stringsJeff King, Jun 18, 2014
  20. 10/16 fast-import: use skip_prefix for parsing inputJeff King, Jun 18, 2014
  21. Eric SunshineJun 20, 2014
  22. Jeff KingJun 20, 2014
  23. Eric SunshineJun 20, 2014
  24. 11/16 daemon: use skip_prefix to avoid magic numbersJeff King, Jun 18, 2014
  25. 12/16 stat_opt: check extra strlen callJeff King, Jun 18, 2014
  26. 13/16 fast-import: refactor parsing of spacesJeff King, Jun 18, 2014
  27. 14/16 fetch-pack: refactor parsing in get_ackJeff King, Jun 18, 2014
  28. Eric SunshineJun 20, 2014
  29. 15/16 git: avoid magic number with skip_prefixJeff King, Jun 18, 2014
  30. 16/16 use skip_prefix to avoid repeated calculationsJeff King, Jun 18, 2014
  31. Tanay AbhraJun 19, 2014
  32. 17/16 http-push: refactor parsing of remote object namesJeff King, Jun 19, 2014
  33. Jeff KingJun 19, 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.