summaryrefslogtreecommitdiff
path: root/refs
diff options
context:
space:
mode:
authorMichael Haggerty <mhagger@alum.mit.edu>2017-09-13 17:16:01 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-09-14 06:19:07 (GMT)
commita8811695e30e48bec0aeefe6a01ed291fd68640b (patch)
treeab7b72b07d89e64fd54a84ea2fc751372b2ba825 /refs
parent36f23534aef58f747048ffea5addb0367406896d (diff)
downloadgit-a8811695e30e48bec0aeefe6a01ed291fd68640b.zip
git-a8811695e30e48bec0aeefe6a01ed291fd68640b.tar.gz
git-a8811695e30e48bec0aeefe6a01ed291fd68640b.tar.bz2
read_packed_refs(): make parsing of the header line more robust
The old code parsed the traits in the `packed-refs` header by looking for the string " trait " (i.e., the name of the trait with a space on either side) in the header line. This is fragile, because if any other implementation of Git forgets to write the trailing space, the last trait would silently be ignored (and the error might never be noticed). So instead, use `string_list_split_in_place()` to split the traits into tokens then use `unsorted_string_list_has_string()` to look for the tokens we are interested in. This means that we can read the traits correctly even if the header line is missing a trailing space (or indeed, if it is missing the space after the colon, or if it has multiple spaces somewhere). However, older Git clients (and perhaps other Git implementations) still require the surrounding spaces, so we still have to output the header with a trailing space. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs')
-rw-r--r--refs/packed-backend.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 141f02b..a45e3ff 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -257,25 +257,30 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
/* If the file has a header line, process it: */
if (pos < eof && *pos == '#') {
- const char *traits;
+ char *p;
+ struct string_list traits = STRING_LIST_INIT_NODUP;
eol = memchr(pos, '\n', eof - pos);
if (!eol)
die_unterminated_line(refs->path, pos, eof - pos);
- strbuf_add(&line, pos, eol + 1 - pos);
+ strbuf_add(&line, pos, eol - pos);
- if (!skip_prefix(line.buf, "# pack-refs with:", &traits))
+ if (!skip_prefix(line.buf, "# pack-refs with:", (const char **)&p))
die_invalid_line(refs->path, pos, eof - pos);
- if (strstr(traits, " fully-peeled "))
+ string_list_split_in_place(&traits, p, ' ', -1);
+
+ if (unsorted_string_list_has_string(&traits, "fully-peeled"))
peeled = PEELED_FULLY;
- else if (strstr(traits, " peeled "))
+ else if (unsorted_string_list_has_string(&traits, "peeled"))
peeled = PEELED_TAGS;
/* perhaps other traits later as well */
/* The "+ 1" is for the LF character. */
pos = eol + 1;
+
+ string_list_clear(&traits, 0);
strbuf_reset(&line);
}
@@ -610,7 +615,11 @@ int packed_refs_is_locked(struct ref_store *ref_store)
/*
* The packed-refs header line that we write out. Perhaps other
- * traits will be added later. The trailing space is required.
+ * traits will be added later.
+ *
+ * Note that earlier versions of Git used to parse these traits by
+ * looking for " trait " in the line. For this reason, the space after
+ * the colon and the trailing space are required.
*/
static const char PACKED_REFS_HEADER[] =
"# pack-refs with: peeled fully-peeled \n";