Git 2.7.6
[gitweb.git] / sha1_file.c
index ab16c7b98cbd72bc79e8c0866417889626e2e71a..b516874473e2d800d1bbad6e50fda4532bc9aae0 100644 (file)
@@ -1076,6 +1076,8 @@ unsigned char *use_pack(struct packed_git *p,
                die("packfile %s cannot be accessed", p->pack_name);
        if (offset > (p->pack_size - 20))
                die("offset beyond end of packfile (truncated pack?)");
+       if (offset < 0)
+               die(_("offset before end of packfile (broken .idx?)"));
 
        if (!win || !in_window(win, offset)) {
                if (win)
@@ -2448,6 +2450,20 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,
        }
 }
 
+void check_pack_index_ptr(const struct packed_git *p, const void *vptr)
+{
+       const unsigned char *ptr = vptr;
+       const unsigned char *start = p->index_data;
+       const unsigned char *end = start + p->index_size;
+       if (ptr < start)
+               die(_("offset before start of pack index for %s (corrupt index?)"),
+                   p->pack_name);
+       /* No need to check for underflow; .idx files must be at least 8 bytes */
+       if (ptr >= end - 8)
+               die(_("offset beyond end of pack index for %s (truncated index?)"),
+                   p->pack_name);
+}
+
 off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
 {
        const unsigned char *index = p->index_data;
@@ -2461,6 +2477,7 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
                if (!(off & 0x80000000))
                        return off;
                index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
+               check_pack_index_ptr(p, index);
                return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
                                   ntohl(*((uint32_t *)(index + 4)));
        }