pack: make sure we don't go out of bounds for extended entries

A corrupt index might have data that tells us to go look past the end of
the file for data. Catch these cases and return an appropriate error
message.
This commit is contained in:
Carlos Martín Nieto 2016-02-23 18:15:43 +01:00
parent 43955927e4
commit ea9e00cb5c

View File

@ -1175,6 +1175,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n) static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n)
{ {
const unsigned char *index = p->index_map.data; const unsigned char *index = p->index_map.data;
const unsigned char *end = index + p->index_map.len;
index += 4 * 256; index += 4 * 256;
if (p->index_version == 1) { if (p->index_version == 1) {
return ntohl(*((uint32_t *)(index + 24 * n))); return ntohl(*((uint32_t *)(index + 24 * n)));
@ -1185,6 +1186,11 @@ static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_
if (!(off & 0x80000000)) if (!(off & 0x80000000))
return off; return off;
index += p->num_objects * 4 + (off & 0x7fffffff) * 8; index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
/* Make sure we're not being sent out of bounds */
if (index >= end - 8)
return -1;
return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) | return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
ntohl(*((uint32_t *)(index + 4))); ntohl(*((uint32_t *)(index + 4)));
} }
@ -1264,6 +1270,7 @@ static int pack_entry_find_offset(
const unsigned char *index = p->index_map.data; const unsigned char *index = p->index_map.data;
unsigned hi, lo, stride; unsigned hi, lo, stride;
int pos, found = 0; int pos, found = 0;
git_off_t offset;
const unsigned char *current = 0; const unsigned char *current = 0;
*offset_out = 0; *offset_out = 0;
@ -1336,7 +1343,12 @@ static int pack_entry_find_offset(
if (found > 1) if (found > 1)
return git_odb__error_ambiguous("found multiple offsets for pack entry"); return git_odb__error_ambiguous("found multiple offsets for pack entry");
*offset_out = nth_packed_object_offset(p, pos); if ((offset = nth_packed_object_offset(p, pos)) < 0) {
giterr_set(GITERR_ODB, "packfile index is corrupt");
return -1;
}
*offset_out = offset;
git_oid_fromraw(found_oid, current); git_oid_fromraw(found_oid, current);
#ifdef INDEX_DEBUG_LOOKUP #ifdef INDEX_DEBUG_LOOKUP