Skip to content

Commit 2d12a8c

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 to inspect whether the oid is not correct. Then, check whether the next character is oid. Then check the refname. 2. If the next line starts with '^', it would continue to parse the peeled oid and check whether the last character is '\n'. As we decide to implement the ref consistency check for "packed-refs", let's port these two checks and update the 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 9dd9b66 commit 2d12a8c

File tree

4 files changed

+169
-1
lines changed

4 files changed

+169
-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: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1812,9 +1812,114 @@ static int packed_fsck_ref_header(struct fsck_options *o,
18121812
return 0;
18131813
}
18141814

1815+
static int packed_fsck_ref_peeled_line(struct fsck_options *o,
1816+
struct ref_store *ref_store,
1817+
unsigned long line_number,
1818+
const char *start, const char *eol)
1819+
{
1820+
struct strbuf packed_entry = STRBUF_INIT;
1821+
struct fsck_ref_report report = { 0 };
1822+
struct object_id peeled;
1823+
const char *p;
1824+
int ret = 0;
1825+
1826+
/*
1827+
* Skip the '^' and parse the peeled oid.
1828+
*/
1829+
start++;
1830+
if (parse_oid_hex_algop(start, &peeled, &p, ref_store->repo->hash_algo)) {
1831+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1832+
report.path = packed_entry.buf;
1833+
1834+
ret = fsck_report_ref(o, &report,
1835+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1836+
"'%.*s' has invalid peeled oid",
1837+
(int)(eol - start), start);
1838+
goto cleanup;
1839+
}
1840+
1841+
if (p != eol) {
1842+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1843+
report.path = packed_entry.buf;
1844+
1845+
ret = fsck_report_ref(o, &report,
1846+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1847+
"has trailing garbage after peeled oid '%.*s'",
1848+
(int)(eol - p), p);
1849+
goto cleanup;
1850+
}
1851+
1852+
cleanup:
1853+
strbuf_release(&packed_entry);
1854+
return ret;
1855+
}
1856+
1857+
static int packed_fsck_ref_main_line(struct fsck_options *o,
1858+
struct ref_store *ref_store,
1859+
unsigned long line_number,
1860+
struct strbuf *refname,
1861+
const char *start, const char *eol)
1862+
{
1863+
struct strbuf packed_entry = STRBUF_INIT;
1864+
struct fsck_ref_report report = { 0 };
1865+
struct object_id oid;
1866+
const char *p;
1867+
int ret = 0;
1868+
1869+
if (parse_oid_hex_algop(start, &oid, &p, ref_store->repo->hash_algo)) {
1870+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1871+
report.path = packed_entry.buf;
1872+
1873+
ret = fsck_report_ref(o, &report,
1874+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1875+
"'%.*s' has invalid oid",
1876+
(int)(eol - start), start);
1877+
goto cleanup;
1878+
}
1879+
1880+
if (p == eol || !isspace(*p)) {
1881+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1882+
report.path = packed_entry.buf;
1883+
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_reset(refname);
1893+
strbuf_add(refname, p, eol - p);
1894+
if (refname_contains_nul(refname)) {
1895+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1896+
report.path = packed_entry.buf;
1897+
1898+
ret = fsck_report_ref(o, &report,
1899+
FSCK_MSG_BAD_PACKED_REF_ENTRY,
1900+
"refname '%s' contains NULL binaries",
1901+
refname->buf);
1902+
}
1903+
1904+
if (check_refname_format(refname->buf, 0)) {
1905+
strbuf_addf(&packed_entry, "packed-refs line %lu", line_number);
1906+
report.path = packed_entry.buf;
1907+
1908+
ret = fsck_report_ref(o, &report,
1909+
FSCK_MSG_BAD_REF_NAME,
1910+
"has bad refname '%s'", refname->buf);
1911+
}
1912+
1913+
cleanup:
1914+
strbuf_release(&packed_entry);
1915+
return ret;
1916+
}
1917+
18151918
static int packed_fsck_ref_content(struct fsck_options *o,
1919+
struct ref_store *ref_store,
18161920
const char *start, const char *eof)
18171921
{
1922+
struct strbuf refname = STRBUF_INIT;
18181923
unsigned long line_number = 1;
18191924
const char *eol;
18201925
int ret = 0;
@@ -1827,6 +1932,21 @@ static int packed_fsck_ref_content(struct fsck_options *o,
18271932
line_number++;
18281933
}
18291934

1935+
while (start < eof) {
1936+
ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol);
1937+
ret |= packed_fsck_ref_main_line(o, ref_store, line_number, &refname, start, eol);
1938+
start = eol + 1;
1939+
line_number++;
1940+
if (start < eof && *start == '^') {
1941+
ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol);
1942+
ret |= packed_fsck_ref_peeled_line(o, ref_store, line_number,
1943+
start, eol);
1944+
start = eol + 1;
1945+
line_number++;
1946+
}
1947+
}
1948+
1949+
strbuf_release(&refname);
18301950
return ret;
18311951
}
18321952

@@ -1892,7 +2012,7 @@ static int packed_fsck(struct ref_store *ref_store,
18922012
goto cleanup;
18932013
}
18942014

1895-
ret = packed_fsck_ref_content(o, packed_ref_content.buf,
2015+
ret = packed_fsck_ref_content(o, ref_store, packed_ref_content.buf,
18962016
packed_ref_content.buf + packed_ref_content.len);
18972017

18982018
cleanup:

t/t0602-reffiles-fsck.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,48 @@ test_expect_success 'packed-refs unknown traits should not be reported' '
691691
)
692692
'
693693

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

0 commit comments

Comments
 (0)