diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-06-18 20:23:22 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-06-18 20:23:22 +0200 |
commit | f35f43f565c99d5cbbac210b82448d9f445c9607 (patch) | |
tree | b03ce86ff4b83a5a3d57675862308310413ae959 | |
parent | Merge tag 'l10n-2.18.0-rnd3' of git://github.com/git-l10n/git-po (diff) | |
parent | ewah: adjust callers of ewah_read_mmap() (diff) | |
download | git-f35f43f565c99d5cbbac210b82448d9f445c9607.tar.xz git-f35f43f565c99d5cbbac210b82448d9f445c9607.zip |
Merge branch 'jk/ewah-bounds-check'
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
-rw-r--r-- | dir.c | 3 | ||||
-rw-r--r-- | ewah/ewah_io.c | 25 | ||||
-rw-r--r-- | ewah/ewok.h | 2 | ||||
-rw-r--r-- | pack-bitmap.c | 2 | ||||
-rwxr-xr-x | t/t5310-pack-bitmaps.sh | 13 |
5 files changed, 38 insertions, 7 deletions
@@ -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') diff --git a/ewah/ewah_io.c b/ewah/ewah_io.c index bed1994551..33c08c40f8 100644 --- a/ewah/ewah_io.c +++ b/ewah/ewah_io.c @@ -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) diff --git a/ewah/ewok.h b/ewah/ewok.h index dc43d05b64..357fd93c84 100644 --- a/ewah/ewok.h +++ b/ewah/ewok.h @@ -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); diff --git a/pack-bitmap.c b/pack-bitmap.c index 06771113fb..18f8b22aeb 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -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); diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 423c0a475f..2d22a17c4a 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -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 |