[PATCH 1/6] Fix CVE-2010-1519

James Le Cuirot chewi at aura-online.co.uk
Sun Jun 1 15:28:36 PDT 2014


From: Hans de Goede <hdegoede at redhat.com>

---
 src/glpng.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/src/glpng.c b/src/glpng.c
index 4bbf238..688bbba 100644
--- a/src/glpng.c
+++ b/src/glpng.c
@@ -31,6 +31,7 @@
 #include <GL/gl.h>
 #include <GL/glext.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <math.h>
 #include <png.h>
 
@@ -262,9 +263,9 @@ int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
 	png_structp png;
 	png_infop   info;
 	png_infop   endinfo;
-	png_bytep   data;
-   png_bytep  *row_p;
-   double	fileGamma;
+	png_bytep   data = NULL;
+	png_bytep  *row_p = NULL;
+	double      fileGamma;
 
 	png_uint_32 width, height;
 	int depth, color;
@@ -277,13 +278,19 @@ int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
 	if (!png_check_sig(header, 8)) return 0;
 
 	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if (!png) return 0;
 	info = png_create_info_struct(png);
+	if (!info) return 0;
 	endinfo = png_create_info_struct(png);
+	if (!endinfo) return 0;
 
 	// DH: added following lines
 	if (setjmp(png_jmpbuf(png)))
 	{
+error:
 		png_destroy_read_struct(&png, &info, &endinfo);
+		free(data);
+		free(row_p);
 		return 0;
 	}
 	// ~DH
@@ -306,8 +313,16 @@ int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
 
 	png_read_update_info(png, info);
 
+	/* HDG: We allocate all the png data in one linear array, thus
+	   height * png_get_rowbytes() may not be > PNG_UINT_32_MAX !
+	   This check fixes CVE-2010-1519. */
+	if ((uint64_t)height * png_get_rowbytes(png, info) > PNG_UINT_32_MAX)
+		goto error;
+
 	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
 	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
+	if (!data || !row_p)
+		goto error;
 
 	for (i = 0; i < height; i++) {
 		if (StandardOrientation)
@@ -318,6 +333,7 @@ int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
 
 	png_read_image(png, row_p);
 	free(row_p);
+	row_p = NULL;
 
 	if (color == PNG_COLOR_TYPE_PALETTE) {
 		int cols;
@@ -368,9 +384,10 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 	png_structp png;
 	png_infop   info;
 	png_infop   endinfo;
-	png_bytep   data, data2;
-   png_bytep  *row_p;
-   double	fileGamma;
+	png_bytep   data = NULL;
+	png_bytep   data2 = NULL;
+	png_bytep  *row_p = NULL;
+	double      fileGamma;
 
 	png_uint_32 width, height, rw, rh;
 	int depth, color;
@@ -381,13 +398,20 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 	if (!png_check_sig(header, 8)) return 0;
 
 	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if (!png) return 0;
 	info = png_create_info_struct(png);
+	if (!info) return 0;
 	endinfo = png_create_info_struct(png);
+	if (!endinfo) return 0;
 
 	// DH: added following lines
 	if (setjmp(png_jmpbuf(png)))
 	{
+error:
 		png_destroy_read_struct(&png, &info, &endinfo);
+		free(data);
+		free(data2);
+		free(row_p);
 		return 0;
 	}
 	// ~DH
@@ -445,8 +469,16 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 
 	png_read_update_info(png, info);
 
+	/* HDG: We allocate all the png data in one linear array, thus
+	   height * png_get_rowbytes() may not be > PNG_UINT_32_MAX !
+	   This check fixes CVE-2010-1519. */
+	if ((uint64_t)height * png_get_rowbytes(png, info) > PNG_UINT_32_MAX)
+		goto error;
+
 	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
 	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);
+	if (!data || !row_p)
+		goto error;
 
 	for (i = 0; i < height; i++) {
 		if (StandardOrientation)
@@ -457,6 +489,7 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 
 	png_read_image(png, row_p);
 	free(row_p);
+	row_p = NULL;
 
 	rw = SafeSize(width), rh = SafeSize(height);
 
@@ -464,6 +497,8 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 		const int channels = png_get_rowbytes(png, info)/width;
 
 		data2 = (png_bytep) malloc(rw*rh*channels);
+		if (!data2)
+			goto error;
 
  		/* Doesn't work on certain sizes */
 /* 		if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0)
@@ -474,6 +509,7 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 		width = rw, height = rh;
 		free(data);
 		data = data2;
+		data2 = NULL;
 	}
 
 	{ /* OpenGL stuff */
@@ -543,6 +579,12 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
 			png_bytep p, endp, q;
 			int r, g, b, a;
 
+			/* HDG another potential 32 bit address overflow, the
+			   original png had 3 channels and we are going to
+			   4 channels now! */
+			if ((uint64_t)width * height > (PNG_UINT_32_MAX >> 2))
+				goto error;
+
 			p = data, endp = p+width*height*3;
 			q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4);
 
-- 
1.9.2



More information about the Games mailing list