Add an 64-bit offset table index bounds check for v2 pack index Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
diff --git a/src/odb.c b/src/odb.c
index 5e95e53..47015c6 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -746,8 +746,8 @@ static int pack_openidx_v2(git_pack *p)
unsigned char *data = p->idx_map.data;
uint32_t *src_fanout = (uint32_t *)(data + 8);
uint32_t *im_fanout;
- size_t sz;
- int j;
+ size_t sz, o64_sz, o64_len;
+ uint32_t j;
if ((im_fanout = git__malloc(sizeof(*im_fanout) * 256)) == NULL)
return GIT_ERROR;
@@ -775,6 +775,21 @@ static int pack_openidx_v2(git_pack *p)
p->im_crc = (uint32_t *)(p->im_oid + 20 * p->obj_cnt);
p->im_offset32 = p->im_crc + p->obj_cnt;
p->im_offset64 = p->im_offset32 + p->obj_cnt;
+
+ /* check 64-bit offset table index values are within bounds */
+ o64_sz = p->idx_map.len - sz;
+ o64_len = o64_sz / 8;
+ for (j = 0; j < p->obj_cnt; j++) {
+ uint32_t o32 = decode32(p->im_offset32 + j);
+ if (o32 & 0x80000000) {
+ uint32_t o64_idx = (o32 & ~0x80000000);
+ if (o64_idx >= o64_len) {
+ free(im_fanout);
+ return GIT_ERROR;
+ }
+ }
+ }
+
return GIT_SUCCESS;
}