{"thread":{"id":"14136","subject":"[PATCH 3/4] verify-pack: check packed object CRC when using index version 2","startedAt":"2008-06-25T03:19:02Z","lastAt":"2008-06-25T03:19:02Z","messageCount":1,"participants":["Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"81042","messageId":"alpine.LFD.1.10.0806242318210.2979@xanadu.home","threadId":"14136","inReplyTo":null,"subject":"[PATCH 3/4] verify-pack: check packed object CRC when using index version 2","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2008-06-25T03:19:02Z","receivedAt":"2008-06-25T03:19:02Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"\nTo do so, check_pack_crc() moved from builtin-pack-objects.c to\npack-check.c where it is more logical to share.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n builtin-pack-objects.c |   22 ----------------------\n pack-check.c           |   39 +++++++++++++++++++++++++++++++++++++--\n pack.h                 |    2 +-\n 3 files changed, 38 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex 827673c..28207d9 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -209,28 +209,6 @@ static int check_pack_inflate(struct packed_git *p,\n \t\tstream.total_in == len) ? 0 : -1;\n }\n \n-static int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n-\t\t\t  off_t offset, off_t len, unsigned int nr)\n-{\n-\tconst uint32_t *index_crc;\n-\tuint32_t data_crc = crc32(0, Z_NULL, 0);\n-\n-\tdo {\n-\t\tunsigned int avail;\n-\t\tvoid *data = use_pack(p, w_curs, offset, &avail);\n-\t\tif (avail > len)\n-\t\t\tavail = len;\n-\t\tdata_crc = crc32(data_crc, data, avail);\n-\t\toffset += avail;\n-\t\tlen -= avail;\n-\t} while (len);\n-\n-\tindex_crc = p->index_data;\n-\tindex_crc += 2 + 256 + p->num_objects * (20/4) + nr;\n-\n-\treturn data_crc != ntohl(*index_crc);\n-}\n-\n static void copy_pack_data(struct sha1file *f,\n \t\tstruct packed_git *p,\n \t\tstruct pack_window **w_curs,\ndiff --git a/pack-check.c b/pack-check.c\nindex 5f02a65..f596bf2 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -4,8 +4,9 @@\n \n struct idx_entry\n {\n-\tconst unsigned char *sha1;\n \toff_t                offset;\n+\tconst unsigned char *sha1;\n+\tunsigned int nr;\n };\n \n static int compare_entries(const void *e1, const void *e2)\n@@ -19,6 +20,28 @@ static int compare_entries(const void *e1, const void *e2)\n \treturn 0;\n }\n \n+int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,\n+\t\t   off_t offset, off_t len, unsigned int nr)\n+{\n+\tconst uint32_t *index_crc;\n+\tuint32_t data_crc = crc32(0, Z_NULL, 0);\n+\n+\tdo {\n+\t\tunsigned int avail;\n+\t\tvoid *data = use_pack(p, w_curs, offset, &avail);\n+\t\tif (avail > len)\n+\t\t\tavail = len;\n+\t\tdata_crc = crc32(data_crc, data, avail);\n+\t\toffset += avail;\n+\t\tlen -= avail;\n+\t} while (len);\n+\n+\tindex_crc = p->index_data;\n+\tindex_crc += 2 + 256 + p->num_objects * (20/4) + nr;\n+\n+\treturn data_crc != ntohl(*index_crc);\n+}\n+\n static int verify_packfile(struct packed_git *p,\n \t\tstruct pack_window **w_curs)\n {\n@@ -61,13 +84,15 @@ static int verify_packfile(struct packed_git *p,\n \t * we do not do scan-streaming check on the pack file.\n \t */\n \tnr_objects = p->num_objects;\n-\tentries = xmalloc(nr_objects * sizeof(*entries));\n+\tentries = xmalloc((nr_objects + 1) * sizeof(*entries));\n+\tentries[nr_objects].offset = pack_sig_ofs;\n \t/* first sort entries by pack offset, since unpacking them is more efficient that way */\n \tfor (i = 0; i < nr_objects; i++) {\n \t\tentries[i].sha1 = nth_packed_object_sha1(p, i);\n \t\tif (!entries[i].sha1)\n \t\t\tdie(\"internal error pack-check nth-packed-object\");\n \t\tentries[i].offset = nth_packed_object_offset(p, i);\n+\t\tentries[i].nr = i;\n \t}\n \tqsort(entries, nr_objects, sizeof(*entries), compare_entries);\n \n@@ -76,6 +101,16 @@ static int verify_packfile(struct packed_git *p,\n \t\tenum object_type type;\n \t\tunsigned long size;\n \n+\t\tif (p->index_version > 1) {\n+\t\t\toff_t offset = entries[i].offset;\n+\t\t\toff_t len = entries[i+1].offset - offset;\n+\t\t\tunsigned int nr = entries[i].nr;\n+\t\t\tif (check_pack_crc(p, w_curs, offset, len, nr))\n+\t\t\t\terr = error(\"index CRC mismatch for object %s \"\n+\t\t\t\t\t    \"from %s at offset %\"PRIuMAX\"\",\n+\t\t\t\t\t    sha1_to_hex(entries[i].sha1),\n+\t\t\t\t\t    p->pack_name, (uintmax_t)offset);\n+\t\t}\n \t\tdata = unpack_entry(p, entries[i].offset, &type, &size);\n \t\tif (!data) {\n \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\ndiff --git a/pack.h b/pack.h\nindex 465071c..76e6aa2 100644\n--- a/pack.h\n+++ b/pack.h\n@@ -56,7 +56,7 @@ struct pack_idx_entry {\n };\n \n extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);\n-\n+extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);\n extern int verify_pack(struct packed_git *);\n extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t);\n extern char *index_pack_lockfile(int fd);\n-- \n1.5.6.56.g29b0d\n"}]}