File xemacs-21.5.29-large-images.patch of Package xemacs

|APPROVE COMMIT 21.5
|
|This patch has been committed.  When trying to open very large image
|files (or image files with header files that claim the image is very
|large), we multiply length times width to get the number of pixels in
|the image (and possibly multiply that number if a pixel occupies more
|than 1 byte).  The multiplication can overflow, resulting in passing
|negative or insufficiently positive size values to malloc.  This patch
|checks whether the multiplication will overflow.  If so, XEmacs
|refuses to attempt to load the image.
|
|(Patch taken from upstream, already applied there)
|
--- src/glyphs-eimage.c	Mon Jun 29 08:20:47 2009 -0600
+++ src/glyphs-eimage.c	Wed Jul 01 15:42:54 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;