mirror of
https://github.com/nothings/stb
synced 2024-12-15 20:32:33 +03:00
Merge branch 'stb_img_overflows' of https://github.com/rygorous/stb into working
Conflicts: stb_image.h
This commit is contained in:
commit
ae241feec4
335
stb_image.h
335
stb_image.h
@ -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);
|
|
||||||
|
|
||||||
if (z->img_comp[i].raw_data == NULL) {
|
|
||||||
for(--i; i >= 0; --i) {
|
|
||||||
STBI_FREE(z->img_comp[i].raw_data);
|
|
||||||
z->img_comp[i].raw_data = NULL;
|
|
||||||
}
|
|
||||||
return stbi__err("outofmem", "Out of memory");
|
|
||||||
}
|
|
||||||
// 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].linebuf = NULL;
|
|
||||||
if (z->progressive) {
|
|
||||||
z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3;
|
|
||||||
z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3;
|
|
||||||
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 = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);
|
|
||||||
} else {
|
|
||||||
z->img_comp[i].coeff = 0;
|
z->img_comp[i].coeff = 0;
|
||||||
z->img_comp[i].raw_coeff = 0;
|
z->img_comp[i].raw_coeff = 0;
|
||||||
|
z->img_comp[i].linebuf = NULL;
|
||||||
|
z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);
|
||||||
|
if (z->img_comp[i].raw_data == NULL)
|
||||||
|
return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));
|
||||||
|
// align blocks for idct using mmx/sse
|
||||||
|
z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
|
||||||
|
if (z->progressive) {
|
||||||
|
// w2, h2 are multiples of 8 (see above)
|
||||||
|
z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
||||||
|
stbi_uc fill = 0;
|
||||||
|
if (c == 16) {
|
||||||
c = stbi__zreceive(a,2)+3;
|
c = stbi__zreceive(a,2)+3;
|
||||||
memset(lencodes+n, lencodes[n-1], c);
|
if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
|
||||||
n += c;
|
fill = lencodes[n-1];
|
||||||
} else if (c == 17) {
|
} else if (c == 17)
|
||||||
c = stbi__zreceive(a,3)+3;
|
c = stbi__zreceive(a,3)+3;
|
||||||
memset(lencodes+n, 0, c);
|
else {
|
||||||
n += c;
|
|
||||||
} 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,6 +6570,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
if (scanline)
|
||||||
STBI_FREE(scanline);
|
STBI_FREE(scanline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user