changeset 66195:ad1acaef1abb

* image.c (Vmax_image_size): New variable. (check_image_size): New function. (xbm_read_bitmap_data, pbm_load, png_load, jpeg_load, tiff_load) (gif_load, gs_load): Use it. (lookup_image): Try loading again if previous load failed. (xbm_read_bitmap_data): Add a new argument, a pointer to the frame to display in, NULL if none. (xbm_load_image, xbm_file_p): Pass xbm_read_bitmap_data the new argument.
author Chong Yidong <cyd@stupidchicken.com>
date Wed, 19 Oct 2005 03:54:56 +0000
parents 6b43bb0a3a9c
children 2e59eea25fcf
files src/ChangeLog src/image.c
diffstat 2 files changed, 100 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Oct 19 01:52:59 2005 +0000
+++ b/src/ChangeLog	Wed Oct 19 03:54:56 2005 +0000
@@ -1,3 +1,15 @@
+2005-10-18  Chong Yidong  <cyd@stupidchicken.com>
+
+	* image.c (Vmax_image_size): New variable.
+	(check_image_size): New function.
+	(xbm_read_bitmap_data, pbm_load, png_load, jpeg_load, tiff_load)
+	(gif_load, gs_load): Use it.
+	(lookup_image): Try loading again if previous load failed.
+	(xbm_read_bitmap_data): Add a new argument, a pointer to the frame
+	to display in, NULL if none.
+	(xbm_load_image, xbm_file_p): Pass xbm_read_bitmap_data the new
+	argument.
+
 2005-10-18  Richard M. Stallman  <rms@gnu.org>
 
 	* search.c (Fstring_match): Doc fix.
--- a/src/image.c	Wed Oct 19 01:52:59 2005 +0000
+++ b/src/image.c	Wed Oct 19 03:54:56 2005 +0000
@@ -1099,7 +1099,10 @@
 
 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
 static void free_image P_ ((struct frame *f, struct image *img));
-
+static int check_image_size P_ ((struct frame *f, int width, int height));
+
+#define MAX_IMAGE_SIZE 6.0
+Lisp_Object Vmax_image_size;
 
 /* Allocate and return a new image structure for image specification
    SPEC.  SPEC has a hash value of HASH.  */
@@ -1151,6 +1154,27 @@
     }
 }
 
+/* Return 1 if the given widths and heights are valid for display;
+   otherwise, return 0. */
+
+int
+check_image_size (f, width, height)
+     struct frame *f;
+     int width;
+     int height;
+{
+  if (width <= 0 || height <=0)
+    return 0;
+
+  if (FLOATP (Vmax_image_size) && f
+      && ((width > (int)(XFLOAT_DATA (Vmax_image_size)
+  			 * FRAME_PIXEL_WIDTH (f)))
+  	  || (height > (int)(XFLOAT_DATA (Vmax_image_size)
+  			     * FRAME_PIXEL_HEIGHT (f)))))
+    return 0;
+
+  return 1;
+}
 
 /* Prepare image IMG for display on frame F.  Must be called before
    drawing an image.  */
@@ -1708,6 +1732,12 @@
     if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
       break;
 
+  if (img && img->load_failed_p)
+    {
+      free_image (f, img);
+      img = NULL;
+    }
+
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
@@ -2551,7 +2581,8 @@
 static int xbm_load_image P_ ((struct frame *f, struct image *img,
 			       unsigned char *, unsigned char *));
 static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *,
+static int xbm_read_bitmap_data P_ ((struct frame *f,
+				     unsigned char *, unsigned char *,
 				     int *, int *, unsigned char **));
 static int xbm_file_p P_ ((Lisp_Object));
 
@@ -2939,7 +2970,8 @@
    CONTENTS looks like an in-memory XBM file.  */
 
 static int
-xbm_read_bitmap_data (contents, end, width, height, data)
+xbm_read_bitmap_data (f, contents, end, width, height, data)
+     struct frame *f;
      unsigned char *contents, *end;
      int *width, *height;
      unsigned char **data;
@@ -2992,7 +3024,7 @@
       expect (XBM_TK_NUMBER);
     }
 
-  if (*width < 0 || *height < 0)
+  if (!check_image_size (f, *width, *height))
     goto failure;
   else if (data == NULL)
     goto success;
@@ -3096,7 +3128,7 @@
   unsigned char *data;
   int success_p = 0;
 
-  rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
+  rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
   if (rc)
     {
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
@@ -3150,7 +3182,7 @@
 {
   int w, h;
   return (STRINGP (data)
-	  && xbm_read_bitmap_data (SDATA (data),
+	  && xbm_read_bitmap_data (NULL, SDATA (data),
 				   (SDATA (data)
 				    + SBYTES (data)),
 				   &w, &h, NULL));
@@ -5465,8 +5497,7 @@
 	max_color_idx = 255;
     }
 
-  if (width < 0
-      || height < 0
+  if (!check_image_size (f, width, height)
       || (type != PBM_MONO && max_color_idx < 0))
     goto error;
 
@@ -5966,6 +5997,9 @@
   fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
 		   &interlace_type, NULL, NULL);
 
+  if (!check_image_size (f, width, height))
+    goto error;
+
   /* If image contains simply transparency data, we prefer to
      construct a clipping mask.  */
   if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
@@ -6726,6 +6760,12 @@
   width = img->width = cinfo.output_width;
   height = img->height = cinfo.output_height;
 
+  if (!check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      longjmp (mgr.setjmp_buffer, 2);
+    }
+
   /* Create X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     longjmp (mgr.setjmp_buffer, 2);
@@ -7155,6 +7195,14 @@
      of width x height 32-bit values.  */
   fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
   fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+
+  if (!check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      UNGCPRO;
+      return 0;
+    }
+
   buf = (uint32 *) xmalloc (width * height * sizeof *buf);
 
   rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
@@ -7459,6 +7507,15 @@
 	}
     }
 
+  /* Before reading entire contents, check the declared image size. */
+  if (!check_image_size (f, gif->SWidth, gif->SHeight))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      fn_DGifCloseFile (gif);
+      UNGCPRO;
+      return 0;
+    }
+
   /* Read entire contents.  */
   rc = fn_DGifSlurp (gif);
   if (rc == GIF_ERROR)
@@ -7492,6 +7549,14 @@
 			      max (gif->Image.Top + gif->Image.Height,
 				   image_top + image_height));
 
+  if (!check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      fn_DGifCloseFile (gif);
+      UNGCPRO;
+      return 0;
+    }
+
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
@@ -7944,6 +8009,12 @@
   in_height = XFASTINT (pt_height) / 72.0;
   img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
 
+  if (!check_image_size (f, img->width, img->height))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      return 0;
+    }
+
   /* Create the pixmap.  */
   xassert (img->pixmap == NO_PIXMAP);
 
@@ -8217,6 +8288,15 @@
   Vimage_library_alist = Qnil;
   Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
 
+  DEFVAR_LISP ("max-image-size", &Vmax_image_size,
+    doc: /* Maximum size of an image, relative to the selected frame.
+
+This is a floating point number that is multiplied by the width and
+height of the selected frame, to give the maximum width and height for
+images.  Emacs will not load an image into memory if its width or
+height exceeds this limit. */);
+  Vmax_image_size = make_float (MAX_IMAGE_SIZE);
+
   Vimage_type_cache = Qnil;
   staticpro (&Vimage_type_cache);