Skip to content

Commit d87c126

Browse files
shejialuogitster
authored andcommitted
packed-backend: add "packed-refs" entry consistency check
"packed-backend.c::next_record" will parse the ref entry to check the consistency. This function has already checked the following things: 1. Parse the main line of the ref entry, if the oid is not correct. It will die the program. And then it will check whether the next character of the oid is space. Then it will check whether the refname is correct. 2. If the next line starts with '^', it will continue to parse the oid of the peeled oid content and check whether the last character is '\n'. We can iterate each line by using the "packed_fsck_ref_unterminated_line" function. Then, create a new fsck message "badPackedRefEntry(ERROR)" to report to the user when something is wrong. Create two new functions "packed_fsck_ref_main_line" and "packed_fsck_ref_peeled_line" for case 1 and case 2 respectively. Last, update the unit test to exercise the code. Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: Karthik Nayak <[email protected]> Signed-off-by: shejialuo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1be2de2 commit d87c126

File tree

4 files changed

+148
-1
lines changed

4 files changed

+148
-1
lines changed

Documentation/fsck-msgids.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
`badObjectSha1`::
1717
(ERROR) An object has a bad sha1.
1818

19+
`badPackedRefEntry`::
20+
(ERROR) The "packed-refs" file contains an invalid entry.
21+
1922
`badPackedRefHeader`::
2023
(ERROR) The "packed-refs" file contains an invalid
2124
header.

fsck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum fsck_msg_type {
3030
FUNC(BAD_EMAIL, ERROR) \
3131
FUNC(BAD_NAME, ERROR) \
3232
FUNC(BAD_OBJECT_SHA1, ERROR) \
33+
FUNC(BAD_PACKED_REF_ENTRY, ERROR) \
3334
FUNC(BAD_PACKED_REF_HEADER, ERROR) \
3435
FUNC(BAD_PARENT_SHA1, ERROR) \
3536
FUNC(BAD_REF_CONTENT, ERROR) \

refs/packed-backend.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,96 @@ static int packed_fsck_ref_header(struct fsck_options *o, const char *start, con
18231823
return 0;
18241824
}
18251825

1826+
static int packed_fsck_ref_peeled_line(struct fsck_options *o,
1827+
struct ref_store *ref_store, int line_number,
1828+
const char *start, const char *eol)
1829+
{
1830+
struct strbuf peeled_entry = STRBUF_INIT;
1831+
struct fsck_ref_report report = { 0 };
1832+
struct object_id peeled;
1833+
const char *p;
1834+
int ret = 0;
1835+
1836+
strbuf_addf(&peeled_entry, "packed-refs line %d", line_number);
1837+
report.path = peeled_entry.buf;
1838+
1839+
start++;
1840+
if (parse_oid_hex_algop(start, &peeled, &p, ref_store->repo->hash_algo)) {
1841+
ret |= fsck_report_ref(o, &report,
1842+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1843+
"'%.*s' has invalid peeled oid",
1844+
(int)(eol - start), start);
1845+
goto cleanup;
1846+
}
1847+
1848+
if (p != eol) {
1849+
ret |= fsck_report_ref(o, &report,
1850+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1851+
"has trailing garbage after peeled oid '%.*s'",
1852+
(int)(eol - p), p);
1853+
goto cleanup;
1854+
}
1855+
1856+
cleanup:
1857+
strbuf_release(&peeled_entry);
1858+
return ret;
1859+
}
1860+
1861+
static int packed_fsck_ref_main_line(struct fsck_options *o,
1862+
struct ref_store *ref_store, int line_number,
1863+
const char *start, const char *eol)
1864+
{
1865+
struct strbuf packed_entry = STRBUF_INIT;
1866+
struct fsck_ref_report report = { 0 };
1867+
struct strbuf refname = STRBUF_INIT;
1868+
struct object_id oid;
1869+
const char *p;
1870+
int ret = 0;
1871+
1872+
strbuf_addf(&packed_entry, "packed-refs line %d", line_number);
1873+
report.path = packed_entry.buf;
1874+
1875+
if (parse_oid_hex_algop(start, &oid, &p, ref_store->repo->hash_algo)) {
1876+
ret |= fsck_report_ref(o, &report,
1877+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1878+
"'%.*s' has invalid oid",
1879+
(int)(eol - start), start);
1880+
goto cleanup;
1881+
}
1882+
1883+
if (p == eol || !isspace(*p)) {
1884+
ret |= fsck_report_ref(o, &report,
1885+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1886+
"has no space after oid '%s' but with '%.*s'",
1887+
oid_to_hex(&oid), (int)(eol - p), p);
1888+
goto cleanup;
1889+
}
1890+
1891+
p++;
1892+
strbuf_add(&refname, p, eol - p);
1893+
if (refname_contains_null(refname)) {
1894+
ret |= fsck_report_ref(o, &report,
1895+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1896+
"refname '%s' contains NULL binaries",
1897+
refname.buf);
1898+
goto cleanup;
1899+
}
1900+
1901+
if (check_refname_format(refname.buf, 0)) {
1902+
ret |= fsck_report_ref(o, &report,
1903+
FSCK_MSG_BAD_REF_NAME,
1904+
"has bad refname '%s'", refname.buf);
1905+
goto cleanup;
1906+
}
1907+
1908+
cleanup:
1909+
strbuf_release(&packed_entry);
1910+
strbuf_release(&refname);
1911+
return ret;
1912+
}
1913+
18261914
static int packed_fsck_ref_content(struct fsck_options *o,
1915+
struct ref_store *ref_store,
18271916
const char *start, const char *eof)
18281917
{
18291918
int line_number = 1;
@@ -1845,6 +1934,20 @@ static int packed_fsck_ref_content(struct fsck_options *o,
18451934
"missing header line");
18461935
}
18471936

1937+
while (start < eof) {
1938+
ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol);
1939+
ret |= packed_fsck_ref_main_line(o, ref_store, line_number, start, eol);
1940+
start = eol + 1;
1941+
line_number++;
1942+
if (start < eof && *start == '^') {
1943+
ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol);
1944+
ret |= packed_fsck_ref_peeled_line(o, ref_store, line_number,
1945+
start, eol);
1946+
start = eol + 1;
1947+
line_number++;
1948+
}
1949+
}
1950+
18481951
/*
18491952
* If there is anything wrong during the parsing of the "packed-refs"
18501953
* file, we should not check the object of the refs.
@@ -1901,7 +2004,7 @@ static int packed_fsck(struct ref_store *ref_store,
19012004
goto cleanup;
19022005
}
19032006

1904-
ret = packed_fsck_ref_content(o, packed_ref_content.buf,
2007+
ret = packed_fsck_ref_content(o, ref_store, packed_ref_content.buf,
19052008
packed_ref_content.buf + packed_ref_content.len);
19062009

19072010
cleanup:

t/t0602-reffiles-fsck.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,4 +690,44 @@ test_expect_success 'packed-refs header should be checked' '
690690
done
691691
'
692692

693+
test_expect_success 'packed-refs content should be checked' '
694+
test_when_finished "rm -rf repo" &&
695+
git init repo &&
696+
cd repo &&
697+
test_commit default &&
698+
git branch branch-1 &&
699+
git branch branch-2 &&
700+
git tag -a annotated-tag-1 -m tag-1 &&
701+
git tag -a annotated-tag-2 -m tag-2 &&
702+
703+
branch_1_oid=$(git rev-parse branch-1) &&
704+
branch_2_oid=$(git rev-parse branch-2) &&
705+
tag_1_oid=$(git rev-parse annotated-tag-1) &&
706+
tag_2_oid=$(git rev-parse annotated-tag-2) &&
707+
tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
708+
tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) &&
709+
short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) &&
710+
711+
printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs &&
712+
printf "%s\n" "$short_oid refs/heads/branch-1" >>.git/packed-refs &&
713+
printf "%sx\n" "$branch_1_oid" >>.git/packed-refs &&
714+
printf "%s refs/heads/bad-branch\n" "$branch_2_oid" >>.git/packed-refs &&
715+
printf "%s refs/heads/branch.\n" "$branch_2_oid" >>.git/packed-refs &&
716+
printf "%s refs/tags/annotated-tag-3\n" "$tag_1_oid" >>.git/packed-refs &&
717+
printf "^%s\n" "$short_oid" >>.git/packed-refs &&
718+
printf "%s refs/tags/annotated-tag-4.\n" "$tag_2_oid" >>.git/packed-refs &&
719+
printf "^%s garbage\n" "$tag_2_peeled_oid" >>.git/packed-refs &&
720+
test_must_fail git refs verify 2>err &&
721+
cat >expect <<-EOF &&
722+
error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid
723+
error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\''
724+
error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\''
725+
error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\''
726+
error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid
727+
error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\''
728+
error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\''
729+
EOF
730+
test_cmp expect err
731+
'
732+
693733
test_done

0 commit comments

Comments
 (0)