From ab0d378fb408ec1192797be4094c7f8f0233ff5e Mon Sep 17 00:00:00 2001 From: Sean Fox Date: Sat, 24 Jan 2009 22:46:29 +0000 Subject: Properly avoid overflows of width and height and cast integers to 64-bit where necessary to do proper calculations. svn path=/trunk/libnsbmp/; revision=6254 --- libnsbmp.c | 53 ++++++++++------------------------------------------- libnsbmp.h | 4 ++-- 2 files changed, 12 insertions(+), 45 deletions(-) diff --git a/libnsbmp.c b/libnsbmp.c index a9cecbf..6101e07 100644 --- a/libnsbmp.c +++ b/libnsbmp.c @@ -106,33 +106,6 @@ 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); @@ -319,9 +292,9 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { uint32_t i; uint8_t j; int32_t width, height; + uint32_t uheight; 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 @@ -342,7 +315,7 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { */ width = read_int16(data, 4); height = read_int16(data, 6); - if (width < 0) + if ((width <= 0) || (height == 0)) return BMP_DATA_ERROR; if (height < 0) { bmp->reversed = true; @@ -418,11 +391,11 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { */ width = read_int32(data, 4); height = read_int32(data, 8); - if (width < 0) + if ((width <= 0) || (height == 0)) return BMP_DATA_ERROR; if (height < 0) { bmp->reversed = true; - height = -height; + uheight = -height; } /* ICOs only support 256*256 resolutions * In the case of the ICO header, the height is actually the added @@ -536,13 +509,7 @@ static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { */ /* boundary checking */ - if (!uint32_mult(bmp->colours, 4, &colour_table_size)) - return BMP_DATA_ERROR; - if (!uint32_add(BMP_FILE_HEADER_SIZE, colour_table_size, &colour_table_size)) - return BMP_DATA_ERROR; - if (!uint32_add(header_size, colour_table_size, &colour_table_size)) - return BMP_DATA_ERROR; - if (bmp->buffer_size < colour_table_size) + if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours))) return BMP_INSUFFICIENT_DATA; /* create the colour table */ @@ -724,7 +691,7 @@ static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes) { top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); + bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; skip = bmp->bpp >> 3; @@ -801,7 +768,7 @@ static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes) { top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); + bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; bmp->decoded = true; @@ -889,7 +856,7 @@ static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) { top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); + bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; bmp->decoded = true; @@ -942,7 +909,7 @@ static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes) { top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); + bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; @@ -990,7 +957,7 @@ static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int s top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; - bottom = top + swidth * (bmp->height - 1); + bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; bmp->decoded = true; diff --git a/libnsbmp.h b/libnsbmp.h index 9e9f92f..4bdda23 100644 --- a/libnsbmp.h +++ b/libnsbmp.h @@ -70,8 +70,8 @@ typedef struct bmp_bitmap_callback_vt_s { typedef struct bmp_image { bmp_bitmap_callback_vt bitmap_callbacks; /**< callbacks for bitmap functions */ uint8_t *bmp_data; /** pointer to BMP data */ - uint16_t width; /** width of BMP (valid after _analyse) */ - uint16_t height; /** heigth of BMP (valid after _analyse) */ + uint32_t width; /** width of BMP (valid after _analyse) */ + uint32_t height; /** heigth of BMP (valid after _analyse) */ bool decoded; /** whether the image has been decoded */ void *bitmap; /** decoded image */ /** Internal members are listed below -- cgit v1.2.1