stb_image: fix assert failing when loading BMP

This fixes two issues with an assert failing. I tested that the
first part fixes #909 and the second fixes #897.

1. Loading 16/24/32-bit BMP from memory caused an assert to fail
(excluding 16-bit BMP with hsz 12).

img_buffer offset was always compared with the buffer for
stbi_load_from_file() but stbi_load_from_memory() uses an external
buffer.

Resolution: Change s->buffer_start to s->img_buffer_original.

2. Loading BMP with large header from file caused assert to fail.

img_buffer points to stbi_uc buffer_start[128] but the largest BMP
supported has a 138 byte header (hsz 124) causing img_buffer to wrap
around to an offset of 10. The assert fails because 138 (header size)
!= 10 (offset in temp read buffer).

Resolution: Add the previously read bytes to the offset in temp read
buffer to get the absolute offset.

The issues were introduced by the commit c440a53d06
("stb_image: fix reading BMP with explicit masks").
This commit is contained in:
Zack Middleton 2020-03-22 00:17:25 -04:00
parent f54acd4e13
commit e919bcd32e

View File

@ -107,7 +107,7 @@ RECENT REVISION HISTORY:
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
Christian Floisand Kevin Schmidt JR Smith github:darealshinji
Brad Weinberger Matvey Cherevko github:Michaelangel007
Brad Weinberger Matvey Cherevko Zack Middleton github:Michaelangel007
Blazej Dariusz Roszkowski Alexander Veselov
*/
@ -751,6 +751,7 @@ typedef struct
int read_from_callbacks;
int buflen;
stbi_uc buffer_start[128];
int callback_already_read;
stbi_uc *img_buffer, *img_buffer_end;
stbi_uc *img_buffer_original, *img_buffer_original_end;
@ -764,6 +765,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
{
s->io.read = NULL;
s->read_from_callbacks = 0;
s->callback_already_read = 0;
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
}
@ -775,7 +777,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
s->io_user_data = user;
s->buflen = sizeof(s->buffer_start);
s->read_from_callbacks = 1;
s->img_buffer_original = s->buffer_start;
s->callback_already_read = 0;
s->img_buffer = s->img_buffer_original = s->buffer_start;
stbi__refill_buffer(s);
s->img_buffer_original_end = s->img_buffer_end;
}
@ -1499,6 +1502,7 @@ enum
static void stbi__refill_buffer(stbi__context *s)
{
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);
if (n == 0) {
// at end of file, treat same as if from memory, but need to handle case
// where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
@ -5324,7 +5328,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
STBI_ASSERT(info.offset == (s->img_buffer - s->buffer_start));
STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
}
if (info.bpp == 24 && ma == 0xff000000)