stb_image: Fix HDR/PSD RLE decoders.

Runs need to be bounds checked.

Fixes issues #315, #317.
pull/343/head
Fabian Giesen 2016-08-12 17:31:53 -07:00
parent 02190634c2
commit 62f372754f
1 changed files with 56 additions and 33 deletions

View File

@ -5392,11 +5392,49 @@ static int stbi__psd_test(stbi__context *s)
return r;
}
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 stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
int pixelCount;
int pixelCount;
int channelCount, compression;
int channel, i, count, len;
int channel, i;
int bitdepth;
int w,h;
stbi_uc *out;
@ -5493,34 +5531,9 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
*p = (channel == 3 ? 255 : 0);
} else {
// Read the RLE data.
count = 0;
while (count < pixelCount) {
len = stbi__get8(s);
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--;
}
}
if (!stbi__psd_decode_rle(s, p, pixelCount)) {
STBI_FREE(out);
return stbi__errpuc("corrupt", "bad RLE data");
}
}
}
@ -6325,20 +6338,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
len <<= 8;
len |= stbi__get8(s);
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) {
int nleft;
i = 0;
while (i < width) {
while ((nleft = width - i) > 0) {
count = stbi__get8(s);
if (count > 128) {
// Run
value = stbi__get8(s);
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)
scanline[i++ * 4 + k] = value;
} else {
// 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)
scanline[i++ * 4 + k] = stbi__get8(s);
}
@ -6347,7 +6369,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
for (i=0; i < width; ++i)
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;