[P21.4] Fix for CVE-2009-2688

Vin Shelton <[email protected]> Sat, 14 Feb 2015 17:43:33 -0500
Newsgroups gmane.emacs.xemacs.patches
Message-ID <CACeGjnU3A_2G4VMre3L8YH596YC4i=-eGVc4vC_QnMyAU4iY1A@mail.gmail.com>
I adapted this patch from the gentoo patch by Vincent Danan (
https://bugzilla.redhat.com/show_bug.cgi?id=511994).  I used uint64_t for
the (necessary 8-byte) type, rather than the lisp.h ugliness listed there.

Please review.

  - Vin

_______________________________________________
XEmacs-Patches mailing list
[email protected]
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
xem-image.patch (text/x-patch, 3.6 KB)
diff -r a06923a62e1f src/ChangeLog
--- a/src/ChangeLog	Sat Feb 14 11:48:30 2015 -0500
+++ b/src/ChangeLog	Sat Feb 14 17:19:21 2015 -0500
@@ -1,3 +1,8 @@
+2015-02-14  Vin Shelton  <[email protected]>
+
+	* glyphs-eimage.c: CVE-2009-2688 - Check for images too large
+	(GIF, TIFF, JPEG and PNG).
+
 2015-01-29  Vin Shelton <[email protected]>
  
 	* XEmacs 21.4.23 is released
diff -r a06923a62e1f src/glyphs-eimage.c
--- a/src/glyphs-eimage.c	Sat Feb 14 11:48:30 2015 -0500
+++ b/src/glyphs-eimage.c	Sat Feb 14 17:19:21 2015 -0500
@@ -407,6 +407,7 @@
    */
 
   {
+    uint64_t pixels_sq;
     int jpeg_gray = 0;		/* if we're dealing with a grayscale */
     /* Step 4: set parameters for decompression.   */
 
@@ -430,6 +431,10 @@
 
     /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/
 
+    pixels_sq =
+      (uint64_t) cinfo.output_width * (uint64_t) cinfo.output_height;
+    if (pixels_sq > ((size_t) -1) / 3)
+      signal_image_error ("JPEG image too large to instantiate", instantiator);
     unwind.eimage = (unsigned char*) xmalloc (cinfo.output_width * cinfo.output_height * 3);
     if (!unwind.eimage)
       signal_image_error("Unable to allocate enough memory for image", instantiator);
@@ -671,6 +676,7 @@
   {
     ColorMapObject *cmo = unwind.giffile->SColorMap;
     int i, j, row, pass, interlace, slice;
+    uint64_t pixels_sq;
     unsigned char *eip;
     /* interlaced gifs have rows in this order:
        0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ...  */
@@ -679,6 +685,9 @@
 
     height = unwind.giffile->SHeight;
     width = unwind.giffile->SWidth;
+    pixels_sq = (uint64_t) width * (uint64_t) height;
+    if (pixels_sq > ((size_t) -1) / (3 * unwind.giffile->ImageCount))
+      signal_image_error ("GIF image too large to instantiate", instantiator);
     unwind.eimage = (unsigned char*)
       xmalloc (width * height * 3 * unwind.giffile->ImageCount);
     if (!unwind.eimage)
@@ -937,8 +946,12 @@
   {
     int y, padding;
     unsigned char **row_pointers;
+    uint64_t pixels_sq;
     height = png_get_image_height(png_ptr, info_ptr);
     width = png_get_image_width(png_ptr, info_ptr);
+    pixels_sq = (uint64_t) width * (uint64_t) height;
+    if (pixels_sq > ((size_t) -1) / 3)
+      signal_image_error ("PNG image too large to instantiate", instantiator);
 
     /* Wow, allocate all the memory.  Truly, exciting.
        Well, yes, there's excitement to be had.  It turns out that libpng
@@ -949,7 +962,7 @@
 
     padding = 5 * width;
     unwind.eimage = xnew_array_and_zero (unsigned char,
-					 width * height * 3 + padding);
+					 pixels_sq * 3 + padding);
 
     /* libpng expects that the image buffer passed in contains a
        picture to draw on top of if the png has any transparencies.
@@ -1286,6 +1299,7 @@
 
     uint32 *raster;
     unsigned char *ep;
+    uint64_t pixels_sq;
 
     assert (!NILP (data));
 
@@ -1308,12 +1322,15 @@
 
     TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
     TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
-    unwind.eimage = (unsigned char *) xmalloc (width * height * 3);
+    pixels_sq = (uint64_t) width * (uint64_t) height;
+    if (pixels_sq >= 1 << 29)
+      signal_image_error ("TIFF image too large to instantiate", instantiator);
+    unwind.eimage = (unsigned char *) xmalloc (pixels_sq * 3);
 
     /* #### This is little more than proof-of-concept/function testing.
        It needs to be reimplemented via scanline reads for both memory
        compactness. */
-    raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32));
+    raster = (uint32*) _TIFFmalloc ((tsize_t) (pixels_sq * sizeof (uint32)));
     if (raster != NULL)
       {
 	int i,j;