From 3534f43bcbc323453931c072f8f981ef01930490 Mon Sep 17 00:00:00 2001 From: Sean Fox Date: Sat, 17 Jan 2009 23:44:33 +0000 Subject: Avoid integer overflow when boundary checking the size of the colour table. Kudos to Joonas Pihlaja. svn path=/trunk/libnsbmp/; revision=6121 --- libnsbmp.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/libnsbmp.c b/libnsbmp.c index ded7ff8..4d38207 100644 --- a/libnsbmp.c +++ b/libnsbmp.c @@ -106,6 +106,33 @@ static inline uint32_t read_uint32(uint8_t *data, unsigned int o) { return (uint32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24)); } + +/** + * Multiplies two 32-bit unsigned integers and checks for overflow + * + * \return 1 if successful; 0 if overflow occurred + */ +static uint8_t uint32_mult(uint32_t a, uint32_t b, uint32_t *c) { + uint64_t x = (uint64_t)a * b; + if (x > 0xffffffff) + return 0; + *c = x & 0xffffffff; + return 1; +} + +/** + * Adds two 32-bit unsigned integers and checks for overflow + * + * \return 1 if successful; 0 if overflow occurred + */ +static uint8_t uint32_add(uint32_t a, uint32_t b, uint32_t *c) { + uint64_t x = (uint64_t)a + b; + if (x > 0xffffffff) + return 0; + *c = x & 0xffffffff; + return 1; +} + static bmp_result next_ico_image(ico_collection *ico, ico_image *image); static bmp_result bmp_analyse_header(bmp_image *bmp, unsigned char *data); static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes); @@ -294,6 +321,7 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { int32_t width, height; uint8_t palette_size; unsigned int flags; + uint32_t colour_table_size; /* a variety of different bitmap headers can follow, depending * on the BMP variant. A full description of the various headers @@ -464,8 +492,18 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { * if the palette is from an OS/2 or Win2.x file then the entries * are padded with an extra byte. */ - if (bmp->buffer_size < (14 + header_size + (4 * bmp->colours))) + + /* boundary checking */ + if (!uint32_mult(bmp->colours, 4, &colour_table_size)) return BMP_INSUFFICIENT_DATA; + if (!uint32_add(BMP_FILE_HEADER_SIZE, colour_table_size, &colour_table_size)) + return BMP_INSUFFICIENT_DATA; + if (!uint32_add(header_size, colour_table_size, &colour_table_size)) + return BMP_INSUFFICIENT_DATA; + if (bmp->buffer_size < colour_table_size) + return BMP_INSUFFICIENT_DATA; + + /* create the colour table */ bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4); if (!bmp->colour_table) return BMP_INSUFFICIENT_MEMORY; -- cgit v1.2.3