@matheusbsbs / matheus-bagliano / commits / 6241360498
Fork 0

make verify-pack a bit more useful with bad packs

When a pack gets corrupted, its SHA1 checksum will fail. However, this is more useful to let the test go on in order to find the actual problem location than only complain about the SHA1 mismatch and bail out. Also, it is more useful to compare the stored pack SHA1 with the one in the index file instead of the computed SHA1 since the computed SHA1 from a corrupted pack won't match the one stored in the index either. Finally a few code and message cleanups were thrown in as a bonus. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nicolas Pitre committed May 29, 2008 at 17:34 UTC 6241360498eb811d4bb130328b1d13241c5e14b6
1 file changed +27 -28
pack-check.c
+27 -28
@@ -25,10 +25,10 @@ static int verify_packfile(struct packed_git *p,
25 off_t index_size = p->index_size;
26 const unsigned char *index_base = p->index_data;
27 SHA_CTX ctx;
28 - unsigned char sha1[20];
29 - off_t offset = 0, pack_sig = p->pack_size - 20;
28 + unsigned char sha1[20], *pack_sig;
29 + off_t offset = 0, pack_sig_ofs = p->pack_size - 20;
30 uint32_t nr_objects, i;
31 - int err;
31 + int err = 0;
32 struct idx_entry *entries;
33
34 /* Note that the pack header checks are actually performed by
@@ -38,21 +38,22 @@ static int verify_packfile(struct packed_git *p,
38 */
39
40 SHA1_Init(&ctx);
41 - while (offset < pack_sig) {
41 + while (offset < pack_sig_ofs) {
42 unsigned int remaining;
43 unsigned char *in = use_pack(p, w_curs, offset, &remaining);
44 offset += remaining;
45 - if (offset > pack_sig)
46 - remaining -= (unsigned int)(offset - pack_sig);
45 + if (offset > pack_sig_ofs)
46 + remaining -= (unsigned int)(offset - pack_sig_ofs);
47 SHA1_Update(&ctx, in, remaining);
48 }
49 SHA1_Final(sha1, &ctx);
50 - if (hashcmp(sha1, use_pack(p, w_curs, pack_sig, NULL)))
51 - return error("Packfile %s SHA1 mismatch with itself",
52 - p->pack_name);
53 - if (hashcmp(sha1, index_base + index_size - 40))
54 - return error("Packfile %s SHA1 mismatch with idx",
55 - p->pack_name);
50 + pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL);
51 + if (hashcmp(sha1, pack_sig))
52 + err = error("%s SHA1 checksum mismatch",
53 + p->pack_name);
54 + if (hashcmp(index_base + index_size - 40, pack_sig))
55 + err = error("%s SHA1 does not match its inddex",
56 + p->pack_name);
57 unuse_pack(w_curs);
58
59 /* Make sure everything reachable from idx is valid. Since we
@@ -72,22 +73,23 @@ static int verify_packfile(struct packed_git *p,
73 }
74 qsort(entries, nr_objects, sizeof(*entries), compare_entries);
75
75 - for (i = 0, err = 0; i < nr_objects; i++) {
76 + for (i = 0; i < nr_objects; i++) {
77 void *data;
78 enum object_type type;
79 unsigned long size;
80
81 data = unpack_entry(p, entries[i].offset, &type, &size);
82 if (!data) {
82 - err = error("cannot unpack %s from %s",
83 - sha1_to_hex(entries[i].sha1), p->pack_name);
84 - continue;
83 + err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
84 + sha1_to_hex(entries[i].sha1), p->pack_name,
85 + (uintmax_t)entries[i].offset);
86 + break;
87 }
88 if (check_sha1_signature(entries[i].sha1, data, size, typename(type))) {
89 err = error("packed %s from %s is corrupt",
90 sha1_to_hex(entries[i].sha1), p->pack_name);
91 free(data);
90 - continue;
92 + break;
93 }
94 free(data);
95 }
@@ -158,31 +160,28 @@ int verify_pack(struct packed_git *p, int verbose)
160 const unsigned char *index_base;
161 SHA_CTX ctx;
162 unsigned char sha1[20];
161 - int ret;
163 + int err = 0;
164 + struct pack_window *w_curs = NULL;
165
166 if (open_pack_index(p))
167 return error("packfile %s index not opened", p->pack_name);
168 index_size = p->index_size;
169 index_base = p->index_data;
170
168 - ret = 0;
171 /* Verify SHA1 sum of the index file */
172 SHA1_Init(&ctx);
173 SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20));
174 SHA1_Final(sha1, &ctx);
175 if (hashcmp(sha1, index_base + index_size - 20))
174 - ret = error("Packfile index for %s SHA1 mismatch",
176 + err = error("Packfile index for %s SHA1 mismatch",
177 p->pack_name);
178
177 - if (!ret) {
178 - /* Verify pack file */
179 - struct pack_window *w_curs = NULL;
180 - ret = verify_packfile(p, &w_curs);
181 - unuse_pack(&w_curs);
182 - }
179 + /* Verify pack file */
180 + err |= verify_packfile(p, &w_curs);
181 + unuse_pack(&w_curs);
182
183 if (verbose) {
185 - if (ret)
184 + if (err)
185 printf("%s: bad\n", p->pack_name);
186 else {
187 show_pack_info(p);
@@ -190,5 +189,5 @@ int verify_pack(struct packed_git *p, int verbose)
189 }
190 }
191
193 - return ret;
192 + return err;
193 }