summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2016-02-23 18:15:43 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2016-02-25 15:43:17 +0100
commitea9e00cb5ca271b794cca686019d17cc378e23f2 (patch)
tree50d91a5bdf9d7de250abd4d8a01482c404d55f0b
parent43955927e4b4ad004443f07cb5611a1f0ce282a4 (diff)
downloadlibgit2-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.c14
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