diff -p -up xemacs-21.4.22/src/glyphs-eimage.c.orig xemacs-21.4.22/src/glyphs-eimage.c --- xemacs-21.4.22/src/glyphs-eimage.c.orig 2009-09-25 19:04:58.000000000 -0300 +++ xemacs-21.4.22/src/glyphs-eimage.c 2009-09-25 19:22:37.000000000 -0300 @@ -407,6 +407,7 @@ jpeg_instantiate (Lisp_Object image_inst */ { + UINT_64_BIT pixels_sq; int jpeg_gray = 0; /* if we're dealing with a grayscale */ /* Step 4: set parameters for decompression. */ @@ -429,7 +430,10 @@ jpeg_instantiate (Lisp_Object image_inst 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 = (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 +675,7 @@ gif_instantiate (Lisp_Object image_insta { ColorMapObject *cmo = unwind.giffile->SColorMap; int i, j, row, pass, interlace, slice; + UINT_64_BIT 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 +684,9 @@ gif_instantiate (Lisp_Object image_insta 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 = (unsigned char*) xmalloc (width * height * 3 * unwind.giffile->ImageCount); if (!unwind.eimage) @@ -935,13 +943,26 @@ png_instantiate (Lisp_Object image_insta png_read_info (png_ptr, info_ptr); { - int y; + int y, padding; unsigned char **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. + Well, yes, there's excitement to be had. It turns out that libpng + strips in place, so the last row overruns the buffer if depth is 16 + or there's an alpha channel. This is a crash on Linux. So we need + to add padding. + The worst case is reducing 8 bytes (16-bit RGBA) to 3 (8-bit RGB). */ + + padding = 5 * width; + unwind.eimage = xnew_array_and_zero (unsigned char, + (size_t) (pixels_sq * 3 + padding)); - /* Wow, allocate all the memory. Truly, exciting. */ - unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 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... */ @@ -967,16 +988,15 @@ png_instantiate (Lisp_Object image_insta } else { - Lisp_Color_Instance *c; - Lisp_Object rgblist; - - c = XCOLOR_INSTANCE (bkgd); - rgblist = MAYBE_LISP_DEVMETH (XDEVICE (c->device), - color_instance_rgb_components, - (c)); - my_background.red = (unsigned short) XINT (XCAR (rgblist)); - my_background.green = (unsigned short) XINT (XCAR (XCDR (rgblist))); - my_background.blue = (unsigned short) XINT (XCAR (XCDR (XCDR (rgblist)))); + Lisp_Color_Instance *c = XCOLOR_INSTANCE (bkgd); + Lisp_Object rgb = MAYBE_LISP_DEVMETH (XDEVICE (c->device), + color_instance_rgb_components, + (c)); +#define GETCOLOR(col) my_background.col = (unsigned short) XINT (XCAR (rgb)) + GETCOLOR(red); rgb = XCDR (rgb); + GETCOLOR(green); rgb = XCDR (rgb); + GETCOLOR(blue); +#undef GETCOLOR } if (png_get_bKGD (png_ptr, info_ptr, &image_background)) @@ -989,39 +1009,38 @@ png_instantiate (Lisp_Object image_insta /* Now that we're using EImage, ask for 8bit RGB triples for any type of image*/ - /* convert palette images to full RGB */ + /* convert palette images to RGB */ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_set_expand (png_ptr); - /* send grayscale images to RGB too */ - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || - info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_palette_to_rgb (png_ptr); + /* convert grayscale images to RGB */ + else if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); - /* we can't handle alpha values */ - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha (png_ptr); - /* tell libpng to strip 16 bit depth files down to 8 bits */ - if (info_ptr->bit_depth == 16) - png_set_strip_16 (png_ptr); - /* if the image is < 8 bits, pad it out */ - if (info_ptr->bit_depth < 8) + /* pad images with depth < 8 bits */ + else if (info_ptr->bit_depth < 8) { if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) png_set_expand (png_ptr); else png_set_packing (png_ptr); } + /* strip 16-bit depth files down to 8 bits */ + if (info_ptr->bit_depth == 16) + png_set_strip_16 (png_ptr); + /* strip alpha channel + #### shouldn't we handle this? + first call png_read_update_info in case above transformations + have generated an alpha channel */ + png_read_update_info(png_ptr, info_ptr); + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha (png_ptr); png_read_image (png_ptr, row_pointers); png_read_end (png_ptr, info_ptr); -#ifdef PNG_SHOW_COMMENTS - /* #### - * I turn this off by default now, because the !%^@#!% comments - * show up every time the image is instantiated, which can get - * really really annoying. There should be some way to pass this - * type of data down into the glyph code, where you can get to it - * from lisp anyway. - WMP - */ + /* #### There should be some way to pass this type of data down + * into the glyph code, where you can get to it from lisp + * anyway. - WMP */ { int i; @@ -1036,7 +1055,6 @@ png_instantiate (Lisp_Object image_insta info_ptr->text[i].text); } } -#endif xfree (row_pointers); } @@ -1268,6 +1286,7 @@ tiff_instantiate (Lisp_Object image_inst uint32 *raster; unsigned char *ep; + UINT_64_BIT pixels_sq; assert (!NILP (data)); @@ -1290,12 +1309,15 @@ tiff_instantiate (Lisp_Object image_inst TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height); - unwind.eimage = (unsigned char *) xmalloc (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 ((size_t) 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; diff -p -up xemacs-21.4.22/src/lisp.h.orig xemacs-21.4.22/src/lisp.h --- xemacs-21.4.22/src/lisp.h.orig 2009-09-25 19:11:56.000000000 -0300 +++ xemacs-21.4.22/src/lisp.h 2009-09-25 19:39:01.000000000 -0300 @@ -122,6 +122,7 @@ char *xstrdup (const char *); #define countof(x) ((int) (sizeof(x)/sizeof((x)[0]))) #define xnew(type) ((type *) xmalloc (sizeof (type))) #define xnew_array(type, len) ((type *) xmalloc ((len) * sizeof (type))) +#define xnew_binbytes(num) xnew_array(unsigned char, num) #define xnew_and_zero(type) ((type *) xmalloc_and_zero (sizeof (type))) #define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue))) #define xnew_array_and_zero(type, len) ((type *) xmalloc_and_zero ((len) * sizeof (type))) @@ -296,6 +297,14 @@ void assert_failed (const char *, int, c #define BITS_PER_EMACS_INT (SIZEOF_EMACS_INT * BITS_PER_CHAR) +#if SIZEOF_LONG == 8 +#define INT_64_BIT long +#define UINT_64_BIT unsigned long +#elif SIZEOF_LONG_LONG == 8 +#define INT_64_BIT long long +#define UINT_64_BIT unsigned long long +#endif + /************************************************************************/ /* typedefs */