diff options
author | Nicolas Pitre <nico@cam.org> | 2008-10-30 02:02:48 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-11-03 02:22:35 +0300 |
commit | 03d660150cbc80cd7d2ec90c3c4e6ce563295e3a (patch) | |
tree | 97c2db823d00d000136895a205d2cc8c0caa3ea0 | |
parent | 3d77d8774fc18216f18efa5c5907f73b22d61604 (diff) |
make check_object() resilient to pack corruptions
The check_object() function tries to get away with the least amount of
pack access possible when it already has partial information on given
object rather than calling the more costly packed_object_info().
When things don't look right, it should just give up and fall back to
packed_object_info() directly instead of die()'ing.
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin-pack-objects.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 64aefdf23b..c05fb944b0 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1005,6 +1005,8 @@ static void check_object(struct object_entry *entry) used = unpack_object_header_buffer(buf, avail, &entry->in_pack_type, &entry->size); + if (used == 0) + goto give_up; /* * Determine if this is a delta and if so whether we can @@ -1016,6 +1018,8 @@ static void check_object(struct object_entry *entry) /* Not a delta hence we've already got all we need. */ entry->type = entry->in_pack_type; entry->in_pack_header_size = used; + if (entry->type < OBJ_COMMIT || entry->type > OBJ_BLOB) + goto give_up; unuse_pack(&w_curs); return; case OBJ_REF_DELTA: @@ -1032,16 +1036,20 @@ static void check_object(struct object_entry *entry) ofs = c & 127; while (c & 128) { ofs += 1; - if (!ofs || MSB(ofs, 7)) - die("delta base offset overflow in pack for %s", - sha1_to_hex(entry->idx.sha1)); + if (!ofs || MSB(ofs, 7)) { + error("delta base offset overflow in pack for %s", + sha1_to_hex(entry->idx.sha1)); + goto give_up; + } c = buf[used_0++]; ofs = (ofs << 7) + (c & 127); } ofs = entry->in_pack_offset - ofs; - if (ofs <= 0 || ofs >= entry->in_pack_offset) - die("delta base offset out of bound for %s", - sha1_to_hex(entry->idx.sha1)); + if (ofs <= 0 || ofs >= entry->in_pack_offset) { + error("delta base offset out of bound for %s", + sha1_to_hex(entry->idx.sha1)); + goto give_up; + } if (reuse_delta && !entry->preferred_base) { struct revindex_entry *revidx; revidx = find_pack_revindex(p, ofs); @@ -1078,6 +1086,8 @@ static void check_object(struct object_entry *entry) */ entry->size = get_size_from_delta(p, &w_curs, entry->in_pack_offset + entry->in_pack_header_size); + if (entry->size == 0) + goto give_up; unuse_pack(&w_curs); return; } @@ -1087,6 +1097,7 @@ static void check_object(struct object_entry *entry) * with sha1_object_info() to find about the object type * at this point... */ + give_up: unuse_pack(&w_curs); } |