changeset 4646:6c6bfdb80a0c

Prevent integer overflow and subsequent crashes when attempting to load large images. See <870180fe0907011540m7509f371h97d336477145166a@mail.gmail.com> in xemacs-patches.
author Jerry James <james@xemacs.org>
date Wed, 01 Jul 2009 16:42:11 -0600
parents f2a991ff6db0
children e4ed58cb0e5b
files src/ChangeLog src/glyphs-eimage.c
diffstat 2 files changed, 28 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon Jun 29 08:20:47 2009 -0600
+++ b/src/ChangeLog	Wed Jul 01 16:42:11 2009 -0600
@@ -1,3 +1,11 @@
+2009-06-09  Jerry James  <james@xemacs.org>
+
+	* glyphs-eimage.c (jpeg_instantiate):
+	(gif_instantiate):
+	(png_instantiate):
+	(tiff_instantiate): Check for integer overflow before allocating
+	memory for an image.
+
 2009-06-20  Stephen Turnbull  <stephen@xemacs.org>
 
 	* callint.c (Finteractive): Document that (interactive) must
--- a/src/glyphs-eimage.c	Mon Jun 29 08:20:47 2009 -0600
+++ b/src/glyphs-eimage.c	Wed Jul 01 16:42:11 2009 -0600
@@ -409,6 +409,7 @@
    */
 
   {
+    UINT_64_BIT pixels_sq;
     int jpeg_gray = 0;		/* if we're dealing with a grayscale */
     /* Step 4: set parameters for decompression.   */
 
@@ -431,7 +432,10 @@
     jpeg_start_decompress (&cinfo);
 
     /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/
-
+    pixels_sq =
+      (UINT_64_BIT) cinfo.output_width * (UINT_64_BIT) cinfo.output_height;
+    if (pixels_sq > ((size_t) -1) / 3)
+      signal_image_error ("JPEG image too large to instantiate", instantiator);
     unwind.eimage =
       xnew_binbytes (cinfo.output_width * cinfo.output_height * 3);
     if (!unwind.eimage)
@@ -677,6 +681,7 @@
   {
     ColorMapObject *cmo = unwind.giffile->SColorMap;
     int i, j, row, pass, interlace, slice;
+    UINT_64_BIT pixels_sq;
     Binbyte *eip;
     /* interlaced gifs have rows in this order:
        0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ...  */
@@ -685,6 +690,9 @@
 
     height = unwind.giffile->SHeight;
     width = unwind.giffile->SWidth;
+    pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) height;
+    if (pixels_sq > ((size_t) -1) / (3 * unwind.giffile->ImageCount))
+      signal_image_error ("GIF image too large to instantiate", instantiator);
     unwind.eimage =
       xnew_binbytes (width * height * 3 * unwind.giffile->ImageCount);
     if (!unwind.eimage)
@@ -948,11 +956,15 @@
   {
     int y;
     Binbyte **row_pointers;
+    UINT_64_BIT pixels_sq;
     height = info_ptr->height;
     width = info_ptr->width;
+    pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) 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. */
-    unwind.eimage = xnew_array_and_zero (Binbyte, width * height * 3);
+    unwind.eimage = xnew_array_and_zero (Binbyte, (size_t) (pixels_sq * 3));
     /* libpng expects that the image buffer passed in contains a
        picture to draw on top of if the png has any transparencies.
        This could be a good place to pass that in... */
@@ -1299,6 +1311,7 @@
 
     uint32 *raster;
     Binbyte *ep;
+    UINT_64_BIT pixels_sq;
 
     assert (!NILP (data));
 
@@ -1321,12 +1334,15 @@
 
     TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
     TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
-    unwind.eimage = xnew_binbytes (width * height * 3);
+    pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) height;
+    if (pixels_sq >= 1 << 29)
+      signal_image_error ("TIFF image too large to instantiate", instantiator);
+    unwind.eimage = xnew_binbytes (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;