Commit: b0ea6aecb3582e223b85e0cc336b5afcc8600ede
Author: Bastien Montagne
Date:   Fri Nov 21 12:26:13 2014 +0100
Branches: input_method_editor
https://developer.blender.org/rBb0ea6aecb3582e223b85e0cc336b5afcc8600ede

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.

===================================================================

M       source/blender/imbuf/intern/radiance_hdr.c

===================================================================

diff --git a/source/blender/imbuf/intern/radiance_hdr.c 
b/source/blender/imbuf/intern/radiance_hdr.c
index db26854..2a4df2a 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -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 */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to