Fix T42421: HDR reader could easily read past buffer (truncated HDR files e.g.) and segfault.

Now readers get an 'mem_eof' guard pointer, and they abort in case they try to go past it.
This commit is contained in:
Bastien Montagne 2014-11-21 12:26:13 +01:00
parent 7b0c529fe2
commit cc0623ff6c
Notes: blender-bot 2023-02-14 09:53:05 +01:00
Referenced by issue #42421, HDR image thumbnails cause blender to crash
1 changed files with 45 additions and 15 deletions

View File

@ -72,10 +72,13 @@ typedef float fCOLOR[3];
#define COPY_RGBE(c1, c2) (c2[RED] = c1[RED], c2[GRN] = c1[GRN], c2[BLU] = c1[BLU], c2[EXP] = c1[EXP])
/* read routines */
static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax, unsigned char *mem_eof)
{
int i, rshift = 0, len = xmax;
while (len > 0) {
if (mem_eof - mem < 4) {
return NULL;
}
scan[0][RED] = *mem++;
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
@ -97,34 +100,62 @@ static unsigned char *oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
return mem;
}
static unsigned char *freadcolrs(RGBE *scan, unsigned char *mem, int xmax)
static unsigned char *freadcolrs(RGBE *scan, unsigned char *mem, int xmax, unsigned char *mem_eof)
{
int i, j, code, val;
if ((xmax < MINELEN) | (xmax > MAXELEN)) return oldreadcolrs(scan, mem, xmax);
if (mem_eof - mem < 4) {
return NULL;
}
if ((xmax < MINELEN) | (xmax > MAXELEN)) {
return oldreadcolrs(scan, mem, xmax, mem_eof);
}
i = *mem++;
if (i != 2) return oldreadcolrs(scan, mem - 1, xmax);
if (i != 2) {
return oldreadcolrs(scan, mem - 1, xmax, mem_eof);
}
scan[0][GRN] = *mem++;
scan[0][BLU] = *mem++;
i = *mem++;
if (((scan[0][BLU] << 8) | i) != xmax) return NULL;
for (i = 0; i < 4; i++)
if (scan[0][GRN] != 2 || scan[0][BLU] & 128) {
scan[0][RED] = 2;
scan[0][EXP] = i;
return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof);
}
if (((scan[0][BLU] << 8) | i) != xmax) {
return NULL;
}
for (i = 0; i < 4; i++) {
if (mem_eof - mem < 2) {
return NULL;
}
for (j = 0; j < xmax; ) {
code = *mem++;
if (code > 128) {
code &= 127;
val = *mem++;
while (code--)
while (code--) {
scan[j++][i] = (unsigned char)val;
}
}
else
while (code--)
else {
if (mem_eof - mem < code) {
return NULL;
}
while (code--) {
scan[j++][i] = *mem++;
}
}
}
}
return mem;
}
@ -182,7 +213,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
int found = 0;
int width = 0, height = 0;
int x, y;
unsigned char *ptr;
unsigned char *ptr, *mem_eof = mem + size;
char oriY[80], oriX[80];
if (imb_is_a_hdr((void *)mem)) {
@ -218,15 +249,14 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
if (flags & IB_test) return ibuf;
/* read in and decode the actual data */
sline = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_read_tmpscan");
sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
rect_float = ibuf->rect_float;
for (y = 0; y < height; y++) {
ptr = freadcolrs(sline, ptr, width);
ptr = freadcolrs(sline, ptr, width, mem_eof);
if (ptr == NULL) {
printf("HDR decode error\n");
MEM_freeN(sline);
return ibuf;
printf("WARNING! HDR decode error, image may be just truncated, or completely wrong...\n");
break;
}
for (x = 0; x < width; x++) {
/* convert to ldr */