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:
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
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue