Merge branch 'stb_img_overflows' of https://github.com/rygorous/stb into working

Conflicts:
	stb_image.h
This commit is contained in:
Sean Barrett 2016-12-04 05:20:57 -08:00
commit ae241feec4

View File

@ -573,6 +573,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#include <stddef.h> // ptrdiff_t on osx #include <stddef.h> // ptrdiff_t on osx
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
#include <math.h> // ldexp #include <math.h> // ldexp
@ -920,6 +921,77 @@ static void *stbi__malloc(size_t size)
return STBI_MALLOC(size); return STBI_MALLOC(size);
} }
// stb_image uses ints pervasively, including for offset calculations.
// therefore the largest decoded image size we can support with the
// current code, even on 64-bit targets, is INT_MAX. this is not a
// significant limitation for the intended use case.
//
// we do, however, need to make sure our size calculations don't
// overflow. hence a few helper functions for size calculations that
// multiply integers together, making sure that they're non-negative
// and no overflow occurs.
// return 1 if the sum is valid, 0 on overflow.
// negative terms are considered invalid.
static int stbi__addsizes_valid(int a, int b)
{
if (b < 0) return 0;
// now 0 <= b <= INT_MAX, hence also
// 0 <= INT_MAX - b <= INTMAX.
// And "a + b <= INT_MAX" (which might overflow) is the
// same as a <= INT_MAX - b (no overflow)
return a <= INT_MAX - b;
}
// returns 1 if the product is valid, 0 on overflow.
// negative factors are considered invalid.
static int stbi__mul2sizes_valid(int a, int b)
{
if (a < 0 || b < 0) return 0;
if (b == 0) return 1; // mul-by-0 is always safe
// portable way to check for no overflows in a*b
return a <= INT_MAX/b;
}
// 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)
{
return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
}
// 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)
{
return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
stbi__addsizes_valid(a*b*c, add);
}
// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow
static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
{
return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&
stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);
}
// mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add)
{
if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
return stbi__malloc(a*b + add);
}
static void *stbi__malloc_mad3(int a, int b, int c, int add)
{
if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;
return stbi__malloc(a*b*c + add);
}
static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
{
if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;
return stbi__malloc(a*b*c*d + add);
}
// stbi__err - error // stbi__err - error
// stbi__errpf - error returning pointer to float // stbi__errpf - error returning pointer to float
// stbi__errpuc - error returning pointer to unsigned char // stbi__errpuc - error returning pointer to unsigned char
@ -1020,16 +1092,16 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan
{ {
int i; int i;
int img_len = w * h * channels; int img_len = w * h * channels;
stbi__uint16 *reduced; stbi__uint16 *enlarged;
reduced = (stbi__uint16 *) stbi__malloc(img_len*2); enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
if (reduced == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
for (i = 0; i < img_len; ++i) for (i = 0; i < img_len; ++i)
reduced[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
STBI_FREE(orig); STBI_FREE(orig);
return reduced; return enlarged;
} }
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
@ -1479,7 +1551,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
if (req_comp == img_n) return data; if (req_comp == img_n) return data;
STBI_ASSERT(req_comp >= 1 && req_comp <= 4); STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
good = (unsigned char *) stbi__malloc(req_comp * x * y); good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
if (good == NULL) { if (good == NULL) {
STBI_FREE(data); STBI_FREE(data);
return stbi__errpuc("outofmem", "Out of memory"); return stbi__errpuc("outofmem", "Out of memory");
@ -1568,7 +1640,9 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
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)
{ {
int i,k,n; int i,k,n;
float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); float *output;
if (!data) return NULL;
output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);
if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }
// compute number of non-alpha components // compute number of non-alpha components
if (comp & 1) n = comp; else n = comp-1; if (comp & 1) n = comp; else n = comp-1;
@ -1588,7 +1662,9 @@ 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)
{ {
int i,k,n; int i,k,n;
stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); stbi_uc *output;
if (!data) return NULL;
output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);
if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }
// compute number of non-alpha components // compute number of non-alpha components
if (comp & 1) n = comp; else n = comp-1; if (comp & 1) n = comp; else n = comp-1;
@ -2883,6 +2959,28 @@ static int stbi__process_scan_header(stbi__jpeg *z)
return 1; return 1;
} }
static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)
{
int i;
for (i=0; i < ncomp; ++i) {
if (z->img_comp[i].raw_data) {
STBI_FREE(z->img_comp[i].raw_data);
z->img_comp[i].raw_data = NULL;
z->img_comp[i].data = NULL;
}
if (z->img_comp[i].raw_coeff) {
STBI_FREE(z->img_comp[i].raw_coeff);
z->img_comp[i].raw_coeff = 0;
z->img_comp[i].coeff = 0;
}
if (z->img_comp[i].linebuf) {
STBI_FREE(z->img_comp[i].linebuf);
z->img_comp[i].linebuf = NULL;
}
}
return why;
}
static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int stbi__process_frame_header(stbi__jpeg *z, int scan)
{ {
stbi__context *s = z->s; stbi__context *s = z->s;
@ -2920,7 +3018,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
if (scan != STBI__SCAN_load) return 1; if (scan != STBI__SCAN_load) return 1;
if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");
for (i=0; i < s->img_n; ++i) { for (i=0; i < s->img_n; ++i) {
if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
@ -2932,6 +3030,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
z->img_v_max = v_max; z->img_v_max = v_max;
z->img_mcu_w = h_max * 8; z->img_mcu_w = h_max * 8;
z->img_mcu_h = v_max * 8; z->img_mcu_h = v_max * 8;
// these sizes can't be more than 17 bits
z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
@ -2943,28 +3042,27 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
// the bogus oversized data from using interleaved MCUs and their // the bogus oversized data from using interleaved MCUs and their
// big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
// discard the extra data until colorspace conversion // discard the extra data until colorspace conversion
//
// img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)
// so these muls can't overflow with 32-bit ints (which we require)
z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); z->img_comp[i].coeff = 0;
z->img_comp[i].raw_coeff = 0;
if (z->img_comp[i].raw_data == NULL) { z->img_comp[i].linebuf = NULL;
for(--i; i >= 0; --i) { z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
STBI_FREE(z->img_comp[i].raw_data); if (z->img_comp[i].raw_data == NULL)
z->img_comp[i].raw_data = NULL; return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
}
return stbi__err("outofmem", "Out of memory");
}
// align blocks for idct using mmx/sse // align blocks for idct using mmx/sse
z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
z->img_comp[i].linebuf = NULL;
if (z->progressive) { if (z->progressive) {
z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; // w2, h2 are multiples of 8 (see above)
z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;
z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);
if (z->img_comp[i].raw_coeff == NULL)
return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
} else {
z->img_comp[i].coeff = 0;
z->img_comp[i].raw_coeff = 0;
} }
} }
@ -3470,23 +3568,7 @@ static void stbi__setup_jpeg(stbi__jpeg *j)
// clean up the temporary component buffers // clean up the temporary component buffers
static void stbi__cleanup_jpeg(stbi__jpeg *j) static void stbi__cleanup_jpeg(stbi__jpeg *j)
{ {
int i; stbi__free_jpeg_components(j, j->s->img_n, 0);
for (i=0; i < j->s->img_n; ++i) {
if (j->img_comp[i].raw_data) {
STBI_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].raw_coeff) {
STBI_FREE(j->img_comp[i].raw_coeff);
j->img_comp[i].raw_coeff = 0;
j->img_comp[i].coeff = 0;
}
if (j->img_comp[i].linebuf) {
STBI_FREE(j->img_comp[i].linebuf);
j->img_comp[i].linebuf = NULL;
}
}
} }
typedef struct typedef struct
@ -3550,7 +3632,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
} }
// can't error after this so, this is safe // can't error after this so, this is safe
output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);
if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }
// now go ahead and resample // now go ahead and resample
@ -3903,6 +3985,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
int hlit = stbi__zreceive(a,5) + 257; int hlit = stbi__zreceive(a,5) + 257;
int hdist = stbi__zreceive(a,5) + 1; int hdist = stbi__zreceive(a,5) + 1;
int hclen = stbi__zreceive(a,4) + 4; int hclen = stbi__zreceive(a,4) + 4;
int ntot = hlit + hdist;
memset(codelength_sizes, 0, sizeof(codelength_sizes)); memset(codelength_sizes, 0, sizeof(codelength_sizes));
for (i=0; i < hclen; ++i) { for (i=0; i < hclen; ++i) {
@ -3912,27 +3995,29 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
n = 0; n = 0;
while (n < hlit + hdist) { while (n < ntot) {
int c = stbi__zhuffman_decode(a, &z_codelength); int c = stbi__zhuffman_decode(a, &z_codelength);
if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
if (c < 16) if (c < 16)
lencodes[n++] = (stbi_uc) c; lencodes[n++] = (stbi_uc) c;
else if (c == 16) { else {
c = stbi__zreceive(a,2)+3; stbi_uc fill = 0;
memset(lencodes+n, lencodes[n-1], c); if (c == 16) {
n += c; c = stbi__zreceive(a,2)+3;
} else if (c == 17) { if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
c = stbi__zreceive(a,3)+3; fill = lencodes[n-1];
memset(lencodes+n, 0, c); } else if (c == 17)
n += c; c = stbi__zreceive(a,3)+3;
} else { else {
STBI_ASSERT(c == 18); STBI_ASSERT(c == 18);
c = stbi__zreceive(a,7)+11; c = stbi__zreceive(a,7)+11;
memset(lencodes+n, 0, c); }
if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
memset(lencodes+n, fill, c);
n += c; n += c;
} }
} }
if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");
if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
return 1; return 1;
@ -4198,7 +4283,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
int width = x; int width = x;
STBI_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 *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!a->out) return stbi__err("outofmem", "Out of memory");
img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_width_bytes = (((img_n * x * depth) + 7) >> 3);
@ -4396,13 +4481,15 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)
{ {
int bytes = (depth == 16 ? 2 : 1);
int out_bytes = out_n * bytes;
stbi_uc *final; stbi_uc *final;
int p; int p;
if (!interlaced) if (!interlaced)
return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);
// de-interlacing // de-interlacing
final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);
for (p=0; p < 7; ++p) { for (p=0; p < 7; ++p) {
int xorig[] = { 0,4,0,2,0,1,0 }; int xorig[] = { 0,4,0,2,0,1,0 };
int yorig[] = { 0,0,4,0,2,0,1 }; int yorig[] = { 0,0,4,0,2,0,1 };
@ -4422,8 +4509,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3
for (i=0; i < x; ++i) { for (i=0; i < x; ++i) {
int out_y = j*yspc[p]+yorig[p]; int out_y = j*yspc[p]+yorig[p];
int out_x = i*xspc[p]+xorig[p]; int out_x = i*xspc[p]+xorig[p];
memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,
a->out + (j*x+i)*out_n, out_n); a->out + (j*x+i)*out_bytes, out_bytes);
} }
} }
STBI_FREE(a->out); STBI_FREE(a->out);
@ -4491,7 +4578,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
stbi_uc *p, *temp_out, *orig = a->out; stbi_uc *p, *temp_out, *orig = a->out;
p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);
if (p == NULL) return stbi__err("outofmem", "Out of memory"); if (p == NULL) return stbi__err("outofmem", "Out of memory");
// between here and free(out) below, exitting would leak // between here and free(out) below, exitting would leak
@ -5005,7 +5092,11 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
else else
target = s->img_n; // if they want monochrome, we'll post-convert target = s->img_n; // if they want monochrome, we'll post-convert
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); // sanity-check size
if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))
return stbi__errpuc("too large", "Corrupt BMP");
out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (!out) return stbi__errpuc("outofmem", "Out of memory");
if (info.bpp < 16) { if (info.bpp < 16) {
int z=0; int z=0;
@ -5306,7 +5397,10 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
*y = tga_height; *y = tga_height;
if (comp) *comp = tga_comp; if (comp) *comp = tga_comp;
tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))
return stbi__errpuc("too large", "Corrupt TGA");
tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
// skip to the data's starting position (offset usually = 0) // skip to the data's starting position (offset usually = 0)
@ -5325,7 +5419,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
// 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
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);
if (!tga_palette) { if (!tga_palette) {
STBI_FREE(tga_data); STBI_FREE(tga_data);
return stbi__errpuc("outofmem", "Out of memory"); return stbi__errpuc("outofmem", "Out of memory");
@ -5461,12 +5555,49 @@ static int stbi__psd_test(stbi__context *s)
return r; return r;
} }
// @TODO: return 16-bit PSD data to 16-bit interface static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
{
int count, nleft, len;
count = 0;
while ((nleft = pixelCount - count) > 0) {
len = stbi__get8(s);
if (len == 128) {
// No-op.
} else if (len < 128) {
// Copy next len+1 bytes literally.
len++;
if (len > nleft) return 0; // corrupt data
count += len;
while (len) {
*p = stbi__get8(s);
p += 4;
len--;
}
} else if (len > 128) {
stbi_uc val;
// Next -len+1 bytes in the dest are replicated from next source byte.
// (Interpret len as a negative 8-bit int.)
len = 257 - len;
if (len > nleft) return 0; // corrupt data
val = stbi__get8(s);
count += len;
while (len) {
*p = val;
p += 4;
len--;
}
}
}
return 1;
}
static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
{ {
int pixelCount; int pixelCount;
int channelCount, compression; int channelCount, compression;
int channel, i, count, len; int channel, i;
int bitdepth; int bitdepth;
int w,h; int w,h;
stbi_uc *out; stbi_uc *out;
@ -5527,10 +5658,14 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
if (compression > 1) if (compression > 1)
return stbi__errpuc("bad compression", "PSD has an unknown compression format"); return stbi__errpuc("bad compression", "PSD has an unknown compression format");
// Check size
if (!stbi__mad3sizes_valid(4, w, h, 0))
return stbi__errpuc("too large", "Corrupt PSD");
// Create the destination image. // Create the destination image.
if (!compression && bitdepth == 16 && bpc == 16) { if (!compression && bitdepth == 16 && bpc == 16) {
out = (stbi_uc *) stbi__malloc(4 * w*h * 2); out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
ri->bits_per_channel = 16; ri->bits_per_channel = 16;
} else } else
out = (stbi_uc *) stbi__malloc(4 * w*h); out = (stbi_uc *) stbi__malloc(4 * w*h);
@ -5566,41 +5701,16 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
*p = (channel == 3 ? 255 : 0); *p = (channel == 3 ? 255 : 0);
} else { } else {
// Read the RLE data. // Read the RLE data.
count = 0; if (!stbi__psd_decode_rle(s, p, pixelCount)) {
while (count < pixelCount) { STBI_FREE(out);
len = stbi__get8(s); return stbi__errpuc("corrupt", "bad RLE data");
if (len == 128) {
// No-op.
} else if (len < 128) {
// Copy next len+1 bytes literally.
len++;
count += len;
while (len) {
*p = stbi__get8(s);
p += 4;
len--;
}
} else if (len > 128) {
stbi_uc val;
// Next -len+1 bytes in the dest are replicated from next source byte.
// (Interpret len as a negative 8-bit int.)
len ^= 0x0FF;
len += 2;
val = stbi__get8(s);
count += len;
while (len) {
*p = val;
p += 4;
len--;
}
}
} }
} }
} }
} else { } else {
// We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
// where each channel consists of an 8-bit value for each pixel in the image. // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
// Read the data by channel. // Read the data by channel.
for (channel = 0; channel < 4; channel++) { for (channel = 0; channel < 4; channel++) {
@ -5866,14 +5976,14 @@ 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 (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 ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
stbi__get32be(s); //skip `ratio' stbi__get32be(s); //skip `ratio'
stbi__get16be(s); //skip `fields' stbi__get16be(s); //skip `fields'
stbi__get16be(s); //skip `pad' stbi__get16be(s); //skip `pad'
// intermediate buffer is RGBA // intermediate buffer is RGBA
result = (stbi_uc *) stbi__malloc(x*y*4); result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);
memset(result, 0xff, x*y*4); memset(result, 0xff, x*y*4);
if (!stbi__pic_load_core(s,x,y,comp, result)) { if (!stbi__pic_load_core(s,x,y,comp, result)) {
@ -6132,8 +6242,11 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) if (g->out == 0 && !stbi__gif_header(s, g, comp,0))
return 0; // stbi__g_failure_reason set by stbi__gif_header return 0; // stbi__g_failure_reason set by stbi__gif_header
if (!stbi__mad3sizes_valid(g->w, g->h, 4, 0))
return stbi__errpuc("too large", "GIF too large");
prev_out = g->out; prev_out = g->out;
g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0);
if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory");
switch ((g->eflags & 0x1C) >> 2) { switch ((g->eflags & 0x1C) >> 2) {
@ -6381,8 +6494,13 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
if (comp) *comp = 3; if (comp) *comp = 3;
if (req_comp == 0) req_comp = 3; if (req_comp == 0) req_comp = 3;
if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))
return stbi__errpf("too large", "HDR image is too large");
// Read data // Read data
hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);
if (!hdr_data)
return stbi__errpf("outofmem", "Out of memory");
// Load image data // Load image data
// image data is stored as some number of sca // image data is stored as some number of sca
@ -6421,20 +6539,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
len <<= 8; len <<= 8;
len |= stbi__get8(s); len |= stbi__get8(s);
if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); if (scanline == NULL) {
scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
if (!scanline) {
STBI_FREE(hdr_data);
return stbi__errpf("outofmem", "Out of memory");
}
}
for (k = 0; k < 4; ++k) { for (k = 0; k < 4; ++k) {
int nleft;
i = 0; i = 0;
while (i < width) { while ((nleft = width - i) > 0) {
count = stbi__get8(s); count = stbi__get8(s);
if (count > 128) { if (count > 128) {
// Run // Run
value = stbi__get8(s); value = stbi__get8(s);
count -= 128; count -= 128;
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z) for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = value; scanline[i++ * 4 + k] = value;
} else { } else {
// Dump // Dump
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z) for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = stbi__get8(s); scanline[i++ * 4 + k] = stbi__get8(s);
} }
@ -6443,7 +6570,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
for (i=0; i < width; ++i) for (i=0; i < width; ++i)
stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
} }
STBI_FREE(scanline); if (scanline)
STBI_FREE(scanline);
} }
return hdr_data; return hdr_data;
@ -6633,7 +6761,10 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
*y = s->img_y; *y = s->img_y;
*comp = s->img_n; *comp = s->img_n;
out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0))
return stbi__errpuc("too large", "PNM too large");
out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (!out) return stbi__errpuc("outofmem", "Out of memory");
stbi__getn(s, out, s->img_n * s->img_x * s->img_y); stbi__getn(s, out, s->img_n * s->img_x * s->img_y);