Commit ea9e00cb5ca271b794cca686019d17cc378e23f2

Carlos Martín Nieto 2016-02-23T18:15:43

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.

diff --git a/src/pack.c b/src/pack.c
index 081e370..b9b22a2 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