@matheusbsbs / matheus-bagliano / commits / 3d77d8774f
Fork 0

make packed_object_info() resilient to pack corruptions

In the same spirit as commit 8eca0b47ff, let's try to survive a pack corruption by making packed_object_info() able to fall back to alternate packs or loose objects. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nicolas Pitre committed Oct 29, 2008 at 19:02 UTC 3d77d8774fc18216f18efa5c5907f73b22d61604
1 file changed +30 -6
sha1_file.c
+30 -6
@@ -1314,8 +1314,10 @@ unsigned long get_size_from_delta(struct packed_git *p,
1314 } while ((st == Z_OK || st == Z_BUF_ERROR) &&
1315 stream.total_out < sizeof(delta_head));
1316 inflateEnd(&stream);
1317 - if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head))
1318 - die("delta data unpack-initial failed");
1317 + if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) {
1318 + error("delta data unpack-initial failed");
1319 + return 0;
1320 + }
1321
1322 /* Examine the initial part of the delta to figure out
1323 * the result size.
@@ -1382,15 +1384,29 @@ static int packed_delta_info(struct packed_git *p,
1384 off_t base_offset;
1385
1386 base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
1387 + if (!base_offset)
1388 + return OBJ_BAD;
1389 type = packed_object_info(p, base_offset, NULL);
1390 + if (type <= OBJ_NONE) {
1391 + struct revindex_entry *revidx = find_pack_revindex(p, base_offset);
1392 + const unsigned char *base_sha1 =
1393 + nth_packed_object_sha1(p, revidx->nr);
1394 + mark_bad_packed_object(p, base_sha1);
1395 + type = sha1_object_info(base_sha1, NULL);
1396 + if (type <= OBJ_NONE)
1397 + return OBJ_BAD;
1398 + }
1399
1400 /* We choose to only get the type of the base object and
1401 * ignore potentially corrupt pack file that expects the delta
1402 * based on a base with a wrong size. This saves tons of
1403 * inflate() calls.
1404 */
1392 - if (sizep)
1405 + if (sizep) {
1406 *sizep = get_size_from_delta(p, w_curs, curpos);
1407 + if (*sizep == 0)
1408 + type = OBJ_BAD;
1409 + }
1410
1411 return type;
1412 }
@@ -1500,8 +1516,9 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
1516 *sizep = size;
1517 break;
1518 default:
1503 - die("pack %s contains unknown object type %d",
1504 - p->pack_name, type);
1519 + error("unknown object type %i at offset %"PRIuMAX" in %s",
1520 + type, (uintmax_t)obj_offset, p->pack_name);
1521 + type = OBJ_BAD;
1522 }
1523 unuse_pack(&w_curs);
1524 return type;
@@ -1971,7 +1988,14 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
1988 if (!find_pack_entry(sha1, &e, NULL))
1989 return status;
1990 }
1974 - return packed_object_info(e.p, e.offset, sizep);
1991 +
1992 + status = packed_object_info(e.p, e.offset, sizep);
1993 + if (status < 0) {
1994 + mark_bad_packed_object(e.p, sha1);
1995 + status = sha1_object_info(sha1, sizep);
1996 + }
1997 +
1998 + return status;
1999 }
2000
2001 static void *read_packed_sha1(const unsigned char *sha1,