Update stb_image to 2.26.

This commit is contained in:
Bartosz Taudul 2020-07-31 01:42:57 +02:00
parent 2be3f1766f
commit 6866d8f429
2 changed files with 690 additions and 260 deletions

View File

@ -1,4 +1,4 @@
/* stb_image - v2.22 - public domain image loader - http://nothings.org/stb /* stb_image - v2.26 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -48,6 +48,10 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.26 (2020-07-13) many minor fixes
2.25 (2020-02-02) fix warnings
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
2.23 (2019-08-11) fix clang static analysis warning
2.22 (2019-03-04) gif fixes, fix warnings 2.22 (2019-03-04) gif fixes, fix warnings
2.21 (2019-02-25) fix typo in comment 2.21 (2019-02-25) fix typo in comment
2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
@ -90,21 +94,30 @@ RECENT REVISION HISTORY:
Carmelo J Fdez-Aguera Carmelo J Fdez-Aguera
Bug & warning fixes Bug & warning fixes
Marc LeBlanc David Woo Guillaume George Martins Mozeiko Marc LeBlanc David Woo Guillaume George Martins Mozeiko
Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
Dave Moore Roy Eltham Hayaki Saito Nathan Reed Phil Jordan Dave Moore Roy Eltham
Won Chun Luke Graham Johan Duparc Nick Verigakis Hayaki Saito Nathan Reed Won Chun
the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh Luke Graham Johan Duparc Nick Verigakis the Horde3D community
Janez Zemva John Bartholomew Michal Cichon github:romigrou Thomas Ruf Ronny Chevalier github:rlyeh
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk Janez Zemva John Bartholomew Michal Cichon github:romigrou
Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex Laurent Gomila Cort Stratton github:snagar
Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex
Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw Cass Everitt Ryamond Barbiero github:grim210
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
Christian Floisand Kevin Schmidt JR Smith github:darealshinji Josh Tobin Matthew Gregan github:poppolopoppo
Blazej Dariusz Roszkowski github:Michaelangel007 Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
Brad Weinberger Matvey Cherevko [reserved]
Luca Sas Alexander Veselov Zack Middleton [reserved]
Ryan C. Gordon [reserved] [reserved]
DO NOT ADD YOUR NAME HERE
To add your name to the credits, pick a random blank space in the middle and fill it.
80% of merge conflicts on stb PRs are due to people adding their name at the end
of the credits.
*/ */
#ifndef STBI_INCLUDE_STB_IMAGE_H #ifndef STBI_INCLUDE_STB_IMAGE_H
@ -314,7 +327,14 @@ RECENT REVISION HISTORY:
// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
// //
// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
// than that size (in either width or height) without further processing.
// This is to let programs in the wild set an upper bound to prevent
// denial-of-service attacks on untrusted data, as one could generate a
// valid image of gigantic dimensions and force stb_image to allocate a
// huge block of memory and spend disproportionate time decoding it. By
// default this is set to (1 << 24), which is 16777216, but that's still
// very big.
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
#include <stdio.h> #include <stdio.h>
@ -433,7 +453,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f);
// get a VERY brief reason for failure // get a VERY brief reason for failure
// NOT THREADSAFE // on most compilers (and ALL modern mainstream compilers) this is threadsafe
STBIDEF const char *stbi_failure_reason (void); STBIDEF const char *stbi_failure_reason (void);
// free the loaded image -- this is just free() // free the loaded image -- this is just free()
@ -466,6 +486,11 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically, so the first pixel in the output array is the bottom left // flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// as above, but only applies to images loaded on the thread that calls the function
// this function is only available if your compiler supports thread-local variables;
// calling it will fail to link if your compiler doesn't
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes // ZLIB client - used by PNG, available for other purposes
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
@ -562,6 +587,23 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#define stbi_inline __forceinline #define stbi_inline __forceinline
#endif #endif
#ifndef STBI_NO_THREAD_LOCALS
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STBI_THREAD_LOCAL thread_local
#elif defined(__GNUC__) && __GNUC__ < 5
#define STBI_THREAD_LOCAL __thread
#elif defined(_MSC_VER)
#define STBI_THREAD_LOCAL __declspec(thread)
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
#define STBI_THREAD_LOCAL _Thread_local
#endif
#ifndef STBI_THREAD_LOCAL
#if defined(__GNUC__)
#define STBI_THREAD_LOCAL __thread
#endif
#endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned short stbi__uint16; typedef unsigned short stbi__uint16;
@ -714,6 +756,10 @@ static int stbi__sse2_available(void)
#define STBI_SIMD_ALIGN(type, name) type name #define STBI_SIMD_ALIGN(type, name) type name
#endif #endif
#ifndef STBI_MAX_DIMENSIONS
#define STBI_MAX_DIMENSIONS (1 << 24)
#endif
/////////////////////////////////////////////// ///////////////////////////////////////////////
// //
// stbi__context struct and start_xxx functions // stbi__context struct and start_xxx functions
@ -731,6 +777,7 @@ typedef struct
int read_from_callbacks; int read_from_callbacks;
int buflen; int buflen;
stbi_uc buffer_start[128]; stbi_uc buffer_start[128];
int callback_already_read;
stbi_uc *img_buffer, *img_buffer_end; stbi_uc *img_buffer, *img_buffer_end;
stbi_uc *img_buffer_original, *img_buffer_original_end; stbi_uc *img_buffer_original, *img_buffer_original_end;
@ -744,6 +791,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
{ {
s->io.read = NULL; s->io.read = NULL;
s->read_from_callbacks = 0; s->read_from_callbacks = 0;
s->callback_already_read = 0;
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
} }
@ -755,7 +803,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
s->io_user_data = user; s->io_user_data = user;
s->buflen = sizeof(s->buffer_start); s->buflen = sizeof(s->buffer_start);
s->read_from_callbacks = 1; 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); stbi__refill_buffer(s);
s->img_buffer_original_end = s->img_buffer_end; s->img_buffer_original_end = s->img_buffer_end;
} }
@ -769,12 +818,17 @@ static int stbi__stdio_read(void *user, char *data, int size)
static void stbi__stdio_skip(void *user, int n) static void stbi__stdio_skip(void *user, int n)
{ {
int ch;
fseek((FILE*) user, n, SEEK_CUR); fseek((FILE*) user, n, SEEK_CUR);
ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */
if (ch != EOF) {
ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */
}
} }
static int stbi__stdio_eof(void *user) static int stbi__stdio_eof(void *user)
{ {
return feof((FILE*) user); return feof((FILE*) user) || ferror((FILE *) user);
} }
static stbi_io_callbacks stbi__stdio_callbacks = static stbi_io_callbacks stbi__stdio_callbacks =
@ -872,19 +926,24 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif #endif
// this is not threadsafe static
static const char *stbi__g_failure_reason; #ifdef STBI_THREAD_LOCAL
STBI_THREAD_LOCAL
#endif
const char *stbi__g_failure_reason;
STBIDEF const char *stbi_failure_reason(void) STBIDEF const char *stbi_failure_reason(void)
{ {
return stbi__g_failure_reason; return stbi__g_failure_reason;
} }
#ifndef STBI_NO_FAILURE_STRINGS
static int stbi__err(const char *str) static int stbi__err(const char *str)
{ {
stbi__g_failure_reason = str; stbi__g_failure_reason = str;
return 0; return 0;
} }
#endif
static void *stbi__malloc(size_t size) static void *stbi__malloc(size_t size)
{ {
@ -923,11 +982,13 @@ static int stbi__mul2sizes_valid(int a, int b)
return a <= INT_MAX/b; return a <= INT_MAX/b;
} }
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
static int stbi__mad2sizes_valid(int a, int b, int add) static int stbi__mad2sizes_valid(int a, int b, int add)
{ {
return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
} }
#endif
// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
static int stbi__mad3sizes_valid(int a, int b, int c, int add) static int stbi__mad3sizes_valid(int a, int b, int c, int add)
@ -945,12 +1006,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
} }
#endif #endif
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// mallocs with size overflow checking // mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add) static void *stbi__malloc_mad2(int a, int b, int add)
{ {
if (!stbi__mad2sizes_valid(a, b, add)) return NULL; if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
return stbi__malloc(a*b + add); return stbi__malloc(a*b + add);
} }
#endif
static void *stbi__malloc_mad3(int a, int b, int c, int add) static void *stbi__malloc_mad3(int a, int b, int c, int add)
{ {
@ -994,13 +1057,29 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif #endif
static int stbi__vertically_flip_on_load = 0; static int stbi__vertically_flip_on_load_global = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{ {
stbi__vertically_flip_on_load = flag_true_if_should_flip; stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
} }
#ifndef STBI_THREAD_LOCAL
#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
#else
static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
stbi__vertically_flip_on_load_set = 1;
}
#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \
? stbi__vertically_flip_on_load_local \
: stbi__vertically_flip_on_load_global)
#endif // STBI_THREAD_LOCAL
static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
{ {
memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
@ -1022,6 +1101,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
#endif #endif
#ifndef STBI_NO_PSD #ifndef STBI_NO_PSD
if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
#else
STBI_NOTUSED(bpc);
#endif #endif
#ifndef STBI_NO_PIC #ifndef STBI_NO_PIC
if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
@ -1124,8 +1205,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
if (result == NULL) if (result == NULL)
return NULL; return NULL;
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
if (ri.bits_per_channel != 8) { if (ri.bits_per_channel != 8) {
STBI_ASSERT(ri.bits_per_channel == 16);
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 8; ri.bits_per_channel = 8;
} }
@ -1148,8 +1231,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
if (result == NULL) if (result == NULL)
return NULL; return NULL;
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
if (ri.bits_per_channel != 16) { if (ri.bits_per_channel != 16) {
STBI_ASSERT(ri.bits_per_channel == 8);
result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 16; ri.bits_per_channel = 16;
} }
@ -1452,6 +1537,7 @@ enum
static void stbi__refill_buffer(stbi__context *s) static void stbi__refill_buffer(stbi__context *s)
{ {
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); 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) { if (n == 0) {
// at end of file, treat same as if from memory, but need to handle case // 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 // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
@ -1476,6 +1562,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s)
return 0; return 0;
} }
#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
stbi_inline static int stbi__at_eof(stbi__context *s) stbi_inline static int stbi__at_eof(stbi__context *s)
{ {
if (s->io.read) { if (s->io.read) {
@ -1487,9 +1576,14 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
return s->img_buffer >= s->img_buffer_end; return s->img_buffer >= s->img_buffer_end;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
// nothing
#else
static void stbi__skip(stbi__context *s, int n) static void stbi__skip(stbi__context *s, int n)
{ {
if (n == 0) return; // already there!
if (n < 0) { if (n < 0) {
s->img_buffer = s->img_buffer_end; s->img_buffer = s->img_buffer_end;
return; return;
@ -1504,7 +1598,11 @@ static void stbi__skip(stbi__context *s, int n)
} }
s->img_buffer += n; s->img_buffer += n;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
// nothing
#else
static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
{ {
if (s->io.read) { if (s->io.read) {
@ -1528,18 +1626,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
} else } else
return 0; return 0;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static int stbi__get16be(stbi__context *s) static int stbi__get16be(stbi__context *s)
{ {
int z = stbi__get8(s); int z = stbi__get8(s);
return (z << 8) + stbi__get8(s); return (z << 8) + stbi__get8(s);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static stbi__uint32 stbi__get32be(stbi__context *s) static stbi__uint32 stbi__get32be(stbi__context *s)
{ {
stbi__uint32 z = stbi__get16be(s); stbi__uint32 z = stbi__get16be(s);
return (z << 16) + stbi__get16be(s); return (z << 16) + stbi__get16be(s);
} }
#endif
#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
// nothing // nothing
@ -1561,7 +1668,9 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// generic converter from built-in img_n to req_comp // generic converter from built-in img_n to req_comp
@ -1577,7 +1686,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b)
{ {
return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1613,7 +1726,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
} }
#undef STBI__CASE #undef STBI__CASE
} }
@ -1621,12 +1734,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 stbi__compute_y_16(int r, int g, int b) static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
{ {
return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1662,7 +1783,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
} }
#undef STBI__CASE #undef STBI__CASE
} }
@ -1670,6 +1791,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#ifndef STBI_NO_LINEAR #ifndef STBI_NO_LINEAR
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
@ -1970,7 +2092,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
k = stbi_lrot(j->code_buffer, n); k = stbi_lrot(j->code_buffer, n);
STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0;
j->code_buffer = k & ~stbi__bmask[n]; j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n]; k &= stbi__bmask[n];
j->code_bits -= n; j->code_bits -= n;
@ -2081,6 +2203,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
// first scan for DC coefficient, must be first // first scan for DC coefficient, must be first
memset(data,0,64*sizeof(data[0])); // 0 all the ac values now memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
t = stbi__jpeg_huff_decode(j, hdc); t = stbi__jpeg_huff_decode(j, hdc);
if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
diff = t ? stbi__extend_receive(j, t) : 0; diff = t ? stbi__extend_receive(j, t) : 0;
dc = j->img_comp[b].dc_pred + diff; dc = j->img_comp[b].dc_pred + diff;
@ -3071,6 +3194,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
c = stbi__get8(s); c = stbi__get8(s);
if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
s->img_n = c; s->img_n = c;
@ -3951,16 +4076,23 @@ typedef struct
stbi__zhuffman z_length, z_distance; stbi__zhuffman z_length, z_distance;
} stbi__zbuf; } stbi__zbuf;
stbi_inline static int stbi__zeof(stbi__zbuf *z)
{
return (z->zbuffer >= z->zbuffer_end);
}
stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
{ {
if (z->zbuffer >= z->zbuffer_end) return 0; return stbi__zeof(z) ? 0 : *z->zbuffer++;
return *z->zbuffer++;
} }
static void stbi__fill_bits(stbi__zbuf *z) static void stbi__fill_bits(stbi__zbuf *z)
{ {
do { do {
STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); if (z->code_buffer >= (1U << z->num_bits)) {
z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
return;
}
z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
z->num_bits += 8; z->num_bits += 8;
} while (z->num_bits <= 24); } while (z->num_bits <= 24);
@ -3985,10 +4117,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
for (s=STBI__ZFAST_BITS+1; ; ++s) for (s=STBI__ZFAST_BITS+1; ; ++s)
if (k < z->maxcode[s]) if (k < z->maxcode[s])
break; break;
if (s == 16) return -1; // invalid code! if (s >= 16) return -1; // invalid code!
// code size is s, so: // code size is s, so:
b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
STBI_ASSERT(z->size[b] == s); if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere!
if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.
a->code_buffer >>= s; a->code_buffer >>= s;
a->num_bits -= s; a->num_bits -= s;
return z->value[b]; return z->value[b];
@ -3997,7 +4130,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
{ {
int b,s; int b,s;
if (a->num_bits < 16) stbi__fill_bits(a); if (a->num_bits < 16) {
if (stbi__zeof(a)) {
return -1; /* report error for unexpected end of data. */
}
stbi__fill_bits(a);
}
b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) { if (b) {
s = b >> 9; s = b >> 9;
@ -4011,13 +4149,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
{ {
char *q; char *q;
int cur, limit, old_limit; unsigned int cur, limit, old_limit;
z->zout = zout; z->zout = zout;
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
cur = (int) (z->zout - z->zout_start); cur = (unsigned int) (z->zout - z->zout_start);
limit = old_limit = (int) (z->zout_end - z->zout_start); limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
while (cur + n > limit) if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
while (cur + n > limit) {
if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
limit *= 2; limit *= 2;
}
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
STBI_NOTUSED(old_limit); STBI_NOTUSED(old_limit);
if (q == NULL) return stbi__err("outofmem", "Out of memory"); if (q == NULL) return stbi__err("outofmem", "Out of memory");
@ -4115,11 +4256,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
c = stbi__zreceive(a,2)+3; c = stbi__zreceive(a,2)+3;
if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
fill = lencodes[n-1]; fill = lencodes[n-1];
} else if (c == 17) } else if (c == 17) {
c = stbi__zreceive(a,3)+3; c = stbi__zreceive(a,3)+3;
else { } else if (c == 18) {
STBI_ASSERT(c == 18);
c = stbi__zreceive(a,7)+11; c = stbi__zreceive(a,7)+11;
} else {
return stbi__err("bad codelengths", "Corrupt PNG");
} }
if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
memset(lencodes+n, fill, c); memset(lencodes+n, fill, c);
@ -4145,7 +4287,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a)
a->code_buffer >>= 8; a->code_buffer >>= 8;
a->num_bits -= 8; a->num_bits -= 8;
} }
STBI_ASSERT(a->num_bits == 0); if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
// now fill header the normal way // now fill header the normal way
while (k < 4) while (k < 4)
header[k++] = stbi__zget8(a); header[k++] = stbi__zget8(a);
@ -4167,6 +4309,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
int cm = cmf & 15; int cm = cmf & 15;
/* int cinfo = cmf >> 4; */ /* int cinfo = cmf >> 4; */
int flg = stbi__zget8(a); int flg = stbi__zget8(a);
if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
@ -4428,7 +4571,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
return stbi__err("invalid filter","Corrupt PNG"); return stbi__err("invalid filter","Corrupt PNG");
if (depth < 8) { if (depth < 8) {
STBI_ASSERT(img_width_bytes <= x); if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
filter_bytes = 1; filter_bytes = 1;
width = img_width_bytes; width = img_width_bytes;
@ -4823,8 +4966,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
first = 0; first = 0;
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_x = stbi__get32be(s);
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_y = stbi__get32be(s);
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
@ -4941,6 +5086,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
++s->img_n; ++s->img_n;
} }
STBI_FREE(z->expanded); z->expanded = NULL; STBI_FREE(z->expanded); z->expanded = NULL;
// end of PNG chunk, read and skip CRC
stbi__get32be(s);
return 1; return 1;
} }
@ -4971,10 +5118,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
void *result=NULL; void *result=NULL;
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
if (p->depth < 8) if (p->depth <= 8)
ri->bits_per_channel = 8; ri->bits_per_channel = 8;
else if (p->depth == 16)
ri->bits_per_channel = 16;
else else
ri->bits_per_channel = p->depth; return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");
result = p->out; result = p->out;
p->out = NULL; p->out = NULL;
if (req_comp && req_comp != p->s->img_out_n) { if (req_comp && req_comp != p->s->img_out_n) {
@ -5079,7 +5228,7 @@ static int stbi__high_bit(unsigned int z)
if (z >= 0x00100) { n += 8; z >>= 8; } if (z >= 0x00100) { n += 8; z >>= 8; }
if (z >= 0x00010) { n += 4; z >>= 4; } if (z >= 0x00010) { n += 4; z >>= 4; }
if (z >= 0x00004) { n += 2; z >>= 2; } if (z >= 0x00004) { n += 2; z >>= 2; }
if (z >= 0x00002) { n += 1; z >>= 1; } if (z >= 0x00002) { n += 1;/* >>= 1;*/ }
return n; return n;
} }
@ -5110,7 +5259,7 @@ static int stbi__shiftsigned(unsigned int v, int shift, int bits)
v <<= -shift; v <<= -shift;
else else
v >>= shift; v >>= shift;
STBI_ASSERT(v >= 0 && v < 256); STBI_ASSERT(v < 256);
v >>= (8-bits); v >>= (8-bits);
STBI_ASSERT(bits >= 0 && bits <= 8); STBI_ASSERT(bits >= 0 && bits <= 8);
return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
@ -5120,6 +5269,7 @@ typedef struct
{ {
int bpp, offset, hsz; int bpp, offset, hsz;
unsigned int mr,mg,mb,ma, all_a; unsigned int mr,mg,mb,ma, all_a;
int extra_read;
} stbi__bmp_data; } stbi__bmp_data;
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
@ -5132,6 +5282,9 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->offset = stbi__get32le(s); info->offset = stbi__get32le(s);
info->hsz = hsz = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s);
info->mr = info->mg = info->mb = info->ma = 0; info->mr = info->mg = info->mb = info->ma = 0;
info->extra_read = 14;
if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
if (hsz == 12) { if (hsz == 12) {
@ -5175,6 +5328,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->mr = stbi__get32le(s); info->mr = stbi__get32le(s);
info->mg = stbi__get32le(s); info->mg = stbi__get32le(s);
info->mb = stbi__get32le(s); info->mb = stbi__get32le(s);
info->extra_read += 12;
// not documented, but generated by photoshop and handled by mspaint // not documented, but generated by photoshop and handled by mspaint
if (info->mr == info->mg && info->mg == info->mb) { if (info->mr == info->mg && info->mg == info->mb) {
// ?!?!? // ?!?!?
@ -5223,6 +5377,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
flip_vertically = ((int) s->img_y) > 0; flip_vertically = ((int) s->img_y) > 0;
s->img_y = abs((int) s->img_y); s->img_y = abs((int) s->img_y);
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
mr = info.mr; mr = info.mr;
mg = info.mg; mg = info.mg;
mb = info.mb; mb = info.mb;
@ -5231,13 +5388,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz == 12) { if (info.hsz == 12) {
if (info.bpp < 24) if (info.bpp < 24)
psize = (info.offset - 14 - 24) / 3; psize = (info.offset - info.extra_read - 24) / 3;
} else { } else {
if (info.bpp < 16) if (info.bpp < 16)
psize = (info.offset - 14 - info.hsz) >> 2; psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) {
return stbi__errpuc("bad offset", "Corrupt BMP");
}
} }
s->img_n = ma ? 4 : 3; if (info.bpp == 24 && ma == 0xff000000)
s->img_n = 3;
else
s->img_n = ma ? 4 : 3;
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
target = req_comp; target = req_comp;
else else
@ -5259,7 +5425,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz != 12) stbi__get8(s); if (info.hsz != 12) stbi__get8(s);
pal[i][3] = 255; pal[i][3] = 255;
} }
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
if (info.bpp == 1) width = (s->img_x + 7) >> 3; if (info.bpp == 1) width = (s->img_x + 7) >> 3;
else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
else if (info.bpp == 8) width = s->img_x; else if (info.bpp == 8) width = s->img_x;
@ -5308,7 +5474,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0; int z = 0;
int easy=0; int easy=0;
stbi__skip(s, info.offset - 14 - info.hsz); stbi__skip(s, info.offset - info.extra_read - info.hsz);
if (info.bpp == 24) width = 3 * s->img_x; if (info.bpp == 24) width = 3 * s->img_x;
else if (info.bpp == 16) width = 2*s->img_x; else if (info.bpp == 16) width = 2*s->img_x;
else /* bpp = 32 and pad = 0 */ width=0; else /* bpp = 32 and pad = 0 */ width=0;
@ -5326,6 +5492,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
} }
for (j=0; j < (int) s->img_y; ++j) { for (j=0; j < (int) s->img_y; ++j) {
if (easy) { if (easy) {
@ -5547,6 +5714,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
int RLE_repeating = 0; int RLE_repeating = 0;
int read_next_pixel = 1; int read_next_pixel = 1;
STBI_NOTUSED(ri); STBI_NOTUSED(ri);
STBI_NOTUSED(tga_x_origin); // @TODO
STBI_NOTUSED(tga_y_origin); // @TODO
if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
// do a tiny bit of precessing // do a tiny bit of precessing
if ( tga_image_type >= 8 ) if ( tga_image_type >= 8 )
@ -5587,6 +5759,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// do I need to load a palette? // do I need to load a palette?
if ( tga_indexed) if ( tga_indexed)
{ {
if (tga_palette_len == 0) { /* you have to have at least one entry! */
STBI_FREE(tga_data);
return stbi__errpuc("bad palette", "Corrupt TGA");
}
// any data to skip? (offset usually = 0) // any data to skip? (offset usually = 0)
stbi__skip(s, tga_palette_start ); stbi__skip(s, tga_palette_start );
// load the palette // load the palette
@ -5710,6 +5887,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// Microsoft's C compilers happy... [8^( // Microsoft's C compilers happy... [8^(
tga_palette_start = tga_palette_len = tga_palette_bits = tga_palette_start = tga_palette_len = tga_palette_bits =
tga_x_origin = tga_y_origin = 0; tga_x_origin = tga_y_origin = 0;
STBI_NOTUSED(tga_palette_start);
// OK, done // OK, done
return tga_data; return tga_data;
} }
@ -5794,6 +5972,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
h = stbi__get32be(s); h = stbi__get32be(s);
w = stbi__get32be(s); w = stbi__get32be(s);
if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
// Make sure the depth is 8 bits. // Make sure the depth is 8 bits.
bitdepth = stbi__get16be(s); bitdepth = stbi__get16be(s);
if (bitdepth != 8 && bitdepth != 16) if (bitdepth != 8 && bitdepth != 16)
@ -6148,6 +6329,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
x = stbi__get16be(s); x = stbi__get16be(s);
y = stbi__get16be(s); y = stbi__get16be(s);
if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
@ -6256,6 +6441,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
g->ratio = stbi__get8(s); g->ratio = stbi__get8(s);
g->transparent = -1; g->transparent = -1;
if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
if (is_info) return 1; if (is_info) return 1;
@ -6433,7 +6621,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
memset(g->history, 0x00, pcount); // pixels that were affected previous frame memset(g->history, 0x00, pcount); // pixels that were affected previous frame
first_frame = 1; first_frame = 1;
} else { } else {
// second frame - how do we dispoase of the previous one? // second frame - how do we dispose of the previous one?
dispose = (g->eflags & 0x1C) >> 2; dispose = (g->eflags & 0x1C) >> 2;
pcount = g->w * g->h; pcount = g->w * g->h;
@ -6587,6 +6775,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stbi_uc *two_back = 0; stbi_uc *two_back = 0;
stbi__gif g; stbi__gif g;
int stride; int stride;
int out_size = 0;
int delays_size = 0;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
if (delays) { if (delays) {
*delays = 0; *delays = 0;
@ -6603,14 +6793,28 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stride = g.w * g.h * 4; stride = g.w * g.h * 4;
if (out) { if (out) {
out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
if (NULL == tmp) {
STBI_FREE(g.out);
STBI_FREE(g.history);
STBI_FREE(g.background);
return stbi__errpuc("outofmem", "Out of memory");
}
else {
out = (stbi_uc*) tmp;
out_size = layers * stride;
}
if (delays) { if (delays) {
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
delays_size = layers * sizeof(int);
} }
} else { } else {
out = (stbi_uc*)stbi__malloc( layers * stride ); out = (stbi_uc*)stbi__malloc( layers * stride );
out_size = layers * stride;
if (delays) { if (delays) {
*delays = (int*) stbi__malloc( layers * sizeof(int) ); *delays = (int*) stbi__malloc( layers * sizeof(int) );
delays_size = layers * sizeof(int);
} }
} }
memcpy( out + ((layers - 1) * stride), u, stride ); memcpy( out + ((layers - 1) * stride), u, stride );
@ -6789,6 +6993,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
token += 3; token += 3;
width = (int) strtol(token, NULL, 10); width = (int) strtol(token, NULL, 10);
if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
*x = width; *x = width;
*y = height; *y = height;
@ -6936,7 +7143,12 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
return 0; return 0;
if (x) *x = s->img_x; if (x) *x = s->img_x;
if (y) *y = s->img_y; if (y) *y = s->img_y;
if (comp) *comp = info.ma ? 4 : 3; if (comp) {
if (info.bpp == 24 && info.ma == 0xff000000)
*comp = 3;
else
*comp = info.ma ? 4 : 3;
}
return 1; return 1;
} }
#endif #endif
@ -7098,6 +7310,9 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
return 0; return 0;
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
*x = s->img_x; *x = s->img_x;
*y = s->img_y; *y = s->img_y;
if (comp) *comp = s->img_n; if (comp) *comp = s->img_n;

View File

@ -1,4 +1,4 @@
/* stb_image - v2.22 - public domain image loader - http://nothings.org/stb /* stb_image - v2.26 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -48,6 +48,10 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.26 (2020-07-13) many minor fixes
2.25 (2020-02-02) fix warnings
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
2.23 (2019-08-11) fix clang static analysis warning
2.22 (2019-03-04) gif fixes, fix warnings 2.22 (2019-03-04) gif fixes, fix warnings
2.21 (2019-02-25) fix typo in comment 2.21 (2019-02-25) fix typo in comment
2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
@ -90,21 +94,30 @@ RECENT REVISION HISTORY:
Carmelo J Fdez-Aguera Carmelo J Fdez-Aguera
Bug & warning fixes Bug & warning fixes
Marc LeBlanc David Woo Guillaume George Martins Mozeiko Marc LeBlanc David Woo Guillaume George Martins Mozeiko
Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
Dave Moore Roy Eltham Hayaki Saito Nathan Reed Phil Jordan Dave Moore Roy Eltham
Won Chun Luke Graham Johan Duparc Nick Verigakis Hayaki Saito Nathan Reed Won Chun
the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh Luke Graham Johan Duparc Nick Verigakis the Horde3D community
Janez Zemva John Bartholomew Michal Cichon github:romigrou Thomas Ruf Ronny Chevalier github:rlyeh
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk Janez Zemva John Bartholomew Michal Cichon github:romigrou
Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex Laurent Gomila Cort Stratton github:snagar
Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex
Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw Cass Everitt Ryamond Barbiero github:grim210
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
Christian Floisand Kevin Schmidt JR Smith github:darealshinji Josh Tobin Matthew Gregan github:poppolopoppo
Blazej Dariusz Roszkowski github:Michaelangel007 Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
Brad Weinberger Matvey Cherevko [reserved]
Luca Sas Alexander Veselov Zack Middleton [reserved]
Ryan C. Gordon [reserved] [reserved]
DO NOT ADD YOUR NAME HERE
To add your name to the credits, pick a random blank space in the middle and fill it.
80% of merge conflicts on stb PRs are due to people adding their name at the end
of the credits.
*/ */
#ifndef STBI_INCLUDE_STB_IMAGE_H #ifndef STBI_INCLUDE_STB_IMAGE_H
@ -314,7 +327,14 @@ RECENT REVISION HISTORY:
// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
// //
// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
// than that size (in either width or height) without further processing.
// This is to let programs in the wild set an upper bound to prevent
// denial-of-service attacks on untrusted data, as one could generate a
// valid image of gigantic dimensions and force stb_image to allocate a
// huge block of memory and spend disproportionate time decoding it. By
// default this is set to (1 << 24), which is 16777216, but that's still
// very big.
#ifndef STBI_NO_STDIO #ifndef STBI_NO_STDIO
#include <stdio.h> #include <stdio.h>
@ -433,7 +453,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f);
// get a VERY brief reason for failure // get a VERY brief reason for failure
// NOT THREADSAFE // on most compilers (and ALL modern mainstream compilers) this is threadsafe
STBIDEF const char *stbi_failure_reason (void); STBIDEF const char *stbi_failure_reason (void);
// free the loaded image -- this is just free() // free the loaded image -- this is just free()
@ -466,6 +486,11 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically, so the first pixel in the output array is the bottom left // flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// as above, but only applies to images loaded on the thread that calls the function
// this function is only available if your compiler supports thread-local variables;
// calling it will fail to link if your compiler doesn't
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes // ZLIB client - used by PNG, available for other purposes
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
@ -562,6 +587,23 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#define stbi_inline __forceinline #define stbi_inline __forceinline
#endif #endif
#ifndef STBI_NO_THREAD_LOCALS
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STBI_THREAD_LOCAL thread_local
#elif defined(__GNUC__) && __GNUC__ < 5
#define STBI_THREAD_LOCAL __thread
#elif defined(_MSC_VER)
#define STBI_THREAD_LOCAL __declspec(thread)
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
#define STBI_THREAD_LOCAL _Thread_local
#endif
#ifndef STBI_THREAD_LOCAL
#if defined(__GNUC__)
#define STBI_THREAD_LOCAL __thread
#endif
#endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned short stbi__uint16; typedef unsigned short stbi__uint16;
@ -714,6 +756,10 @@ static int stbi__sse2_available(void)
#define STBI_SIMD_ALIGN(type, name) type name #define STBI_SIMD_ALIGN(type, name) type name
#endif #endif
#ifndef STBI_MAX_DIMENSIONS
#define STBI_MAX_DIMENSIONS (1 << 24)
#endif
/////////////////////////////////////////////// ///////////////////////////////////////////////
// //
// stbi__context struct and start_xxx functions // stbi__context struct and start_xxx functions
@ -731,6 +777,7 @@ typedef struct
int read_from_callbacks; int read_from_callbacks;
int buflen; int buflen;
stbi_uc buffer_start[128]; stbi_uc buffer_start[128];
int callback_already_read;
stbi_uc *img_buffer, *img_buffer_end; stbi_uc *img_buffer, *img_buffer_end;
stbi_uc *img_buffer_original, *img_buffer_original_end; stbi_uc *img_buffer_original, *img_buffer_original_end;
@ -744,6 +791,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
{ {
s->io.read = NULL; s->io.read = NULL;
s->read_from_callbacks = 0; s->read_from_callbacks = 0;
s->callback_already_read = 0;
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
} }
@ -755,7 +803,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
s->io_user_data = user; s->io_user_data = user;
s->buflen = sizeof(s->buffer_start); s->buflen = sizeof(s->buffer_start);
s->read_from_callbacks = 1; 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); stbi__refill_buffer(s);
s->img_buffer_original_end = s->img_buffer_end; s->img_buffer_original_end = s->img_buffer_end;
} }
@ -769,12 +818,17 @@ static int stbi__stdio_read(void *user, char *data, int size)
static void stbi__stdio_skip(void *user, int n) static void stbi__stdio_skip(void *user, int n)
{ {
int ch;
fseek((FILE*) user, n, SEEK_CUR); fseek((FILE*) user, n, SEEK_CUR);
ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */
if (ch != EOF) {
ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */
}
} }
static int stbi__stdio_eof(void *user) static int stbi__stdio_eof(void *user)
{ {
return feof((FILE*) user); return feof((FILE*) user) || ferror((FILE *) user);
} }
static stbi_io_callbacks stbi__stdio_callbacks = static stbi_io_callbacks stbi__stdio_callbacks =
@ -872,19 +926,24 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif #endif
// this is not threadsafe static
static const char *stbi__g_failure_reason; #ifdef STBI_THREAD_LOCAL
STBI_THREAD_LOCAL
#endif
const char *stbi__g_failure_reason;
STBIDEF const char *stbi_failure_reason(void) STBIDEF const char *stbi_failure_reason(void)
{ {
return stbi__g_failure_reason; return stbi__g_failure_reason;
} }
#ifndef STBI_NO_FAILURE_STRINGS
static int stbi__err(const char *str) static int stbi__err(const char *str)
{ {
stbi__g_failure_reason = str; stbi__g_failure_reason = str;
return 0; return 0;
} }
#endif
static void *stbi__malloc(size_t size) static void *stbi__malloc(size_t size)
{ {
@ -923,11 +982,13 @@ static int stbi__mul2sizes_valid(int a, int b)
return a <= INT_MAX/b; return a <= INT_MAX/b;
} }
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
static int stbi__mad2sizes_valid(int a, int b, int add) static int stbi__mad2sizes_valid(int a, int b, int add)
{ {
return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
} }
#endif
// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
static int stbi__mad3sizes_valid(int a, int b, int c, int add) static int stbi__mad3sizes_valid(int a, int b, int c, int add)
@ -945,12 +1006,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
} }
#endif #endif
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// mallocs with size overflow checking // mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add) static void *stbi__malloc_mad2(int a, int b, int add)
{ {
if (!stbi__mad2sizes_valid(a, b, add)) return NULL; if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
return stbi__malloc(a*b + add); return stbi__malloc(a*b + add);
} }
#endif
static void *stbi__malloc_mad3(int a, int b, int c, int add) static void *stbi__malloc_mad3(int a, int b, int c, int add)
{ {
@ -994,13 +1057,29 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif #endif
static int stbi__vertically_flip_on_load = 0; static int stbi__vertically_flip_on_load_global = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{ {
stbi__vertically_flip_on_load = flag_true_if_should_flip; stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
} }
#ifndef STBI_THREAD_LOCAL
#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
#else
static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
stbi__vertically_flip_on_load_set = 1;
}
#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \
? stbi__vertically_flip_on_load_local \
: stbi__vertically_flip_on_load_global)
#endif // STBI_THREAD_LOCAL
static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
{ {
memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
@ -1022,6 +1101,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
#endif #endif
#ifndef STBI_NO_PSD #ifndef STBI_NO_PSD
if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
#else
STBI_NOTUSED(bpc);
#endif #endif
#ifndef STBI_NO_PIC #ifndef STBI_NO_PIC
if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
@ -1124,8 +1205,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
if (result == NULL) if (result == NULL)
return NULL; return NULL;
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
if (ri.bits_per_channel != 8) { if (ri.bits_per_channel != 8) {
STBI_ASSERT(ri.bits_per_channel == 16);
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 8; ri.bits_per_channel = 8;
} }
@ -1148,8 +1231,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
if (result == NULL) if (result == NULL)
return NULL; return NULL;
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
if (ri.bits_per_channel != 16) { if (ri.bits_per_channel != 16) {
STBI_ASSERT(ri.bits_per_channel == 8);
result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 16; ri.bits_per_channel = 16;
} }
@ -1452,6 +1537,7 @@ enum
static void stbi__refill_buffer(stbi__context *s) static void stbi__refill_buffer(stbi__context *s)
{ {
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); 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) { if (n == 0) {
// at end of file, treat same as if from memory, but need to handle case // 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 // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
@ -1476,6 +1562,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s)
return 0; return 0;
} }
#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
stbi_inline static int stbi__at_eof(stbi__context *s) stbi_inline static int stbi__at_eof(stbi__context *s)
{ {
if (s->io.read) { if (s->io.read) {
@ -1487,9 +1576,14 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
return s->img_buffer >= s->img_buffer_end; return s->img_buffer >= s->img_buffer_end;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
// nothing
#else
static void stbi__skip(stbi__context *s, int n) static void stbi__skip(stbi__context *s, int n)
{ {
if (n == 0) return; // already there!
if (n < 0) { if (n < 0) {
s->img_buffer = s->img_buffer_end; s->img_buffer = s->img_buffer_end;
return; return;
@ -1504,7 +1598,11 @@ static void stbi__skip(stbi__context *s, int n)
} }
s->img_buffer += n; s->img_buffer += n;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
// nothing
#else
static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
{ {
if (s->io.read) { if (s->io.read) {
@ -1528,18 +1626,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
} else } else
return 0; return 0;
} }
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static int stbi__get16be(stbi__context *s) static int stbi__get16be(stbi__context *s)
{ {
int z = stbi__get8(s); int z = stbi__get8(s);
return (z << 8) + stbi__get8(s); return (z << 8) + stbi__get8(s);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static stbi__uint32 stbi__get32be(stbi__context *s) static stbi__uint32 stbi__get32be(stbi__context *s)
{ {
stbi__uint32 z = stbi__get16be(s); stbi__uint32 z = stbi__get16be(s);
return (z << 16) + stbi__get16be(s); return (z << 16) + stbi__get16be(s);
} }
#endif
#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
// nothing // nothing
@ -1561,7 +1668,9 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// generic converter from built-in img_n to req_comp // generic converter from built-in img_n to req_comp
@ -1577,7 +1686,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b)
{ {
return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1613,7 +1726,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
} }
#undef STBI__CASE #undef STBI__CASE
} }
@ -1621,12 +1734,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 stbi__compute_y_16(int r, int g, int b) static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
{ {
return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
} }
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{ {
int i,j; int i,j;
@ -1662,7 +1783,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
default: STBI_ASSERT(0); default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
} }
#undef STBI__CASE #undef STBI__CASE
} }
@ -1670,6 +1791,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI_FREE(data); STBI_FREE(data);
return good; return good;
} }
#endif
#ifndef STBI_NO_LINEAR #ifndef STBI_NO_LINEAR
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
@ -1970,7 +2092,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
k = stbi_lrot(j->code_buffer, n); k = stbi_lrot(j->code_buffer, n);
STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0;
j->code_buffer = k & ~stbi__bmask[n]; j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n]; k &= stbi__bmask[n];
j->code_bits -= n; j->code_bits -= n;
@ -2081,6 +2203,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
// first scan for DC coefficient, must be first // first scan for DC coefficient, must be first
memset(data,0,64*sizeof(data[0])); // 0 all the ac values now memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
t = stbi__jpeg_huff_decode(j, hdc); t = stbi__jpeg_huff_decode(j, hdc);
if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
diff = t ? stbi__extend_receive(j, t) : 0; diff = t ? stbi__extend_receive(j, t) : 0;
dc = j->img_comp[b].dc_pred + diff; dc = j->img_comp[b].dc_pred + diff;
@ -3071,6 +3194,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
c = stbi__get8(s); c = stbi__get8(s);
if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
s->img_n = c; s->img_n = c;
@ -3951,16 +4076,23 @@ typedef struct
stbi__zhuffman z_length, z_distance; stbi__zhuffman z_length, z_distance;
} stbi__zbuf; } stbi__zbuf;
stbi_inline static int stbi__zeof(stbi__zbuf *z)
{
return (z->zbuffer >= z->zbuffer_end);
}
stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
{ {
if (z->zbuffer >= z->zbuffer_end) return 0; return stbi__zeof(z) ? 0 : *z->zbuffer++;
return *z->zbuffer++;
} }
static void stbi__fill_bits(stbi__zbuf *z) static void stbi__fill_bits(stbi__zbuf *z)
{ {
do { do {
STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); if (z->code_buffer >= (1U << z->num_bits)) {
z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
return;
}
z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
z->num_bits += 8; z->num_bits += 8;
} while (z->num_bits <= 24); } while (z->num_bits <= 24);
@ -3985,10 +4117,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
for (s=STBI__ZFAST_BITS+1; ; ++s) for (s=STBI__ZFAST_BITS+1; ; ++s)
if (k < z->maxcode[s]) if (k < z->maxcode[s])
break; break;
if (s == 16) return -1; // invalid code! if (s >= 16) return -1; // invalid code!
// code size is s, so: // code size is s, so:
b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
STBI_ASSERT(z->size[b] == s); if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere!
if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.
a->code_buffer >>= s; a->code_buffer >>= s;
a->num_bits -= s; a->num_bits -= s;
return z->value[b]; return z->value[b];
@ -3997,7 +4130,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
{ {
int b,s; int b,s;
if (a->num_bits < 16) stbi__fill_bits(a); if (a->num_bits < 16) {
if (stbi__zeof(a)) {
return -1; /* report error for unexpected end of data. */
}
stbi__fill_bits(a);
}
b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) { if (b) {
s = b >> 9; s = b >> 9;
@ -4011,13 +4149,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
{ {
char *q; char *q;
int cur, limit, old_limit; unsigned int cur, limit, old_limit;
z->zout = zout; z->zout = zout;
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
cur = (int) (z->zout - z->zout_start); cur = (unsigned int) (z->zout - z->zout_start);
limit = old_limit = (int) (z->zout_end - z->zout_start); limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
while (cur + n > limit) if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
while (cur + n > limit) {
if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
limit *= 2; limit *= 2;
}
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
STBI_NOTUSED(old_limit); STBI_NOTUSED(old_limit);
if (q == NULL) return stbi__err("outofmem", "Out of memory"); if (q == NULL) return stbi__err("outofmem", "Out of memory");
@ -4115,11 +4256,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
c = stbi__zreceive(a,2)+3; c = stbi__zreceive(a,2)+3;
if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
fill = lencodes[n-1]; fill = lencodes[n-1];
} else if (c == 17) } else if (c == 17) {
c = stbi__zreceive(a,3)+3; c = stbi__zreceive(a,3)+3;
else { } else if (c == 18) {
STBI_ASSERT(c == 18);
c = stbi__zreceive(a,7)+11; c = stbi__zreceive(a,7)+11;
} else {
return stbi__err("bad codelengths", "Corrupt PNG");
} }
if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
memset(lencodes+n, fill, c); memset(lencodes+n, fill, c);
@ -4145,7 +4287,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a)
a->code_buffer >>= 8; a->code_buffer >>= 8;
a->num_bits -= 8; a->num_bits -= 8;
} }
STBI_ASSERT(a->num_bits == 0); if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
// now fill header the normal way // now fill header the normal way
while (k < 4) while (k < 4)
header[k++] = stbi__zget8(a); header[k++] = stbi__zget8(a);
@ -4167,6 +4309,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
int cm = cmf & 15; int cm = cmf & 15;
/* int cinfo = cmf >> 4; */ /* int cinfo = cmf >> 4; */
int flg = stbi__zget8(a); int flg = stbi__zget8(a);
if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
@ -4428,7 +4571,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
return stbi__err("invalid filter","Corrupt PNG"); return stbi__err("invalid filter","Corrupt PNG");
if (depth < 8) { if (depth < 8) {
STBI_ASSERT(img_width_bytes <= x); if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
filter_bytes = 1; filter_bytes = 1;
width = img_width_bytes; width = img_width_bytes;
@ -4823,8 +4966,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
first = 0; first = 0;
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_x = stbi__get32be(s);
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_y = stbi__get32be(s);
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
@ -4941,6 +5086,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
++s->img_n; ++s->img_n;
} }
STBI_FREE(z->expanded); z->expanded = NULL; STBI_FREE(z->expanded); z->expanded = NULL;
// end of PNG chunk, read and skip CRC
stbi__get32be(s);
return 1; return 1;
} }
@ -4971,10 +5118,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
void *result=NULL; void *result=NULL;
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
if (p->depth < 8) if (p->depth <= 8)
ri->bits_per_channel = 8; ri->bits_per_channel = 8;
else if (p->depth == 16)
ri->bits_per_channel = 16;
else else
ri->bits_per_channel = p->depth; return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");
result = p->out; result = p->out;
p->out = NULL; p->out = NULL;
if (req_comp && req_comp != p->s->img_out_n) { if (req_comp && req_comp != p->s->img_out_n) {
@ -5079,7 +5228,7 @@ static int stbi__high_bit(unsigned int z)
if (z >= 0x00100) { n += 8; z >>= 8; } if (z >= 0x00100) { n += 8; z >>= 8; }
if (z >= 0x00010) { n += 4; z >>= 4; } if (z >= 0x00010) { n += 4; z >>= 4; }
if (z >= 0x00004) { n += 2; z >>= 2; } if (z >= 0x00004) { n += 2; z >>= 2; }
if (z >= 0x00002) { n += 1; z >>= 1; } if (z >= 0x00002) { n += 1;/* >>= 1;*/ }
return n; return n;
} }
@ -5110,7 +5259,7 @@ static int stbi__shiftsigned(unsigned int v, int shift, int bits)
v <<= -shift; v <<= -shift;
else else
v >>= shift; v >>= shift;
STBI_ASSERT(v >= 0 && v < 256); STBI_ASSERT(v < 256);
v >>= (8-bits); v >>= (8-bits);
STBI_ASSERT(bits >= 0 && bits <= 8); STBI_ASSERT(bits >= 0 && bits <= 8);
return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
@ -5120,6 +5269,7 @@ typedef struct
{ {
int bpp, offset, hsz; int bpp, offset, hsz;
unsigned int mr,mg,mb,ma, all_a; unsigned int mr,mg,mb,ma, all_a;
int extra_read;
} stbi__bmp_data; } stbi__bmp_data;
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
@ -5132,6 +5282,9 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->offset = stbi__get32le(s); info->offset = stbi__get32le(s);
info->hsz = hsz = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s);
info->mr = info->mg = info->mb = info->ma = 0; info->mr = info->mg = info->mb = info->ma = 0;
info->extra_read = 14;
if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
if (hsz == 12) { if (hsz == 12) {
@ -5175,6 +5328,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->mr = stbi__get32le(s); info->mr = stbi__get32le(s);
info->mg = stbi__get32le(s); info->mg = stbi__get32le(s);
info->mb = stbi__get32le(s); info->mb = stbi__get32le(s);
info->extra_read += 12;
// not documented, but generated by photoshop and handled by mspaint // not documented, but generated by photoshop and handled by mspaint
if (info->mr == info->mg && info->mg == info->mb) { if (info->mr == info->mg && info->mg == info->mb) {
// ?!?!? // ?!?!?
@ -5223,6 +5377,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
flip_vertically = ((int) s->img_y) > 0; flip_vertically = ((int) s->img_y) > 0;
s->img_y = abs((int) s->img_y); s->img_y = abs((int) s->img_y);
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
mr = info.mr; mr = info.mr;
mg = info.mg; mg = info.mg;
mb = info.mb; mb = info.mb;
@ -5231,13 +5388,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz == 12) { if (info.hsz == 12) {
if (info.bpp < 24) if (info.bpp < 24)
psize = (info.offset - 14 - 24) / 3; psize = (info.offset - info.extra_read - 24) / 3;
} else { } else {
if (info.bpp < 16) if (info.bpp < 16)
psize = (info.offset - 14 - info.hsz) >> 2; psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) {
return stbi__errpuc("bad offset", "Corrupt BMP");
}
} }
s->img_n = ma ? 4 : 3; if (info.bpp == 24 && ma == 0xff000000)
s->img_n = 3;
else
s->img_n = ma ? 4 : 3;
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
target = req_comp; target = req_comp;
else else
@ -5259,7 +5425,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz != 12) stbi__get8(s); if (info.hsz != 12) stbi__get8(s);
pal[i][3] = 255; pal[i][3] = 255;
} }
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
if (info.bpp == 1) width = (s->img_x + 7) >> 3; if (info.bpp == 1) width = (s->img_x + 7) >> 3;
else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
else if (info.bpp == 8) width = s->img_x; else if (info.bpp == 8) width = s->img_x;
@ -5308,7 +5474,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0; int z = 0;
int easy=0; int easy=0;
stbi__skip(s, info.offset - 14 - info.hsz); stbi__skip(s, info.offset - info.extra_read - info.hsz);
if (info.bpp == 24) width = 3 * s->img_x; if (info.bpp == 24) width = 3 * s->img_x;
else if (info.bpp == 16) width = 2*s->img_x; else if (info.bpp == 16) width = 2*s->img_x;
else /* bpp = 32 and pad = 0 */ width=0; else /* bpp = 32 and pad = 0 */ width=0;
@ -5326,6 +5492,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
} }
for (j=0; j < (int) s->img_y; ++j) { for (j=0; j < (int) s->img_y; ++j) {
if (easy) { if (easy) {
@ -5547,6 +5714,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
int RLE_repeating = 0; int RLE_repeating = 0;
int read_next_pixel = 1; int read_next_pixel = 1;
STBI_NOTUSED(ri); STBI_NOTUSED(ri);
STBI_NOTUSED(tga_x_origin); // @TODO
STBI_NOTUSED(tga_y_origin); // @TODO
if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
// do a tiny bit of precessing // do a tiny bit of precessing
if ( tga_image_type >= 8 ) if ( tga_image_type >= 8 )
@ -5587,6 +5759,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// do I need to load a palette? // do I need to load a palette?
if ( tga_indexed) if ( tga_indexed)
{ {
if (tga_palette_len == 0) { /* you have to have at least one entry! */
STBI_FREE(tga_data);
return stbi__errpuc("bad palette", "Corrupt TGA");
}
// any data to skip? (offset usually = 0) // any data to skip? (offset usually = 0)
stbi__skip(s, tga_palette_start ); stbi__skip(s, tga_palette_start );
// load the palette // load the palette
@ -5710,6 +5887,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// Microsoft's C compilers happy... [8^( // Microsoft's C compilers happy... [8^(
tga_palette_start = tga_palette_len = tga_palette_bits = tga_palette_start = tga_palette_len = tga_palette_bits =
tga_x_origin = tga_y_origin = 0; tga_x_origin = tga_y_origin = 0;
STBI_NOTUSED(tga_palette_start);
// OK, done // OK, done
return tga_data; return tga_data;
} }
@ -5794,6 +5972,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
h = stbi__get32be(s); h = stbi__get32be(s);
w = stbi__get32be(s); w = stbi__get32be(s);
if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
// Make sure the depth is 8 bits. // Make sure the depth is 8 bits.
bitdepth = stbi__get16be(s); bitdepth = stbi__get16be(s);
if (bitdepth != 8 && bitdepth != 16) if (bitdepth != 8 && bitdepth != 16)
@ -6148,6 +6329,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
x = stbi__get16be(s); x = stbi__get16be(s);
y = stbi__get16be(s); y = stbi__get16be(s);
if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
@ -6256,6 +6441,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
g->ratio = stbi__get8(s); g->ratio = stbi__get8(s);
g->transparent = -1; g->transparent = -1;
if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
if (is_info) return 1; if (is_info) return 1;
@ -6433,7 +6621,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
memset(g->history, 0x00, pcount); // pixels that were affected previous frame memset(g->history, 0x00, pcount); // pixels that were affected previous frame
first_frame = 1; first_frame = 1;
} else { } else {
// second frame - how do we dispoase of the previous one? // second frame - how do we dispose of the previous one?
dispose = (g->eflags & 0x1C) >> 2; dispose = (g->eflags & 0x1C) >> 2;
pcount = g->w * g->h; pcount = g->w * g->h;
@ -6587,6 +6775,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stbi_uc *two_back = 0; stbi_uc *two_back = 0;
stbi__gif g; stbi__gif g;
int stride; int stride;
int out_size = 0;
int delays_size = 0;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
if (delays) { if (delays) {
*delays = 0; *delays = 0;
@ -6603,14 +6793,28 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stride = g.w * g.h * 4; stride = g.w * g.h * 4;
if (out) { if (out) {
out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
if (NULL == tmp) {
STBI_FREE(g.out);
STBI_FREE(g.history);
STBI_FREE(g.background);
return stbi__errpuc("outofmem", "Out of memory");
}
else {
out = (stbi_uc*) tmp;
out_size = layers * stride;
}
if (delays) { if (delays) {
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
delays_size = layers * sizeof(int);
} }
} else { } else {
out = (stbi_uc*)stbi__malloc( layers * stride ); out = (stbi_uc*)stbi__malloc( layers * stride );
out_size = layers * stride;
if (delays) { if (delays) {
*delays = (int*) stbi__malloc( layers * sizeof(int) ); *delays = (int*) stbi__malloc( layers * sizeof(int) );
delays_size = layers * sizeof(int);
} }
} }
memcpy( out + ((layers - 1) * stride), u, stride ); memcpy( out + ((layers - 1) * stride), u, stride );
@ -6789,6 +6993,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
token += 3; token += 3;
width = (int) strtol(token, NULL, 10); width = (int) strtol(token, NULL, 10);
if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
*x = width; *x = width;
*y = height; *y = height;
@ -6936,7 +7143,12 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
return 0; return 0;
if (x) *x = s->img_x; if (x) *x = s->img_x;
if (y) *y = s->img_y; if (y) *y = s->img_y;
if (comp) *comp = info.ma ? 4 : 3; if (comp) {
if (info.bpp == 24 && info.ma == 0xff000000)
*comp = 3;
else
*comp = info.ma ? 4 : 3;
}
return 1; return 1;
} }
#endif #endif
@ -7098,6 +7310,9 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
return 0; return 0;
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
*x = s->img_x; *x = s->img_x;
*y = s->img_y; *y = s->img_y;
if (comp) *comp = s->img_n; if (comp) *comp = s->img_n;