[Bf-blender-cvs] [cc0623f] master: Fix T42421: HDR reader could easily read past buffer (truncated HDR files e.g.) and segfault.

Bastien Montagne noreply at git.blender.org
Fri Nov 21 12:28:33 CET 2014


Commit: cc0623ff6c97c8bde5045f9aba1014f6dbd6bc8e
Author: Bastien Montagne
Date:   Fri Nov 21 12:26:13 2014 +0100
Branches: master
https://developer.blender.org/rBcc0623ff6c97c8bde5045f9aba1014f6dbd6bc8e

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 */




More information about the Bf-blender-cvs mailing list