$NetBSD: patch-ab,v 1.4.14.2 2010/10/17 17:40:29 tron Exp $

Fix for CVE-2010-1526

--- src/jpegcodec.c.orig	2009-09-25 18:06:51.000000000 +0300
+++ src/jpegcodec.c	2010-10-17 08:37:03.000000000 +0300
@@ -282,6 +282,7 @@ gdip_load_jpeg_image_internal (struct jp
 	BYTE		*lines[4] = {NULL, NULL, NULL, NULL};
 	GpStatus	status;
 	int		stride;
+	unsigned long long int size;
 
 	destbuf = NULL;
 	result = NULL;
@@ -323,20 +324,21 @@ gdip_load_jpeg_image_internal (struct jp
 
 	if (cinfo.num_components == 1) {
 		result->cairo_format = CAIRO_FORMAT_A8;
-		result->active_bitmap->stride = cinfo.image_width;
 		result->active_bitmap->pixel_format = PixelFormat8bppIndexed;
+		size = 1;
 	} else if (cinfo.num_components == 3) {
 		/* libjpeg gives us RGB for many formats and
 		 * we convert to RGB format when needed. JPEG
 		 * does not support alpha (transparency). */
 		result->cairo_format = CAIRO_FORMAT_ARGB32;
-		result->active_bitmap->stride = 4 * cinfo.image_width;
 		result->active_bitmap->pixel_format = PixelFormat24bppRGB;
+		size = 4;
 	} else if (cinfo.num_components == 4) {
 		result->cairo_format = CAIRO_FORMAT_ARGB32;
-		result->active_bitmap->stride = 4 * cinfo.image_width;
 		result->active_bitmap->pixel_format = PixelFormat32bppRGB;
-	}
+		size = 4;
+	} else
+		goto error;
 
 	switch (cinfo.jpeg_color_space) {
 	case JCS_GRAYSCALE:
@@ -360,7 +362,12 @@ gdip_load_jpeg_image_internal (struct jp
 		break;
 	}
 
-	stride = result->active_bitmap->stride;
+	size *= cinfo.image_width;
+	/* stride is a (signed) _int_ and once multiplied by 4 it should hold a value that can be allocated by GdipAlloc
+	 * this effectively limits 'width' to 536870911 pixels */
+	if (size > G_MAXINT32)
+		goto error;
+	stride = result->active_bitmap->stride = size;
 
 	/* Request cairo-compat output */
 	/* libjpeg can do only following conversions,
@@ -397,7 +404,13 @@ gdip_load_jpeg_image_internal (struct jp
 
 	jpeg_start_decompress (&cinfo);
 
-	destbuf = GdipAlloc (stride * cinfo.output_height);
+	/* ensure total 'size' does not overflow an integer and fits inside our 2GB limit */
+	size *= cinfo.output_height;
+	if (size > G_MAXINT32) {
+		status = OutOfMemory;
+		goto error;
+	}
+	destbuf = GdipAlloc (size);
 	if (destbuf == NULL) {
 		status = OutOfMemory;
 		goto error;
