# HG changeset patch # User Jerry James # Date 1246488131 21600 # Node ID 6c6bfdb80a0c435a323a0b489174dce5820eb87c # Parent f2a991ff6db0211cbcb8729cd2393c5898f09c13 Prevent integer overflow and subsequent crashes when attempting to load large images. See <870180fe0907011540m7509f371h97d336477145166a@mail.gmail.com> in xemacs-patches. diff -r f2a991ff6db0 -r 6c6bfdb80a0c src/ChangeLog --- 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 + + * 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 * callint.c (Finteractive): Document that (interactive) must diff -r f2a991ff6db0 -r 6c6bfdb80a0c src/glyphs-eimage.c --- 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;