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) --- a/src/glyphs-eimage.c Mon Jun 29 08:20:47 2009 -0600 +++ b/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;