Add input checks, fix overflow/wrap related bugs

This commit is contained in:
2025-08-04 20:35:19 +03:00
parent deb4ec00f4
commit 4ce443f0d9
4 changed files with 137 additions and 113 deletions

View File

@@ -113,8 +113,8 @@ I<BH_BITMAP_RGBA32> pixel format.
=head2 BH_BitmapNew =head2 BH_BitmapNew
BH_Bitmap *BH_BitmapNew(int width, BH_Bitmap *BH_BitmapNew(uint32_t width,
int height, uint32_t height,
int format, int format,
int flags, int flags,
void *data, void *data,
@@ -149,8 +149,8 @@ Destroys the bitmap object.
=head2 BH_BitmapColor =head2 BH_BitmapColor
void BH_BitmapColor(const BH_Bitmap *bitmap, void BH_BitmapColor(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
BH_Color *value); BH_Color *value);
Reads color value of the pixel at specified position. Reads color value of the pixel at specified position.
@@ -161,8 +161,8 @@ The I<x> and I<y> parameters specify a position on the bitmap.
=head2 BH_BitmapSetColor =head2 BH_BitmapSetColor
void BH_BitmapSetColor(BH_Bitmap *bitmap, void BH_BitmapSetColor(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
const BH_Color *value); const BH_Color *value);
Writes color value of the pixel at specified position. Writes color value of the pixel at specified position.
@@ -173,8 +173,8 @@ The I<x> and I<y> parameters specify a position on the bitmap.
=head2 BH_BitmapIndex =head2 BH_BitmapIndex
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap, uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
Returns the index value at the specified position. Returns the index value at the specified position.
@@ -184,8 +184,8 @@ The I<x> and I<y> parameters specify a position on the bitmap.
=head2 BH_BitmapSetIndex =head2 BH_BitmapSetIndex
void BH_BitmapSetIndex(BH_Bitmap *bitmap, void BH_BitmapSetIndex(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
uint8_t index); uint8_t index);
Sets the index value at the specified position. Sets the index value at the specified position.
@@ -196,10 +196,10 @@ The I<x> and I<y> parameters specify a position on the bitmap.
=head2 BH_BitmapCopy =head2 BH_BitmapCopy
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap, BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
int width, uint32_t width,
int height, uint32_t height,
int shallow); int shallow);
Creates a copy of the bitmap region by the given position and size. Creates a copy of the bitmap region by the given position and size.
@@ -218,7 +218,7 @@ This function returns a pointer to a new BH_Bitmap object or NULL.
=head2 BH_BitmapScanline =head2 BH_BitmapScanline
void *BH_BitmapScanline(const BH_Bitmap *bitmap, void *BH_BitmapScanline(const BH_Bitmap *bitmap,
int y); uint32_t y);
Returns address of the scanline in the bitmap. Returns address of the scanline in the bitmap.
@@ -226,22 +226,22 @@ Returns address of the scanline in the bitmap.
=head2 BH_BitmapAt =head2 BH_BitmapAt
void *BH_BitmapAt(const BH_Bitmap *bitmap, void *BH_BitmapAt(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
Returns address of the pixel in the bitmap. Returns address of the pixel in the bitmap.
=head2 BH_BitmapWidth =head2 BH_BitmapWidth
int BH_BitmapWidth(BH_Bitmap *bitmap); uint32_t BH_BitmapWidth(BH_Bitmap *bitmap);
Returns width of the bitmap. Returns width of the bitmap.
=head2 BH_BitmapHeight =head2 BH_BitmapHeight
int BH_BitmapHeight(BH_Bitmap *bitmap); uint32_t BH_BitmapHeight(BH_Bitmap *bitmap);
Returns height of the bitmap. Returns height of the bitmap.

View File

@@ -114,12 +114,12 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
=head2 BH_BitmapNew =head2 BH_BitmapNew
BH_Bitmap *BH_BitmapNew(int width, BH_Bitmap *BH_BitmapNew(uint32_t width,
int height, uint32_t height,
int format, int format,
int flags, int flags,
void *data, void *data,
void *palette); void *palette);
Создает растровое изображение с указанной шириной, высотой и пиксельным Создает растровое изображение с указанной шириной, высотой и пиксельным
форматом. форматом.
@@ -155,8 +155,8 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
=head2 BH_BitmapColor =head2 BH_BitmapColor
void BH_BitmapColor(const BH_Bitmap *bitmap, void BH_BitmapColor(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
BH_Color *value); BH_Color *value);
Считывает значение цвета пикселя в указанной позиции. Считывает значение цвета пикселя в указанной позиции.
@@ -167,8 +167,8 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
=head2 BH_BitmapSetColor =head2 BH_BitmapSetColor
void BH_BitmapSetColor(BH_Bitmap *bitmap, void BH_BitmapSetColor(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
const BH_Color *value); const BH_Color *value);
Записывает значение цвета пикселя в указанной позиции. Записывает значение цвета пикселя в указанной позиции.
@@ -179,8 +179,8 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
=head2 BH_BitmapIndex =head2 BH_BitmapIndex
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap, uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
Возвращает значение индекса в указанной позиции. Возвращает значение индекса в указанной позиции.
@@ -190,8 +190,8 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
=head2 BH_BitmapSetIndex =head2 BH_BitmapSetIndex
void BH_BitmapSetIndex(BH_Bitmap *bitmap, void BH_BitmapSetIndex(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
uint8_t index); uint8_t index);
Устанавливает значение индекса в указанной позиции. Устанавливает значение индекса в указанной позиции.
@@ -202,10 +202,10 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
=head2 BH_BitmapCopy =head2 BH_BitmapCopy
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap, BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
int width, uint32_t width,
int height, uint32_t height,
int shallow); int shallow);
Создает копию области растрового изображения с заданным положением и размером. Создает копию области растрового изображения с заданным положением и размером.
@@ -225,7 +225,7 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
=head2 BH_BitmapScanline =head2 BH_BitmapScanline
void *BH_BitmapScanline(const BH_Bitmap *bitmap, void *BH_BitmapScanline(const BH_Bitmap *bitmap,
int y); uint32_t y);
Возвращает адрес строки сканирования в растровом изображении. Возвращает адрес строки сканирования в растровом изображении.
@@ -233,22 +233,22 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
=head2 BH_BitmapAt =head2 BH_BitmapAt
void *BH_BitmapAt(const BH_Bitmap *bitmap, void *BH_BitmapAt(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
Возвращает адрес пикселя в растровом изображении. Возвращает адрес пикселя в растровом изображении.
=head2 BH_BitmapWidth =head2 BH_BitmapWidth
int BH_BitmapWidth(BH_Bitmap *bitmap); uint32_t BH_BitmapWidth(BH_Bitmap *bitmap);
Возвращает ширину растрового изображения. Возвращает ширину растрового изображения.
=head2 BH_BitmapHeight =head2 BH_BitmapHeight
int BH_BitmapHeight(BH_Bitmap *bitmap); uint32_t BH_BitmapHeight(BH_Bitmap *bitmap);
Возвращает высоту растрового изображения. Возвращает высоту растрового изображения.

View File

@@ -35,8 +35,8 @@ typedef struct BH_Bitmap BH_Bitmap;
#define BH_BITMAP_FLAG_EXT_PALETTE 0x0004 #define BH_BITMAP_FLAG_EXT_PALETTE 0x0004
BH_Bitmap *BH_BitmapNew(int width, BH_Bitmap *BH_BitmapNew(uint32_t width,
int height, uint32_t height,
int format, int format,
int flags, int flags,
void *data, void *data,
@@ -47,49 +47,49 @@ void BH_BitmapFree(BH_Bitmap *bitmap);
void BH_BitmapColor(const BH_Bitmap *bitmap, void BH_BitmapColor(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
BH_Color *value); BH_Color *value);
void BH_BitmapSetColor(BH_Bitmap *bitmap, void BH_BitmapSetColor(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
const BH_Color *value); const BH_Color *value);
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap, uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
void BH_BitmapSetIndex(BH_Bitmap *bitmap, void BH_BitmapSetIndex(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
uint8_t index); uint8_t index);
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap, BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
int width, uint32_t width,
int height, uint32_t height,
int shallow); int shallow);
void *BH_BitmapScanline(const BH_Bitmap *bitmap, void *BH_BitmapScanline(const BH_Bitmap *bitmap,
int y); uint32_t y);
void *BH_BitmapAt(const BH_Bitmap *bitmap, void *BH_BitmapAt(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y); uint32_t y);
int BH_BitmapWidth(BH_Bitmap *bitmap); uint32_t BH_BitmapWidth(BH_Bitmap *bitmap);
int BH_BitmapHeight(BH_Bitmap *bitmap); uint32_t BH_BitmapHeight(BH_Bitmap *bitmap);
int BH_BitmapFormat(BH_Bitmap *bitmap); int BH_BitmapFormat(BH_Bitmap *bitmap);

View File

@@ -9,8 +9,8 @@
struct BH_Bitmap struct BH_Bitmap
{ {
int width; uint32_t width;
int height; uint32_t height;
int format; int format;
int flags; int flags;
size_t step; size_t step;
@@ -131,7 +131,7 @@ static size_t calculateStep(int format)
static uint8_t bitmapIndex(void *data, static uint8_t bitmapIndex(void *data,
int format, int format,
int x) uint32_t x)
{ {
int isLSB; int isLSB;
uint8_t octet; uint8_t octet;
@@ -161,7 +161,7 @@ static uint8_t bitmapIndex(void *data,
static void setBitmapIndex(void *data, static void setBitmapIndex(void *data,
int format, int format,
int x, uint32_t x,
uint8_t index) uint8_t index)
{ {
int isLSB; int isLSB;
@@ -199,7 +199,7 @@ static void bitmapColor(void *data,
void *palette, void *palette,
int format, int format,
BH_Color *value, BH_Color *value,
int x) uint32_t x)
{ {
switch (format & 0x0FFF) switch (format & 0x0FFF)
{ {
@@ -423,7 +423,7 @@ static void setBitmapColor(void *data,
void *palette, void *palette,
int format, int format,
const BH_Color *value, const BH_Color *value,
int x) uint32_t x)
{ {
switch (format & 0x0FFF) switch (format & 0x0FFF)
{ {
@@ -611,7 +611,7 @@ static void setBitmapColor(void *data,
static void *rowAt(void *data, static void *rowAt(void *data,
int format, int format,
int step, int step,
int x) uint32_t x)
{ {
switch (format & 0x0FFF) switch (format & 0x0FFF)
{ {
@@ -631,16 +631,22 @@ static void *rowAt(void *data,
static size_t calculateStride(int format, static size_t calculateStride(int format,
int width) uint32_t width)
{ {
size_t step;
switch (format & 0x0FFF) switch (format & 0x0FFF)
{ {
case BH_BITMAP_INDEX1: return (width + 7) / 8; case BH_BITMAP_INDEX1: return (width + 7) / 8;
case BH_BITMAP_INDEX2: return (width + 3) / 4; case BH_BITMAP_INDEX2: return (width + 3) / 4;
case BH_BITMAP_INDEX4: return (width + 1) / 2; case BH_BITMAP_INDEX4: return (width + 1) / 2;
case BH_BITMAP_INDEX8: return width * calculateStep(format);
} }
return width * calculateStep(format);
step = calculateStep(format);
if (BH_CHECK_UMUL_WRAP(step, width, size_t))
return 0;
return step * width;
} }
@@ -673,8 +679,8 @@ static size_t calculateTrailer(int format)
/* Public functions */ /* Public functions */
BH_Bitmap *BH_BitmapNew(int width, BH_Bitmap *BH_BitmapNew(uint32_t width,
int height, uint32_t height,
int format, int format,
int flags, int flags,
void *data, void *data,
@@ -682,7 +688,12 @@ BH_Bitmap *BH_BitmapNew(int width,
{ {
BH_Bitmap *result; BH_Bitmap *result;
int needPalette; int needPalette;
size_t header, body, trailer, stride, step; size_t header, body, allocSize, stride, step;
/* Basic sanity check */
if (width == 0 || width >= 0x7FFFFFFF ||
height == 0 || height >= 0x7FFFFFFF)
return NULL;
/* Unset internal flags */ /* Unset internal flags */
flags &= ~BH_BITMAP_FLAG_EXT_DATA; flags &= ~BH_BITMAP_FLAG_EXT_DATA;
@@ -693,19 +704,35 @@ BH_Bitmap *BH_BitmapNew(int width,
stride = calculateStride(format, width); stride = calculateStride(format, width);
needPalette = isPaletteNeeded(format); needPalette = isPaletteNeeded(format);
/* Check stride overflow */
if (!stride)
return NULL;
if (flags & BH_BITMAP_FLAG_ALIGN32) if (flags & BH_BITMAP_FLAG_ALIGN32)
{
if (BH_CHECK_UADD_WRAP(stride, sizeof(uint32_t) - 1, size_t))
return NULL;
stride = (stride + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); stride = (stride + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
}
header = sizeof(*result); header = sizeof(*result);
header = (header + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1); header = (header + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1);
body = (stride * height + (sizeof(uint32_t) - 1)) & ~(sizeof(uint32_t) - 1); allocSize = calculateTrailer(format);
trailer = calculateTrailer(format);
body = stride * height;
if (BH_CHECK_UMUL_WRAP(stride, height, size_t))
return NULL;
if (BH_CHECK_UADD_WRAP(body, sizeof(uint32_t) - 1, size_t))
return NULL;
body = (body + (sizeof(uint32_t) - 1)) & ~(sizeof(uint32_t) - 1);
/* Adjust body and trailer size if ext data or palette is provided */ /* Adjust body and trailer size if ext data or palette is provided */
if (palette) if (palette)
{ {
flags |= BH_BITMAP_FLAG_EXT_PALETTE; flags |= BH_BITMAP_FLAG_EXT_PALETTE;
trailer = 0; allocSize = 0;
} }
if (data) if (data)
@@ -714,8 +741,16 @@ BH_Bitmap *BH_BitmapNew(int width,
body = 0; body = 0;
} }
if (BH_CHECK_UADD_WRAP(allocSize, header, size_t))
return NULL;
allocSize += header;
if (BH_CHECK_UADD_WRAP(allocSize, body, size_t))
return NULL;
allocSize += body;
/* Allocate and setup bitmap data */ /* Allocate and setup bitmap data */
result = malloc(header + body + trailer); result = malloc(allocSize);
if (!result) if (!result)
return NULL; return NULL;
@@ -745,16 +780,16 @@ void BH_BitmapFree(BH_Bitmap *bitmap)
void BH_BitmapColor(const BH_Bitmap *bitmap, void BH_BitmapColor(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
BH_Color *value) BH_Color *value)
{ {
bitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x); bitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
} }
void BH_BitmapSetColor(BH_Bitmap *bitmap, void BH_BitmapSetColor(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
const BH_Color *value) const BH_Color *value)
{ {
setBitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x); setBitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
@@ -762,33 +797,28 @@ void BH_BitmapSetColor(BH_Bitmap *bitmap,
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap, BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
int width, uint32_t width,
int height, uint32_t height,
int shallow) int shallow)
{ {
BH_Bitmap *result; BH_Bitmap *result;
int i, j; uint32_t i, j;
/* Check for bogus width and height */ /* Sanity checks */
if (width < 0 || height < 0) if (!width || !height || x >= bitmap->width || y >= bitmap->height)
return NULL;
if (width < bitmap->width - x || height < bitmap->height - y)
return NULL; return NULL;
/* Shallow copy can't go out of bounds of the source bitmap */ /* Shallow copy can't go out of bounds of the source bitmap */
if (shallow) if (shallow)
{ {
if (x < 0 || x > bitmap->width || y < 0 || y > bitmap->height)
return NULL;
if (width < 0 || width > bitmap->width - x ||
height < 0 || height > bitmap->height - y)
return NULL;
result = BH_BitmapNew(width, height, bitmap->format, bitmap->flags, result = BH_BitmapNew(width, height, bitmap->format, bitmap->flags,
BH_BitmapAt(bitmap, x, y), bitmap->palette); BH_BitmapAt(bitmap, x, y), bitmap->palette);
result->stride = bitmap->stride; result->stride = bitmap->stride;
return result; return result;
} }
@@ -806,13 +836,7 @@ BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
for (i = 0; i < width; ++i) for (i = 0; i < width; ++i)
{ {
BH_Color color; BH_Color color;
memset(&color, 0, sizeof(color)); BH_BitmapColor(bitmap, i + x, j + y, &color);
if (i + x >= 0 && i + x < bitmap->width &&
j + y >= 0 && j + y < bitmap->height)
BH_BitmapColor(bitmap, i + x, j + y, &color);
BH_BitmapSetColor(result, i, j, &color); BH_BitmapSetColor(result, i, j, &color);
} }
} }
@@ -822,16 +846,16 @@ BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap, uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y) uint32_t y)
{ {
return bitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x); return bitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x);
} }
void BH_BitmapSetIndex(BH_Bitmap *bitmap, void BH_BitmapSetIndex(BH_Bitmap *bitmap,
int x, uint32_t x,
int y, uint32_t y,
uint8_t index) uint8_t index)
{ {
setBitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x, index); setBitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x, index);
@@ -839,27 +863,27 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
void *BH_BitmapScanline(const BH_Bitmap *bitmap, void *BH_BitmapScanline(const BH_Bitmap *bitmap,
int y) uint32_t y)
{ {
return bitmap->data + y * bitmap->stride; return bitmap->data + y * bitmap->stride;
} }
void *BH_BitmapAt(const BH_Bitmap *bitmap, void *BH_BitmapAt(const BH_Bitmap *bitmap,
int x, uint32_t x,
int y) uint32_t y)
{ {
return rowAt(BH_BitmapScanline(bitmap, y), bitmap->format, bitmap->step, x); return rowAt(BH_BitmapScanline(bitmap, y), bitmap->format, bitmap->step, x);
} }
int BH_BitmapWidth(BH_Bitmap *bitmap) uint32_t BH_BitmapWidth(BH_Bitmap *bitmap)
{ {
return bitmap->width; return bitmap->width;
} }
int BH_BitmapHeight(BH_Bitmap *bitmap) uint32_t BH_BitmapHeight(BH_Bitmap *bitmap)
{ {
return bitmap->height; return bitmap->height;
} }