From efd6b2698f0b420ec06c79e0def961e6b4f1866b Mon Sep 17 00:00:00 2001 From: Lysander Date: Wed, 9 Jul 2014 22:41:22 +0900 Subject: [PATCH 1/5] Fix crash when trying to load progressive jpeg due to uninitialized s->img_n Proper pointer check before deleting --- stb_image.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index ff7eb49..0a62997 100644 --- a/stb_image.h +++ b/stb_image.h @@ -553,6 +553,7 @@ static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { + s->img_n = 0; if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); @@ -1807,8 +1808,9 @@ static void stbi__cleanup_jpeg(stbi__jpeg *j) { int i; for (i=0; i < j->s->img_n; ++i) { - if (j->img_comp[i].data) { + if (j->img_comp[i].raw_data) { free(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; j->img_comp[i].data = NULL; } if (j->img_comp[i].linebuf) { From 932d485146e888d899b31e586b5b9e9f5faac5e8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 9 Jul 2014 23:01:29 -0700 Subject: [PATCH 2/5] fix warnings in certain console compilers --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index ff7eb49..296a35a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -354,7 +354,7 @@ STBIDEF void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); #include #endif #include -#include +#include #include #include #include // ptrdiff_t on osx @@ -4119,7 +4119,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i } case 0x3B: // gif stream termination code - return (stbi_uc *) 1; + return (stbi_uc *) s; // using '1' causes warning on some compilers default: return stbi__errpuc("unknown code", "Corrupt GIF"); @@ -4134,7 +4134,7 @@ static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int memset(&g, 0, sizeof(g)); u = stbi__gif_load_next(s, &g, comp, req_comp); - if (u == (void *) 1) u = 0; // end of animated gif marker + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { *x = g.w; *y = g.h; From a2b9aa8d06c6a59e59b489f61c882703c08ab657 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 9 Jul 2014 23:23:48 -0700 Subject: [PATCH 3/5] modifiy jpeg img_n fix switch from fopen to fopen_s on later MSVCs --- stb_image.h | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/stb_image.h b/stb_image.h index faafd2e..909a692 100644 --- a/stb_image.h +++ b/stb_image.h @@ -189,12 +189,6 @@ #ifndef STBI_NO_STDIO - -#if defined(_MSC_VER) && _MSC_VER >= 1400 -#define _CRT_SECURE_NO_WARNINGS // suppress warnings about fopen() -#pragma warning(push) -#pragma warning(disable:4996) // suppress even more warnings about fopen() -#endif #include #endif // STBI_NO_STDIO @@ -553,7 +547,6 @@ static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { - s->img_n = 0; if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); @@ -575,9 +568,23 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp } #ifndef STBI_NO_STDIO + +FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, "rb")) + f=0; +#else + f = fopen(filename, "rb"); +#endif + return f; +} + + STBIDEF unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) { - FILE *f = fopen(filename, "rb"); + FILE *f = stbi__fopen(filename, "rb"); unsigned char *result; if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); result = stbi_load_from_file(f,x,y,comp,req_comp); @@ -645,8 +652,8 @@ float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int #ifndef STBI_NO_STDIO float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) { - FILE *f = fopen(filename, "rb"); float *result; + FILE *f = stbi__fopen(filename, "rb"); if (!f) return stbi__errpf("can't fopen", "Unable to open file"); result = stbi_loadf_from_file(f,x,y,comp,req_comp); fclose(f); @@ -683,7 +690,7 @@ int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) #ifndef STBI_NO_STDIO STBIDEF int stbi_is_hdr (char const *filename) { - FILE *f = fopen(filename, "rb"); + FILE *f = stbi__fopen(filename, "rb"); int result=0; if (f) { result = stbi_is_hdr_from_file(f); @@ -1624,6 +1631,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int decode_jpeg_header(stbi__jpeg *z, int scan) { int m; + z->s->img_n = 0; z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no stbi__SOI","Corrupt JPEG"); @@ -1835,7 +1843,6 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp int n, decode_n; // validate req_comp if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); - z->s->img_n = 0; // load a jpeg image from whichever source if (!decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } @@ -4504,7 +4511,7 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_STDIO STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) { - FILE *f = fopen(filename, "rb"); + FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); result = stbi_info_from_file(f, x, y, comp); From 3bf91543f4060602fee698b44c448fa87df8161b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 9 Jul 2014 23:26:03 -0700 Subject: [PATCH 4/5] revert img_n=0 initialization to original location --- stb_image.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 909a692..4097dbb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1631,7 +1631,6 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int decode_jpeg_header(stbi__jpeg *z, int scan) { int m; - z->s->img_n = 0; z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no stbi__SOI","Corrupt JPEG"); @@ -1841,6 +1840,8 @@ typedef struct static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + // validate req_comp if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); From e0d86b0f5c229d0ee87cf6842078b8eca2ea4980 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 9 Jul 2014 23:35:25 -0700 Subject: [PATCH 5/5] STBI_ASSERT --- stb_image.h | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/stb_image.h b/stb_image.h index 4097dbb..c6e9aa8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6,6 +6,8 @@ #define STB_IMAGE_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. + #define STBI_ASSERT(x) to avoid using assert.h. + QUICK NOTES: Primarily of interest to game developers and other people who can avoid problematic images and only need the trivial interface @@ -26,6 +28,7 @@ - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) Latest revisions: + 1.42 (2014-07-09) no _CRT_SECURE_NO_WARNINGS; error-path fixes; STBI_ASSERT 1.41 (2014-06-25) fix search&replace that messed up comments/error messages 1.40 (2014-06-22) gcc warning 1.39 (2014-06-15) TGA optimization fix, multiple BMP fixes @@ -33,8 +36,6 @@ 1.37 (2014-06-04) remove duplicate typedef 1.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag 1.35 (2014-05-27) warnings, bugfixes, TGA optimization, etc - 1.34 (unknown ) warning fix - 1.33 (2011-07-14) minor fixes suggested by Dave Moore See end of file for full revision history. @@ -349,7 +350,10 @@ STBIDEF void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); #endif #include #include +#ifndef STBI_ASSERT #include +#define STBI_ASSERT(x) assert(x) +#endif #include #include // ptrdiff_t on osx @@ -868,7 +872,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r unsigned char *good; if (req_comp == img_n) return data; - assert(req_comp >= 1 && req_comp <= 4); + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); good = (unsigned char *) malloc(req_comp * x * y); if (good == NULL) { @@ -897,7 +901,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; - default: assert(0); + default: STBI_ASSERT(0); } #undef CASE } @@ -1134,7 +1138,7 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) // convert the huffman code to the symbol id c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; - assert((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); // convert the id to a symbol j->code_bits -= k; @@ -2008,7 +2012,7 @@ stbi_inline static int stbi__bitreverse16(int n) stbi_inline static int stbi__bit_reverse(int v, int bits) { - assert(bits <= 16); + STBI_ASSERT(bits <= 16); // to bit reverse n bits, reverse 16 and shift // stbi__err.g. 11 bits, bit reverse and shift away 5 return stbi__bitreverse16(v) >> (16-bits); @@ -2026,7 +2030,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) ++sizes[sizelist[i]]; sizes[0] = 0; for (i=1; i < 16; ++i) - assert(sizes[i] <= (1 << i)); + STBI_ASSERT(sizes[i] <= (1 << i)); code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; @@ -2088,7 +2092,7 @@ stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) static void stbi__fill_bits(stbi__zbuf *z) { do { - assert(z->code_buffer < (1U << z->num_bits)); + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); z->code_buffer |= stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); @@ -2125,7 +2129,7 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) if (s == 16) return -1; // invalid code! // code size is s, so: b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - assert(z->size[b] == s); + STBI_ASSERT(z->size[b] == s); a->code_buffer >>= s; a->num_bits -= s; return z->value[b]; @@ -2212,7 +2216,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) n = 0; while (n < hlit + hdist) { int c = stbi__zhuffman_decode(a, &z_codelength); - assert(c >= 0 && c < 19); + STBI_ASSERT(c >= 0 && c < 19); if (c < 16) lencodes[n++] = (stbi_uc) c; else if (c == 16) { @@ -2224,7 +2228,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) memset(lencodes+n, 0, c); n += c; } else { - assert(c == 18); + STBI_ASSERT(c == 18); c = stbi__zreceive(a,7)+11; memset(lencodes+n, 0, c); n += c; @@ -2249,7 +2253,7 @@ static int stbi__parse_uncomperssed_block(stbi__zbuf *a) a->code_buffer >>= 8; a->num_bits -= 8; } - assert(a->num_bits == 0); + STBI_ASSERT(a->num_bits == 0); // now fill header the normal way while (k < 4) header[k++] = stbi__zget8(a); @@ -2478,7 +2482,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r stbi__uint32 i,j,stride = x*out_n; int k; int img_n = s->img_n; // copy it into a local for later - assert(out_n == s->img_n || out_n == s->img_n+1); + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); a->out = (stbi_uc *) malloc(x * y * out_n); if (!a->out) return stbi__err("outofmem", "Out of memory"); if (s->img_x == x && s->img_y == y) { @@ -2526,7 +2530,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r } #undef CASE } else { - assert(img_n+1 == out_n); + STBI_ASSERT(img_n+1 == out_n); #define CASE(f) \ case f: \ for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ @@ -2591,7 +2595,7 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) // compute color-based transparency, assuming we've // already got 255 as the alpha value in the output - assert(out_n == 2 || out_n == 4); + STBI_ASSERT(out_n == 2 || out_n == 4); if (out_n == 2) { for (i=0; i < pixel_count; ++i) { @@ -2672,7 +2676,7 @@ static void stbi__de_iphone(stbi__png *z) p += 3; } } else { - assert(s->img_out_n == 4); + STBI_ASSERT(s->img_out_n == 4); if (stbi__unpremultiply_on_load) { // convert bgr to rgb and unpremultiply for (i=0; i < pixel_count; ++i) { @@ -3046,7 +3050,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int return stbi__errpuc("bad BMP", "bad BMP"); } } else { - assert(hsz == 108 || hsz == 124); + STBI_ASSERT(hsz == 108 || hsz == 124); mr = stbi__get32le(s); mg = stbi__get32le(s); mb = stbi__get32le(s); @@ -4555,6 +4559,10 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h 1.41 (2014-06-25) fix search&replace from 1.36 that messed up comments/error messages 1.40 (2014-06-22)