diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 15b80db5a1..1591417962 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1698,6 +1698,16 @@ static void prepare_pack(int window, int depth) get_object_details(); + /* + * If we're locally repacking then we need to be doubly careful + * from now on in order to make sure no stealth corruption gets + * propagated to the new pack. Clients receiving streamed packs + * should validate everything they get anyway so no need to incur + * the additional cost here in that case. + */ + if (!pack_to_stdout) + do_check_packed_object_crc = 1; + if (!nr_objects || !window || !depth) return; diff --git a/cache.h b/cache.h index b0edbf9b9f..6b18fab3c1 100644 --- a/cache.h +++ b/cache.h @@ -565,6 +565,9 @@ extern int force_object_loose(const unsigned char *sha1, time_t mtime); /* just like read_sha1_file(), but non fatal in presence of bad objects */ extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size); +/* global flag to enable extra checks when accessing packed objects */ +extern int do_check_packed_object_crc; + extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); extern int move_temp_to_file(const char *tmpfile, const char *filename); diff --git a/sha1_file.c b/sha1_file.c index ab2b520f03..88d9cf357f 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1694,6 +1694,8 @@ static void *unpack_delta_entry(struct packed_git *p, return result; } +int do_check_packed_object_crc; + void *unpack_entry(struct packed_git *p, off_t obj_offset, enum object_type *type, unsigned long *sizep) { @@ -1701,6 +1703,19 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset, off_t curpos = obj_offset; void *data; + if (do_check_packed_object_crc && p->index_version > 1) { + struct revindex_entry *revidx = find_pack_revindex(p, obj_offset); + unsigned long len = revidx[1].offset - obj_offset; + if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) { + const unsigned char *sha1 = + nth_packed_object_sha1(p, revidx->nr); + error("bad packed object CRC for %s", + sha1_to_hex(sha1)); + mark_bad_packed_object(p, sha1); + return NULL; + } + } + *type = unpack_object_header(p, &w_curs, &curpos, sizep); switch (*type) { case OBJ_OFS_DELTA: diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 344ab25b8b..29896141b9 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -160,7 +160,8 @@ test_expect_success \ test_expect_success \ '[index v2] 5) pack-objects refuses to reuse corrupted data' \ - 'test_must_fail git pack-objects test-5