read_packed_refs(): die if `packed-refs` contains bogus data

The old code ignored any lines that it didn't understand, including unterminated lines. This is dangerous. Instead, `die()` if the `packed-refs` file contains any unterminated lines or lines that we don't know how to handle. This fixes the tests added in the last commit. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jul 1, 2017 at 20:31 UTC 9308b7f3ca9bbe7e76b16c832617a8c6aea5ade3
2 files changed +10 -6
refs/packed-backend.c
+7 -3
@@ -229,6 +229,9 @@ static struct packed_ref_cache *read_packed_refs(const char *packed_refs_file)
229 const char *refname;
230 const char *traits;
231
232 + if (!line.len || line.buf[line.len - 1] != '\n')
233 + die("unterminated line in %s: %s", packed_refs_file, line.buf);
234 +
235 if (skip_prefix(line.buf, "# pack-refs with:", &traits)) {
236 if (strstr(traits, " fully-peeled "))
237 peeled = PEELED_FULLY;
@@ -253,9 +256,7 @@ static struct packed_ref_cache *read_packed_refs(const char *packed_refs_file)
256 (peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
257 last->flag |= REF_KNOWS_PEELED;
258 add_ref_entry(dir, last);
256 - continue;
257 - }
258 - if (last &&
259 + } else if (last &&
260 line.buf[0] == '^' &&
261 line.len == PEELED_LINE_LENGTH &&
262 line.buf[PEELED_LINE_LENGTH - 1] == '\n' &&
@@ -267,6 +268,9 @@ static struct packed_ref_cache *read_packed_refs(const char *packed_refs_file)
268 * reference:
269 */
270 last->flag |= REF_KNOWS_PEELED;
271 + } else {
272 + strbuf_setlen(&line, line.len - 1);
273 + die("unexpected line in %s: %s", packed_refs_file, line.buf);
274 }
275 }
276
t/t3210-pack-refs.sh
+3 -3
@@ -194,7 +194,7 @@ test_expect_success 'notice d/f conflict with existing ref' '
194 test_must_fail git branch foo/bar/baz/lots/of/extra/components
195 '
196
197 -test_expect_failure 'reject packed-refs with unterminated line' '
197 +test_expect_success 'reject packed-refs with unterminated line' '
198 cp .git/packed-refs .git/packed-refs.bak &&
199 test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
200 printf "%s" "$HEAD refs/zzzzz" >>.git/packed-refs &&
@@ -203,7 +203,7 @@ test_expect_failure 'reject packed-refs with unterminated line' '
203 test_cmp expected_err err
204 '
205
206 -test_expect_failure 'reject packed-refs containing junk' '
206 +test_expect_success 'reject packed-refs containing junk' '
207 cp .git/packed-refs .git/packed-refs.bak &&
208 test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
209 printf "%s\n" "bogus content" >>.git/packed-refs &&
@@ -212,7 +212,7 @@ test_expect_failure 'reject packed-refs containing junk' '
212 test_cmp expected_err err
213 '
214
215 -test_expect_failure 'reject packed-refs with a short SHA-1' '
215 +test_expect_success 'reject packed-refs with a short SHA-1' '
216 cp .git/packed-refs .git/packed-refs.bak &&
217 test_when_finished "mv .git/packed-refs.bak .git/packed-refs" &&
218 printf "%.7s %s\n" $HEAD refs/zzzzz >>.git/packed-refs &&