fsck: check rev-index position values

When checking a rev-index file, it may be helpful to identify exactly
which positions are incorrect. Compare the rev-index to a
freshly-computed in-memory rev-index and report the comparison failures.

This additional check (on top of the checksum validation) can help find
files that were corrupt by a single bit flip on-disk or perhaps were
written incorrectly due to a bug in Git.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee 2023-04-17 16:21:40 +00:00 committed by Junio C Hamano
parent d975fe1fa5
commit 5f658d1b57
2 changed files with 26 additions and 4 deletions

View File

@ -310,16 +310,33 @@ int load_pack_revindex(struct repository *r, struct packed_git *p)
*/ */
int verify_pack_revindex(struct packed_git *p) int verify_pack_revindex(struct packed_git *p)
{ {
int res = 0;
/* Do not bother checking if not initialized. */ /* Do not bother checking if not initialized. */
if (!p->revindex_map) if (!p->revindex_map || !p->revindex_data)
return 0; return res;
if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) { if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) {
error(_("invalid checksum")); error(_("invalid checksum"));
return -1; res = -1;
} }
return 0; /* This may fail due to a broken .idx. */
if (create_pack_revindex_in_memory(p))
return res;
for (size_t i = 0; i < p->num_objects; i++) {
uint32_t nr = p->revindex[i].nr;
uint32_t rev_val = get_be32(p->revindex_data + i);
if (nr != rev_val) {
error(_("invalid rev-index position at %"PRIu64": %"PRIu32" != %"PRIu32""),
(uint64_t)i, nr, rev_val);
res = -1;
}
}
return res;
} }
int load_midx_revindex(struct multi_pack_index *m) int load_midx_revindex(struct multi_pack_index *m)

View File

@ -185,4 +185,9 @@ test_expect_success 'fsck catches invalid checksum' '
"invalid checksum" "invalid checksum"
' '
test_expect_success 'fsck catches invalid row position' '
corrupt_rev_and_verify 14 "\07" \
"invalid rev-index position"
'
test_done test_done