From e919bcd32e504c7878b2898ac41725dc5abe78b2 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 22 Mar 2020 00:17:25 -0400 Subject: [PATCH] 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"). --- stb_image.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2857f05..c34757d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -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)