Merge branch 'jk/ewah-bounds-check'
authorJunio C Hamano <gitster@pobox.com>
Mon, 18 Jun 2018 18:23:22 +0000 (11:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 18 Jun 2018 18:23:22 +0000 (11:23 -0700)
The code to read compressed bitmap was not careful to avoid reading
past the end of the file, which has been corrected.

* jk/ewah-bounds-check:
ewah: adjust callers of ewah_read_mmap()
ewah_read_mmap: bounds-check mmap reads

dir.c
ewah/ewah_io.c
ewah/ewok.h
pack-bitmap.c
t/t5310-pack-bitmaps.sh
diff --git a/dir.c b/dir.c
index ccf8b4975e8645182da783b2367e31401a4cdadb..fe9bf58e4c72790dca5492de4bd98df06798d27a 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -2853,7 +2853,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
        struct read_data rd;
        const unsigned char *next = data, *end = (const unsigned char *)data + sz;
        const char *ident;
-       int ident_len, len;
+       int ident_len;
+       ssize_t len;
        const char *exclude_per_dir;
 
        if (sz <= 1 || end[-1] != '\0')
index bed1994551cd03532fe56913b0e27343834c805f..33c08c40f896f32d9a1c251c1456755e949d91bd 100644 (file)
@@ -122,16 +122,23 @@ int ewah_serialize_strbuf(struct ewah_bitmap *self, struct strbuf *sb)
        return ewah_serialize_to(self, write_strbuf, sb);
 }
 
-int ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len)
+ssize_t ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len)
 {
        const uint8_t *ptr = map;
+       size_t data_len;
        size_t i;
 
+       if (len < sizeof(uint32_t))
+               return error("corrupt ewah bitmap: eof before bit size");
        self->bit_size = get_be32(ptr);
        ptr += sizeof(uint32_t);
+       len -= sizeof(uint32_t);
 
+       if (len < sizeof(uint32_t))
+               return error("corrupt ewah bitmap: eof before length");
        self->buffer_size = self->alloc_size = get_be32(ptr);
        ptr += sizeof(uint32_t);
+       len -= sizeof(uint32_t);
 
        REALLOC_ARRAY(self->buffer, self->alloc_size);
 
@@ -141,15 +148,25 @@ int ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len)
         * the endianness conversion in a separate pass to ensure
         * we're loading 8-byte aligned words.
         */
-       memcpy(self->buffer, ptr, self->buffer_size * sizeof(eword_t));
-       ptr += self->buffer_size * sizeof(eword_t);
+       data_len = st_mult(self->buffer_size, sizeof(eword_t));
+       if (len < data_len)
+               return error("corrupt ewah bitmap: eof in data "
+                            "(%"PRIuMAX" bytes short)",
+                            (uintmax_t)(data_len - len));
+       memcpy(self->buffer, ptr, data_len);
+       ptr += data_len;
+       len -= data_len;
 
        for (i = 0; i < self->buffer_size; ++i)
                self->buffer[i] = ntohll(self->buffer[i]);
 
+       if (len < sizeof(uint32_t))
+               return error("corrupt ewah bitmap: eof before rlw");
        self->rlw = self->buffer + get_be32(ptr);
+       ptr += sizeof(uint32_t);
+       len -= sizeof(uint32_t);
 
-       return (3 * 4) + (self->buffer_size * 8);
+       return ptr - (const uint8_t *)map;
 }
 
 int ewah_deserialize(struct ewah_bitmap *self, int fd)
index dc43d05b644af07a86bb64dbc6790ea0897d2f43..357fd93c84edbe79f9bcb10e2947ed935ac9f0df 100644 (file)
@@ -91,7 +91,7 @@ int ewah_serialize_native(struct ewah_bitmap *self, int fd);
 int ewah_serialize_strbuf(struct ewah_bitmap *self, struct strbuf *);
 
 int ewah_deserialize(struct ewah_bitmap *self, int fd);
-int ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len);
+ssize_t ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len);
 
 uint32_t ewah_checksum(struct ewah_bitmap *self);
 
index 06771113fb311e4a75fa7a1e325221e4b60c850c..18f8b22aeb422bb81999e1e564006daf8b64f637 100644 (file)
@@ -120,7 +120,7 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
 {
        struct ewah_bitmap *b = ewah_pool_new();
 
-       int bitmap_size = ewah_read_mmap(b,
+       ssize_t bitmap_size = ewah_read_mmap(b,
                index->map + index->map_pos,
                index->map_size - index->map_pos);
 
index 423c0a475f7e87b4c32abf60ef85ccbb898eca11..2d22a17c4a7f9dcc402e89e73ce01c97ebd4ba48 100755 (executable)
@@ -331,4 +331,17 @@ test_expect_success 'pack reuse respects --incremental' '
        git show-index <empty.idx >actual &&
        test_cmp expect actual
 '
+
+test_expect_success 'truncated bitmap fails gracefully' '
+       git repack -ad &&
+       git rev-list --use-bitmap-index --count --all >expect &&
+       bitmap=$(ls .git/objects/pack/*.bitmap) &&
+       test_when_finished "rm -f $bitmap" &&
+       head -c 512 <$bitmap >$bitmap.tmp &&
+       mv -f $bitmap.tmp $bitmap &&
+       git rev-list --use-bitmap-index --count --all >actual 2>stderr &&
+       test_cmp expect actual &&
+       test_i18ngrep corrupt stderr
+'
+
 test_done