summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Fox <dyntryx@gmail.com>2009-01-24 22:46:29 +0000
committerSean Fox <dyntryx@gmail.com>2009-01-24 22:46:29 +0000
commitab0d378fb408ec1192797be4094c7f8f0233ff5e (patch)
tree53e97cc73458775720f2d528199a1a63f4242cdf
parent3a18e3f0cdebb54504d083419377529d1465cf64 (diff)
downloadlibnsbmp-ab0d378fb408ec1192797be4094c7f8f0233ff5e.tar.gz
libnsbmp-ab0d378fb408ec1192797be4094c7f8f0233ff5e.tar.bz2
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
-rw-r--r--libnsbmp.c53
-rw-r--r--libnsbmp.h4
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