summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--include/libnsbmp.h2
-rw-r--r--src/libnsbmp.c63
-rw-r--r--test/decode_bmp.c14
-rw-r--r--test/decode_ico.c10
-rwxr-xr-xtest/runtest.sh4
6 files changed, 47 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index e40cee5..e456758 100644
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,11 @@
#
# Makefile for libnsbmp
#
-# Copyright 2009-2015 John-Mark Bell <jmb@netsurf-browser.org>
+# Copyright 2009-2020 John-Mark Bell <jmb@netsurf-browser.org>
# Component settings
COMPONENT := nsbmp
-COMPONENT_VERSION := 0.1.3
+COMPONENT_VERSION := 0.1.7
# Default to a static library
COMPONENT_TYPE ?= lib-static
diff --git a/include/libnsbmp.h b/include/libnsbmp.h
index 7e90b4a..ad683f0 100644
--- a/include/libnsbmp.h
+++ b/include/libnsbmp.h
@@ -62,8 +62,6 @@ typedef struct bmp_bitmap_callback_vt_s {
bmp_bitmap_cb_destroy bitmap_destroy;
/** Return a pointer to the pixel data in a bitmap. */
bmp_bitmap_cb_get_buffer bitmap_get_buffer;
- /** Find the width of a pixel row in bytes. */
- bmp_bitmap_cb_get_bpp bitmap_get_bpp;
} bmp_bitmap_callback_vt;
/**
diff --git a/src/libnsbmp.c b/src/libnsbmp.c
index 381fcf4..b4da553 100644
--- a/src/libnsbmp.c
+++ b/src/libnsbmp.c
@@ -64,11 +64,17 @@ static inline uint16_t read_uint16(uint8_t *data, unsigned int o) {
}
static inline int32_t read_int32(uint8_t *data, unsigned int o) {
- return (int32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24));
+ return (int32_t) ((unsigned)data[o] |
+ ((unsigned)data[o+1] << 8) |
+ ((unsigned)data[o+2] << 16) |
+ ((unsigned)data[o+3] << 24));
}
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));
+ return (uint32_t) ((unsigned)data[o] |
+ ((unsigned)data[o+1] << 8) |
+ ((unsigned)data[o+2] << 16) |
+ ((unsigned)data[o+3] << 24));
}
@@ -147,7 +153,8 @@ static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
(bmp->bpp != 24) &&
(bmp->bpp != 32))
return BMP_DATA_ERROR;
- bmp->colours = (1 << bmp->bpp);
+ if (bmp->bpp < 16)
+ bmp->colours = (1 << bmp->bpp);
palette_size = 3;
} else if (header_size < 40) {
return BMP_DATA_ERROR;
@@ -265,6 +272,8 @@ static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
for (i = 0; i < 3; i++)
bmp->mask[i] = read_uint32(data, 40 + (i << 2));
} else {
+ if (header_size < 56)
+ return BMP_INSUFFICIENT_DATA;
for (i = 0; i < 4; i++)
bmp->mask[i] = read_uint32(data, 40 + (i << 2));
}
@@ -272,9 +281,9 @@ static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
if (bmp->mask[i] == 0)
break;
for (j = 31; j > 0; j--)
- if (bmp->mask[i] & (1 << j)) {
+ if (bmp->mask[i] & ((unsigned)1 << j)) {
if ((j - 7) > 0)
- bmp->mask[i] &= 0xff << (j - 7);
+ bmp->mask[i] &= (unsigned)0xff << (j - 7);
else
bmp->mask[i] &= 0xff >> (-(j - 7));
bmp->shift[i] = (i << 3) - (j - 7);
@@ -283,7 +292,7 @@ static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
}
}
bmp->colours = read_uint32(data, 32);
- if (bmp->colours == 0)
+ if (bmp->colours == 0 && bmp->bpp < 16)
bmp->colours = (1 << bmp->bpp);
palette_size = 4;
}
@@ -316,11 +325,11 @@ static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data)
if (!bmp->colour_table)
return BMP_INSUFFICIENT_MEMORY;
for (i = 0; i < bmp->colours; i++) {
- bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16);
+ uint32_t colour = data[2] | (data[1] << 8) | (data[0] << 16);
if (bmp->opaque)
- bmp->colour_table[i] |= (0xff << 24);
+ colour |= ((uint32_t)0xff << 24);
data += palette_size;
- bmp->colour_table[i] = read_uint32((uint8_t *)&bmp->colour_table[i],0);
+ bmp->colour_table[i] = read_uint32((uint8_t *)&colour,0);
}
/* some bitmaps have a bad offset if there is a pallete, work
@@ -465,6 +474,9 @@ static bmp_result ico_header_parse(ico_collection *ico, uint8_t *data)
image->bmp.height = 256;
image->bmp.buffer_size = read_uint32(data, 8);
image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12);
+ if (image->bmp.bmp_data + image->bmp.buffer_size >
+ ico->ico_data + ico->buffer_size)
+ return BMP_INSUFFICIENT_DATA;
image->bmp.ico = true;
data += ICO_DIR_ENTRY_SIZE;
@@ -518,7 +530,7 @@ static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes)
assert(bmp->bpp == 32);
data = *start;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -553,7 +565,7 @@ static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes)
scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
/* 32-bit BMPs have alpha masks, but sometimes they're not utilized */
if (bmp->opaque)
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((unsigned)0xff << 24);
data += 4;
scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
}
@@ -564,9 +576,9 @@ static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes)
scanline[x] = bmp->trans_colour;
}
if (bmp->opaque) {
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((unsigned)0xff << 24);
} else {
- scanline[x] |= data[3] << 24;
+ scanline[x] |= (unsigned)data[3] << 24;
}
data += 4;
scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
@@ -600,7 +612,7 @@ static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes)
assert(bmp->bpp == 24);
data = *start;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top) {
return BMP_INSUFFICIENT_MEMORY;
@@ -636,7 +648,7 @@ static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes)
if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) {
scanline[x] = bmp->trans_colour;
} else {
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((uint32_t)0xff << 24);
}
data += 3;
scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
@@ -671,7 +683,7 @@ static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes)
uint16_t word;
data = *start;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -707,7 +719,7 @@ static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes)
else
scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i]));
if (bmp->opaque)
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((unsigned)0xff << 24);
}
data += 2;
scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
@@ -724,7 +736,7 @@ static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes)
((word & (31 << 10)) >> 7);
}
if (bmp->opaque)
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((unsigned)0xff << 24);
data += 2;
scanline[x] = read_uint32((uint8_t *)&scanline[x],0);
}
@@ -758,11 +770,14 @@ static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes)
uint8_t bit_mask = (1 << bmp->bpp) - 1;
uint8_t cur_byte = 0, bit, i;
+ /* Belt and braces, we shouldn't get here unless this holds */
+ assert(ppb >= 1);
+
for (i = 0; i < ppb; i++)
bit_shifts[i] = 8 - ((i + 1) * bmp->bpp);
data = *start;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -781,7 +796,7 @@ static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes)
for (y = 0; y < bmp->height; y++) {
bit = 8;
- if ((data + (bmp->width / ppb)) > end)
+ if ((data + ((bmp->width + ppb - 1) / ppb)) > end)
return BMP_INSUFFICIENT_DATA;
if (bmp->reversed)
scanline = (void *)(top + (y * swidth));
@@ -827,7 +842,7 @@ static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes)
uint32_t x, y, swidth;
uint32_t cur_byte = 0;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -845,7 +860,7 @@ static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes)
cur_byte = *data++;
scanline[x] = read_uint32((uint8_t *)&scanline[x], 0);
if ((cur_byte & 128) == 0) {
- scanline[x] |= (0xff << 24);
+ scanline[x] |= ((unsigned)0xff << 24);
} else {
scanline[x] &= 0xffffff;
}
@@ -882,7 +897,7 @@ bmp_decode_rle8(bmp_image *bmp, uint8_t *data, int bytes)
if (bmp->ico)
return BMP_DATA_ERROR;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
@@ -1036,7 +1051,7 @@ bmp_decode_rle4(bmp_image *bmp, uint8_t *data, int bytes)
if (bmp->ico)
return BMP_DATA_ERROR;
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
+ swidth = sizeof(uint32_t) * bmp->width;
top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap);
if (!top)
return BMP_INSUFFICIENT_MEMORY;
diff --git a/test/decode_bmp.c b/test/decode_bmp.c
index 68de542..a0b02e8 100644
--- a/test/decode_bmp.c
+++ b/test/decode_bmp.c
@@ -17,7 +17,7 @@
#include <sys/stat.h>
#include "../include/libnsbmp.h"
-#define BYTES_PER_PIXEL 4
+#define BYTES_PER_PIXEL sizeof(uint32_t)
#define MAX_IMAGE_BYTES (48 * 1024 * 1024)
#define TRANSPARENT_COLOR 0xffffffff
@@ -25,8 +25,8 @@
static void *bitmap_create(int width, int height, unsigned int state)
{
(void) state; /* unused */
- /* ensure a stupidly large (>50Megs or so) bitmap is not created */
- if (((long long)width * (long long)height) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL)) {
+ /* Ensure a stupidly large bitmap is not created */
+ if (width > 4096 || height > 4096) {
return NULL;
}
return calloc(width * height, BYTES_PER_PIXEL);
@@ -40,13 +40,6 @@ static unsigned char *bitmap_get_buffer(void *bitmap)
}
-static size_t bitmap_get_bpp(void *bitmap)
-{
- (void) bitmap; /* unused */
- return BYTES_PER_PIXEL;
-}
-
-
static void bitmap_destroy(void *bitmap)
{
assert(bitmap);
@@ -144,7 +137,6 @@ int main(int argc, char *argv[])
bitmap_create,
bitmap_destroy,
bitmap_get_buffer,
- bitmap_get_bpp
};
bmp_result code;
bmp_image bmp;
diff --git a/test/decode_ico.c b/test/decode_ico.c
index 5dbc7a5..94db57e 100644
--- a/test/decode_ico.c
+++ b/test/decode_ico.c
@@ -24,7 +24,7 @@
/* Currently the library returns the data in RGBA format,
* so there are 4 bytes per pixel */
-#define BYTES_PER_PIXEL 4
+#define BYTES_PER_PIXEL sizeof(uint32_t)
/* White with alpha masking. */
#define TRANSPARENT_COLOR 0xffffffff
@@ -43,13 +43,6 @@ static unsigned char *bitmap_get_buffer(void *bitmap)
}
-static size_t bitmap_get_bpp(void *bitmap)
-{
- (void) bitmap; /* unused */
- return BYTES_PER_PIXEL;
-}
-
-
static void bitmap_destroy(void *bitmap)
{
assert(bitmap);
@@ -175,7 +168,6 @@ int main(int argc, char *argv[])
bitmap_create,
bitmap_destroy,
bitmap_get_buffer,
- bitmap_get_bpp
};
uint16_t width, height;
ico_collection ico;
diff --git a/test/runtest.sh b/test/runtest.sh
index f3c047d..544c262 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -67,7 +67,7 @@ for BMP in $(ls ${BMPTESTS});do
BMPTESTTOTC=$((BMPTESTTOTC+1))
bmpdecode ${BMP}
ECODE=$?
- if [ "${ECODE}" -gt 127 ];then
+ if [ \( "${ECODE}" -gt 127 \) -o \( "${ECODE}" -eq 1 \) ];then
BMPTESTERRC=$((BMPTESTERRC+1))
else
BMPTESTPASSC=$((BMPTESTPASSC+1))
@@ -89,7 +89,7 @@ for ICO in $(ls ${ICOTESTS});do
ICOTESTTOTC=$((ICOTESTTOTC+1))
icodecode ${ICO}
ECODE=$?
- if [ "${ECODE}" -gt 127 ];then
+ if [ \( "${ECODE}" -gt 127 \) -o \( "${ECODE}" -eq 1 \) ];then
ICOTESTERRC=$((ICOTESTERRC+1))
else
ICOTESTPASSC=$((ICOTESTPASSC+1))