diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2016-02-23 18:15:43 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2016-02-25 15:43:17 +0100 |
commit | ea9e00cb5ca271b794cca686019d17cc378e23f2 (patch) | |
tree | 50d91a5bdf9d7de250abd4d8a01482c404d55f0b | |
parent | 43955927e4b4ad004443f07cb5611a1f0ce282a4 (diff) | |
download | libgit2-ea9e00cb5ca271b794cca686019d17cc378e23f2.tar.gz |
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.
-rw-r--r-- | src/pack.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/src/pack.c b/src/pack.c index 081e37084..b9b22a2ef 100644 --- a/src/pack.c +++ b/src/pack.c @@ -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) { const unsigned char *index = p->index_map.data; + const unsigned char *end = index + p->index_map.len; index += 4 * 256; if (p->index_version == 1) { 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)) return off; 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) | ntohl(*((uint32_t *)(index + 4))); } @@ -1264,6 +1270,7 @@ static int pack_entry_find_offset( const unsigned char *index = p->index_map.data; unsigned hi, lo, stride; int pos, found = 0; + git_off_t offset; const unsigned char *current = 0; *offset_out = 0; @@ -1336,7 +1343,12 @@ static int pack_entry_find_offset( if (found > 1) 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); #ifdef INDEX_DEBUG_LOOKUP |