]> code.delx.au - gnu-emacs/blobdiff - src/image.c
Overflow, signedness and related fixes for images.
[gnu-emacs] / src / image.c
index 0f269f46492666cda6bd32eda22c79ff91c8cb59..3a58be5d85eab2d5bd998036e99a97f993a9b673 100644 (file)
@@ -48,6 +48,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termhooks.h"
 #include "font.h"
 
+#define RANGED_INTEGERP(lo, x, hi) \
+  (INTEGERP (x) && (lo) <= XINT (x) && XINT (x) <= (hi))
+#define TYPE_RANGED_INTEGERP(type, x) \
+  RANGED_INTEGERP (TYPE_MINIMUM (type), x, TYPE_MAXIMUM (type))
+
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #include <sys/types.h>
@@ -136,7 +141,6 @@ static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b);
 #ifdef COLOR_TABLE_SUPPORT
 static void free_color_table (void);
 static unsigned long *colors_in_color_table (int *n);
-static unsigned long lookup_pixel_color (struct frame *f, unsigned long p);
 #endif
 static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object);
 
@@ -182,28 +186,28 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
 /* Functions to access the contents of a bitmap, given an id.  */
 
 int
-x_bitmap_height (FRAME_PTR f, int id)
+x_bitmap_height (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
 }
 
 int
-x_bitmap_width (FRAME_PTR f, int id)
+x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
 }
 
 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
 int
-x_bitmap_pixmap (FRAME_PTR f, int id)
+x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
 {
-  return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
+  return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
 }
 #endif
 
 #ifdef HAVE_X_WINDOWS
 int
-x_bitmap_mask (FRAME_PTR f, int id)
+x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
 }
@@ -211,11 +215,11 @@ x_bitmap_mask (FRAME_PTR f, int id)
 
 /* Allocate a new bitmap record.  Returns index of new record.  */
 
-static int
+static ptrdiff_t
 x_allocate_bitmap_record (FRAME_PTR f)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int i;
+  ptrdiff_t i;
 
   if (dpyinfo->bitmaps == NULL)
     {
@@ -233,6 +237,9 @@ x_allocate_bitmap_record (FRAME_PTR f)
     if (dpyinfo->bitmaps[i].refcount == 0)
       return i + 1;
 
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2
+      < dpyinfo->bitmaps_size)
+    memory_full (SIZE_MAX);
   dpyinfo->bitmaps_size *= 2;
   dpyinfo->bitmaps
     = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
@@ -243,18 +250,18 @@ x_allocate_bitmap_record (FRAME_PTR f)
 /* Add one reference to the reference count of the bitmap with id ID.  */
 
 void
-x_reference_bitmap (FRAME_PTR f, int id)
+x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
 {
   ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
 }
 
 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS.  */
 
-int
+ptrdiff_t
 x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsigned int height)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int id;
+  ptrdiff_t id;
 
 #ifdef HAVE_X_WINDOWS
   Pixmap bitmap;
@@ -309,7 +316,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
 
 /* Create bitmap from file FILE for frame F.  */
 
-int
+ptrdiff_t
 x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
@@ -319,7 +326,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  int id;
+  ptrdiff_t id;
   void *bitmap = ns_image_from_file (file);
 
   if (!bitmap)
@@ -340,7 +347,8 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 #ifdef HAVE_X_WINDOWS
   unsigned int width, height;
   Pixmap bitmap;
-  int xhot, yhot, result, id;
+  int xhot, yhot, result;
+  ptrdiff_t id;
   Lisp_Object found;
   int fd;
   char *filename;
@@ -413,7 +421,7 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
 /* Remove reference to bitmap with id number ID.  */
 
 void
-x_destroy_bitmap (FRAME_PTR f, int id)
+x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -435,7 +443,7 @@ x_destroy_bitmap (FRAME_PTR f, int id)
 void
 x_destroy_all_bitmaps (Display_Info *dpyinfo)
 {
-  int i;
+  ptrdiff_t i;
   Bitmap_Record *bm = dpyinfo->bitmaps;
 
   for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
@@ -467,7 +475,7 @@ static void x_destroy_x_image (XImagePtr ximg);
    It's nicer with some borders in this context */
 
 int
-x_create_bitmap_mask (struct frame *f, int id)
+x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
 {
   Pixmap pixmap, mask;
   XImagePtr ximg, mask_img;
@@ -564,7 +572,6 @@ static Lisp_Object Qxbm;
 /* Keywords.  */
 
 Lisp_Object QCascent, QCmargin, QCrelief;
-static Lisp_Object Qcount, Qextension_data;
 Lisp_Object QCconversion;
 static Lisp_Object QCheuristic_mask;
 static Lisp_Object QCcolor_symbols;
@@ -573,6 +580,7 @@ static Lisp_Object QCcrop, QCrotation;
 
 /* Other symbols.  */
 
+static Lisp_Object Qcount, Qextension_data, Qdelay;
 static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Function prototypes.  */
@@ -804,29 +812,30 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
          break;
 
        case IMAGE_POSITIVE_INTEGER_VALUE:
-         if (!INTEGERP (value) || XINT (value) <= 0)
+         if (! RANGED_INTEGERP (1, value, INT_MAX))
            return 0;
          break;
 
        case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
-         if (INTEGERP (value) && XINT (value) >= 0)
+         if (RANGED_INTEGERP (1, value, INT_MAX))
            break;
          if (CONSP (value)
-             && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
-             && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+             && RANGED_INTEGERP (1, XCAR (value), INT_MAX)
+             && RANGED_INTEGERP (1, XCDR (value), INT_MAX))
            break;
          return 0;
 
        case IMAGE_ASCENT_VALUE:
          if (SYMBOLP (value) && EQ (value, Qcenter))
            break;
-         else if (INTEGERP (value)
-                  && XINT (value) >= 0
-                  && XINT (value) <= 100)
+         else if (RANGED_INTEGERP (0, value, 100))
            break;
          return 0;
 
        case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
+         /* Unlike the other integer-related cases, this one does not
+            verify that VALUE fits in 'int'.  This is because callers
+            want EMACS_INT.  */
          if (!INTEGERP (value) || XINT (value) < 0)
            return 0;
          break;
@@ -846,7 +855,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
          break;
 
        case IMAGE_INTEGER_VALUE:
-         if (!INTEGERP (value))
+         if (! TYPE_RANGED_INTEGERP (int, value))
            return 0;
          break;
 
@@ -916,7 +925,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
@@ -946,7 +955,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       if (img->mask)
        mask = Qt;
@@ -969,9 +978,9 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
-      ext = img->data.lisp_val;
+      ext = img->lisp_data;
     }
 
   return ext;
@@ -982,16 +991,14 @@ or omitted means use the selected frame.  */)
                 Image type independent image structures
  ***********************************************************************/
 
-static struct image *make_image (Lisp_Object spec, unsigned hash);
 static void free_image (struct frame *f, struct image *img);
-static int check_image_size (struct frame *f, int width, int height);
 
 #define MAX_IMAGE_SIZE 6.0
 /* Allocate and return a new image structure for image specification
    SPEC.  SPEC has a hash value of HASH.  */
 
 static struct image *
-make_image (Lisp_Object spec, unsigned int hash)
+make_image (Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
   Lisp_Object file = image_spec_value (spec, QCfile, NULL);
@@ -1002,7 +1009,7 @@ make_image (Lisp_Object spec, unsigned int hash)
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
   xassert (img->type != NULL);
   img->spec = spec;
-  img->data.lisp_val = Qnil;
+  img->lisp_data = Qnil;
   img->ascent = DEFAULT_IMAGE_ASCENT;
   img->hash = hash;
   img->corners[BOT_CORNER] = -1;  /* Full image */
@@ -1039,7 +1046,7 @@ free_image (struct frame *f, struct image *img)
 /* Return 1 if the given widths and heights are valid for display;
    otherwise, return 0. */
 
-int
+static int
 check_image_size (struct frame *f, int width, int height)
 {
   int w, h;
@@ -1048,23 +1055,18 @@ check_image_size (struct frame *f, int width, int height)
     return 0;
 
   if (INTEGERP (Vmax_image_size))
-    w = h = XINT (Vmax_image_size);
+    return (width <= XINT (Vmax_image_size)
+           && height <= XINT (Vmax_image_size));
   else if (FLOATP (Vmax_image_size))
     {
-      if (f != NULL)
-       {
-         w = FRAME_PIXEL_WIDTH (f);
-         h = FRAME_PIXEL_HEIGHT (f);
-       }
-      else
-       w = h = 1024;  /* Arbitrary size for unknown frame. */
-      w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
-      h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
+      xassert (f);
+      w = FRAME_PIXEL_WIDTH (f);
+      h = FRAME_PIXEL_HEIGHT (f);
+      return (width <= XFLOAT_DATA (Vmax_image_size) * w
+             && height <= XFLOAT_DATA (Vmax_image_size) * h);
     }
   else
     return 1;
-
-  return (width <= w && height <= h);
 }
 
 /* Prepare image IMG for display on frame F.  Must be called before
@@ -1125,7 +1127,7 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
        ascent = height / 2;
     }
   else
-    ascent = (int) (height * img->ascent / 100.0);
+    ascent = height * (img->ascent / 100.0);
 
   return ascent;
 }
@@ -1365,7 +1367,9 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
 
   xassert (STRINGP (color_name));
 
-  if (x_defined_color (f, SSDATA (color_name), &color, 1))
+  if (x_defined_color (f, SSDATA (color_name), &color, 1)
+      && img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors,
+                            INT_MAX))
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
@@ -1388,7 +1392,6 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
                             Image Cache
  ***********************************************************************/
 
-static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
 static void cache_image (struct frame *f, struct image *img);
 static void postprocess_image (struct frame *, struct image *);
 
@@ -1414,7 +1417,7 @@ make_image_cache (void)
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
-search_image_cache (struct frame *f, Lisp_Object spec, unsigned int hash)
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1469,7 +1472,7 @@ free_image_cache (struct frame *f)
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
   if (c)
     {
-      int i;
+      ptrdiff_t i;
 
       /* Cache should not be referenced by any frame when freed.  */
       xassert (c->refcount == 0);
@@ -1499,7 +1502,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
 
   if (c)
     {
-      int i, nfreed = 0;
+      ptrdiff_t i, nfreed = 0;
 
       /* Block input so that we won't be interrupted by a SIGIO
         while being in an inconsistent state.  */
@@ -1523,8 +1526,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
        {
          /* Free cache based on timestamp.  */
          EMACS_TIME t;
-         time_t old;
-         int delay, nimages = 0;
+         double old, delay;
+         ptrdiff_t nimages = 0;
 
          for (i = 0; i < c->used; ++i)
            if (c->images[i])
@@ -1532,9 +1535,10 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
 
          /* If the number of cached images has grown unusually large,
             decrease the cache eviction delay (Bug#6230).  */
-         delay = XFASTINT (Vimage_cache_eviction_delay);
+         delay = XINT (Vimage_cache_eviction_delay);
          if (nimages > 40)
-           delay = max (1, 1600 * delay / (nimages*nimages));
+           delay = 1600 * delay / nimages / nimages;
+         delay = max (delay, 1);
 
          EMACS_GET_TIME (t);
          old = EMACS_SECS (t) - delay;
@@ -1710,11 +1714,11 @@ postprocess_image (struct frame *f, struct image *img)
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
-int
+ptrdiff_t
 lookup_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img;
-  unsigned hash;
+  EMACS_UINT hash;
   EMACS_TIME now;
 
   /* F must be a window-system frame, and SPEC must be a valid image
@@ -1769,15 +1773,12 @@ lookup_image (struct frame *f, Lisp_Object spec)
            img->ascent = CENTERED_IMAGE_ASCENT;
 
          margin = image_spec_value (spec, QCmargin, NULL);
-         if (INTEGERP (margin) && XINT (margin) >= 0)
+         if (INTEGERP (margin))
            img->vmargin = img->hmargin = XFASTINT (margin);
-         else if (CONSP (margin) && INTEGERP (XCAR (margin))
-                  && INTEGERP (XCDR (margin)))
+         else if (CONSP (margin))
            {
-             if (XINT (XCAR (margin)) > 0)
-               img->hmargin = XFASTINT (XCAR (margin));
-             if (XINT (XCDR (margin)) > 0)
-               img->vmargin = XFASTINT (XCDR (margin));
+             img->hmargin = XFASTINT (XCAR (margin));
+             img->vmargin = XFASTINT (XCDR (margin));
            }
 
          relief = image_spec_value (spec, QCrelief, NULL);
@@ -1824,7 +1825,7 @@ static void
 cache_image (struct frame *f, struct image *img)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int i;
+  ptrdiff_t i;
 
   /* Find a free slot in c->images.  */
   for (i = 0; i < c->used; ++i)
@@ -1834,6 +1835,8 @@ cache_image (struct frame *f, struct image *img)
   /* If no free slot found, maybe enlarge c->images.  */
   if (i == c->used && c->used == c->size)
     {
+      if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size)
+       memory_full (SIZE_MAX);
       c->size *= 2;
       c->images = (struct image **) xrealloc (c->images,
                                              c->size * sizeof *c->images);
@@ -1866,8 +1869,8 @@ mark_image (struct image *img)
   mark_object (img->spec);
   mark_object (img->dependencies);
 
-  if (!NILP (img->data.lisp_val))
-    mark_object (img->data.lisp_val);
+  if (!NILP (img->lisp_data))
+    mark_object (img->lisp_data);
 }
 
 
@@ -1876,7 +1879,7 @@ mark_image_cache (struct image_cache *c)
 {
   if (c)
     {
-      int i;
+      ptrdiff_t i;
       for (i = 0; i < c->used; ++i)
        if (c->images[i])
          mark_image (c->images[i]);
@@ -1907,6 +1910,38 @@ static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
 static void x_destroy_x_image (XImagePtr);
 static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
 
+/* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break X.
+   WIDTH and HEIGHT must both be positive.
+   If XIMG is null, assume it is a bitmap.  */
+static int
+x_check_image_size (XImagePtr ximg, int width, int height)
+{
+  /* Respect Xlib's limits: it cannot deal with images that have more
+     than INT_MAX (and/or UINT_MAX) bytes.  And respect Emacs's limits
+     of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object.  For now,
+     assume all windowing systems have the same limits that X does.  */
+  enum
+  {
+    XLIB_BYTES_MAX = min (INT_MAX, UINT_MAX),
+    X_IMAGE_BYTES_MAX = min (XLIB_BYTES_MAX, min (PTRDIFF_MAX, SIZE_MAX))
+  };
+
+  int bitmap_pad, depth, bytes_per_line;
+  if (ximg)
+    {
+      bitmap_pad = ximg->bitmap_pad;
+      depth = ximg->depth;
+      bytes_per_line = ximg->bytes_per_line;
+    }
+  else
+    {
+      bitmap_pad = 8;
+      depth = 1;
+      bytes_per_line = (width >> 3) + ((width & 7) != 0);
+    }
+  return (width <= (INT_MAX - (bitmap_pad - 1)) / depth
+         && height <= X_IMAGE_BYTES_MAX / bytes_per_line);
+}
 
 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
    frame F.  Set *XIMG and *PIXMAP to the XImage and Pixmap created.
@@ -1939,6 +1974,15 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
       return 0;
     }
 
+  if (! x_check_image_size (*ximg, width, height))
+    {
+      x_destroy_x_image (*ximg);
+      *ximg = NULL;
+      image_error ("Image too large (%dx%d)",
+                  make_number (width), make_number (height));
+      return 0;
+    }
+
   /* Allocate image raster.  */
   (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
 
@@ -1985,11 +2029,6 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
     palette_colors = 1 << depth - 1;
 
   *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
-  if (*ximg == NULL)
-    {
-      image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
-      return 0;
-    }
 
   header = &(*ximg)->info.bmiHeader;
   memset (&(*ximg)->info, 0, sizeof (BITMAPINFO));
@@ -2031,7 +2070,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
       DWORD err = GetLastError ();
       Lisp_Object errcode;
       /* All system errors are < 10000, so the following is safe.  */
-      XSETINT (errcode, (int) err);
+      XSETINT (errcode, err);
       image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
       x_destroy_x_image (*ximg);
       return 0;
@@ -2114,9 +2153,6 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
                              File Handling
  ***********************************************************************/
 
-static unsigned char *slurp_file (char *, int *);
-
-
 /* Find image file FILE.  Look in data-directory/images, then
    x-bitmap-file-path.  Value is the encoded full name of the file
    found, or nil if not found.  */
@@ -2153,7 +2189,7 @@ x_find_image_file (Lisp_Object file)
    occurred.  *SIZE is set to the size of the file.  */
 
 static unsigned char *
-slurp_file (char *file, int *size)
+slurp_file (char *file, ptrdiff_t *size)
 {
   FILE *fp = NULL;
   unsigned char *buf = NULL;
@@ -2161,6 +2197,7 @@ slurp_file (char *file, int *size)
 
   if (stat (file, &st) == 0
       && (fp = fopen (file, "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (unsigned char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -2328,7 +2365,7 @@ xbm_image_p (Lisp_Object object)
         data.  */
       if (VECTORP (data))
        {
-         int i;
+         EMACS_INT i;
 
          /* Number of elements of the vector must be >= height.  */
          if (ASIZE (data) < height)
@@ -2363,7 +2400,7 @@ xbm_image_p (Lisp_Object object)
        }
       else if (BOOL_VECTOR_P (data))
        {
-         if (XBOOL_VECTOR (data)->size < width * height)
+         if (XBOOL_VECTOR (data)->size / height < width)
            return 0;
        }
       else
@@ -2559,13 +2596,15 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
   img->pixmap = ns_image_from_XBM (data, img->width, img->height);
 
 #else
-  img->pixmap
-    = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
+  img->pixmap =
+   (x_check_image_size (0, img->width, img->height)
+    ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
                                   FRAME_X_WINDOW (f),
                                   data,
                                   img->width, img->height,
                                   fg, bg,
-                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)))
+    : NO_PIXMAP);
 #endif /* !HAVE_NTGUI && !HAVE_NS */
 }
 
@@ -2672,6 +2711,13 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
   expect ('=');
   expect ('{');
 
+  if (! x_check_image_size (0, *width, *height))
+    {
+      if (!inhibit_image_error)
+       image_error ("Image too large (%dx%d)",
+                    make_number (*width), make_number (*height));
+      goto failure;
+    }
   bytes_per_line = (*width + 7) / 8 + padding_p;
   nbytes = bytes_per_line * *height;
   p = *data = (char *) xmalloc (nbytes);
@@ -2816,7 +2862,7 @@ xbm_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -2833,6 +2879,7 @@ xbm_load (struct frame *f, struct image *img)
        }
 
       success_p = xbm_load_image (f, img, contents, contents + size);
+      xfree (contents);
     }
   else
     {
@@ -2861,6 +2908,12 @@ xbm_load (struct frame *f, struct image *img)
          img->width = XFASTINT (fmt[XBM_WIDTH].value);
          img->height = XFASTINT (fmt[XBM_HEIGHT].value);
          xassert (img->width > 0 && img->height > 0);
+         if (!check_image_size (f, img->width, img->height))
+           {
+             image_error ("Invalid image size (see `max-image-size')",
+                          Qnil, Qnil);
+             return 0;
+           }
        }
 
       /* Get foreground and background colors, maybe allocate colors.  */
@@ -2922,9 +2975,13 @@ xbm_load (struct frame *f, struct image *img)
 #endif
          /* Create the pixmap.  */
 
-         Create_Pixmap_From_Bitmap_Data (f, img, bits,
-                                         foreground, background,
-                                         non_default_colors);
+         if (x_check_image_size (0, img->width, img->height))
+           Create_Pixmap_From_Bitmap_Data (f, img, bits,
+                                           foreground, background,
+                                           non_default_colors);
+         else
+           img->pixmap = NO_PIXMAP;
+
          if (img->pixmap)
            success_p = 1;
          else
@@ -3122,12 +3179,8 @@ xpm_free_color_cache (void)
 static int
 xpm_color_bucket (char *color_name)
 {
-  unsigned h = 0;
-  char *s;
-
-  for (s = color_name; *s; ++s)
-    h = (h << 2) ^ *s;
-  return h %= XPM_COLOR_CACHE_BUCKETS;
+  EMACS_UINT hash = hash_string (color_name, strlen (color_name));
+  return hash % XPM_COLOR_CACHE_BUCKETS;
 }
 
 
@@ -3144,7 +3197,7 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
   if (bucket < 0)
     bucket = xpm_color_bucket (color_name);
 
-  nbytes = sizeof *p + strlen (color_name);
+  nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1;
   p = (struct xpm_cached_color *) xmalloc (nbytes);
   strcpy (p->name, color_name);
   p->color = *color;
@@ -3285,11 +3338,12 @@ xpm_image_p (Lisp_Object object)
 #endif /* HAVE_XPM || HAVE_NS */
 
 #if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
-int
+ptrdiff_t
 x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int id, rc;
+  ptrdiff_t id;
+  int rc;
   XpmAttributes attrs;
   Pixmap bitmap, mask;
 
@@ -3593,25 +3647,14 @@ xpm_load (struct frame *f, struct image *img)
 /* XPM support functions for NS where libxpm is not available.
    Only XPM version 3 (without any extensions) is supported.  */
 
-static int xpm_scan (const unsigned char **, const unsigned char *,
-                     const unsigned char **, int *);
-static Lisp_Object xpm_make_color_table_v
-  (void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
-   Lisp_Object (**) (Lisp_Object, const unsigned char *, int));
 static void xpm_put_color_table_v (Lisp_Object, const unsigned char *,
                                    int, Lisp_Object);
 static Lisp_Object xpm_get_color_table_v (Lisp_Object,
                                           const unsigned char *, int);
-static Lisp_Object xpm_make_color_table_h
-  (void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
-   Lisp_Object (**) (Lisp_Object, const unsigned char *, int));
 static void xpm_put_color_table_h (Lisp_Object, const unsigned char *,
                                    int, Lisp_Object);
 static Lisp_Object xpm_get_color_table_h (Lisp_Object,
                                           const unsigned char *, int);
-static int xpm_str_to_color_key (const char *);
-static int xpm_load_image (struct frame *, struct image *,
-                           const unsigned char *, const unsigned char *);
 
 /* Tokens returned from xpm_scan.  */
 
@@ -3633,7 +3676,7 @@ static int
 xpm_scan (const unsigned char **s,
           const unsigned char *end,
           const unsigned char **beg,
-          int *len)
+          ptrdiff_t *len)
 {
   int c;
 
@@ -3751,7 +3794,7 @@ xpm_put_color_table_h (Lisp_Object color_table,
                        Lisp_Object color)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  unsigned hash_code;
+  EMACS_UINT hash_code;
   Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
 
   hash_lookup (table, chars, &hash_code);
@@ -3803,7 +3846,8 @@ xpm_load_image (struct frame *f,
   unsigned char buffer[BUFSIZ];
   int width, height, x, y;
   int num_colors, chars_per_pixel;
-  int len, LA1;
+  ptrdiff_t len;
+  int LA1;
   void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
   Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
   Lisp_Object frame, color_symbols, color_table;
@@ -3855,6 +3899,18 @@ xpm_load_image (struct frame *f,
       goto failure;
     }
 
+  if (!x_create_x_image_and_pixmap (f, width, height, 0,
+                                   &ximg, &img->pixmap)
+#ifndef HAVE_NS
+      || !x_create_x_image_and_pixmap (f, width, height, 1,
+                                      &mask_img, &img->mask)
+#endif
+      )
+    {
+      image_error ("Image too large", Qnil, Qnil);
+      goto failure;
+    }
+
   expect (',');
 
   XSETFRAME (frame, f);
@@ -3948,18 +4004,6 @@ xpm_load_image (struct frame *f,
       expect (',');
     }
 
-  if (!x_create_x_image_and_pixmap (f, width, height, 0,
-                                   &ximg, &img->pixmap)
-#ifndef HAVE_NS
-      || !x_create_x_image_and_pixmap (f, width, height, 1,
-                                      &mask_img, &img->mask)
-#endif
-      )
-    {
-      image_error ("Out of memory (%s)", img->spec, Qnil);
-      goto error;
-    }
-
   for (y = 0; y < height; y++)
     {
       expect (XPM_TK_STRING);
@@ -4041,7 +4085,7 @@ xpm_load (struct frame *f,
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -5013,9 +5057,7 @@ pbm_scan_number (unsigned char **s, unsigned char *end)
    occurred.  *SIZE is set to the size of the file.  */
 
 static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
+pbm_read_file (Lisp_Object file, int *size)
 {
   FILE *fp = NULL;
   char *buf = NULL;
@@ -5023,6 +5065,7 @@ pbm_read_file (file, size)
 
   if (stat (SDATA (file), &st) == 0
       && (fp = fopen (SDATA (file), "rb")) != NULL
+      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
       && (buf = (char *) xmalloc (st.st_size),
          fread (buf, 1, st.st_size, fp) == st.st_size))
     {
@@ -5057,7 +5100,7 @@ pbm_load (struct frame *f, struct image *img)
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   unsigned char *contents = NULL;
   unsigned char *end, *p;
-  int size;
+  ptrdiff_t size;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
 
@@ -5525,8 +5568,8 @@ my_png_warning (png_struct *png_ptr, const char *msg)
 struct png_memory_storage
 {
   unsigned char *bytes;                /* The data       */
-  size_t len;                  /* How big is it? */
-  int index;                   /* Where are we?  */
+  ptrdiff_t len;               /* How big is it? */
+  ptrdiff_t index;             /* Where are we?  */
 };
 
 
@@ -5570,7 +5613,8 @@ png_load (struct frame *f, struct image *img)
 {
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  int x, y, i;
+  int x, y;
+  ptrdiff_t i;
   XImagePtr ximg, mask_img = NULL;
   png_struct *png_ptr = NULL;
   png_info *info_ptr = NULL, *end_info = NULL;
@@ -5690,11 +5734,19 @@ png_load (struct frame *f, struct image *img)
   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))
+  if (! (width <= INT_MAX && height <= INT_MAX
+        && check_image_size (f, width, height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       goto error;
     }
+
+  /* Create the X image and pixmap now, so that the work below can be
+     omitted if the image is too large for X.  */
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
+                                   &img->pixmap))
+    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))
@@ -5783,7 +5835,10 @@ png_load (struct frame *f, struct image *img)
   row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
-  pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
+      || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
+    memory_full (SIZE_MAX);
+  pixels = (png_byte *) xmalloc (sizeof *pixels * row_bytes * height);
   rows = (png_byte **) xmalloc (height * sizeof *rows);
   for (i = 0; i < height; ++i)
     rows[i] = pixels + i * row_bytes;
@@ -5797,11 +5852,6 @@ png_load (struct frame *f, struct image *img)
       fp = NULL;
     }
 
-  /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
-                                   &img->pixmap))
-    goto error;
-
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -5824,7 +5874,7 @@ png_load (struct frame *f, struct image *img)
 
       for (x = 0; x < width; ++x)
        {
-         unsigned r, g, b;
+         int r, g, b;
 
          r = *p++ << 8;
          g = *p++ << 8;
@@ -6199,7 +6249,7 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
   src = (struct jpeg_stdio_mgr *) cinfo->src;
   if (!src->finished)
     {
-      size_t bytes;
+      ptrdiff_t bytes;
 
       bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
       if (bytes > 0)
@@ -6609,34 +6659,33 @@ init_tiff_functions (Lisp_Object libraries)
 typedef struct
 {
   unsigned char *bytes;
-  size_t len;
-  int index;
+  ptrdiff_t len;
+  ptrdiff_t index;
 }
 tiff_memory_source;
 
-static size_t
+static tsize_t
 tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
 {
   tiff_memory_source *src = (tiff_memory_source *) data;
 
-  if (size > src->len - src->index)
-    return (size_t) -1;
+  size = min (size, src->len - src->index);
   memcpy (buf, src->bytes + src->index, size);
   src->index += size;
   return size;
 }
 
-static size_t
+static tsize_t
 tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size)
 {
-  return (size_t) -1;
+  return -1;
 }
 
 static toff_t
 tiff_seek_in_memory (thandle_t data, toff_t off, int whence)
 {
   tiff_memory_source *src = (tiff_memory_source *) data;
-  int idx;
+  ptrdiff_t idx;
 
   switch (whence)
     {
@@ -6690,17 +6739,29 @@ tiff_size_of_memory (thandle_t data)
 }
 
 
+static void tiff_handler (const char *, const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (3, 0);
+static void
+tiff_handler (const char *log_format, const char *title,
+             const char *format, va_list ap)
+{
+  /* doprnt is not suitable here, as TIFF handlers are called from
+     libtiff and are passed arbitrary printf directives.  Instead, use
+     vsnprintf, taking care to be portable to nonstandard environments
+     where vsnprintf returns -1 on buffer overflow.  Since it's just a
+     log entry, it's OK to truncate it.  */
+  char buf[4000];
+  int len = vsnprintf (buf, sizeof buf, format, ap);
+  add_to_log (log_format, build_string (title),
+             make_string (buf, max (0, min (len, sizeof buf - 1))));
+}
+
 static void tiff_error_handler (const char *, const char *, va_list)
   ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
 tiff_error_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF error: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF error: %s %s", title, format, ap);
 }
 
 
@@ -6709,12 +6770,7 @@ static void tiff_warning_handler (const char *, const char *, va_list)
 static void
 tiff_warning_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF warning: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF warning: %s %s", title, format, ap);
 }
 
 
@@ -6772,8 +6828,8 @@ tiff_load (struct frame *f, struct image *img)
       memsrc.index = 0;
 
       tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
-                               (TIFFReadWriteProc) tiff_read_from_memory,
-                               (TIFFReadWriteProc) tiff_write_from_memory,
+                               tiff_read_from_memory,
+                               tiff_write_from_memory,
                                tiff_seek_in_memory,
                                tiff_close_memory,
                                tiff_size_of_memory,
@@ -6790,8 +6846,9 @@ tiff_load (struct frame *f, struct image *img)
   image = image_spec_value (img->spec, QCindex, NULL);
   if (INTEGERP (image))
     {
-      int ino = XFASTINT (image);
-      if (!fn_TIFFSetDirectory (tiff, ino))
+      EMACS_INT ino = XFASTINT (image);
+      if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
+            && fn_TIFFSetDirectory (tiff, ino)))
        {
          image_error ("Invalid image number `%s' in image `%s'",
                       image, img->spec);
@@ -6812,7 +6869,16 @@ tiff_load (struct frame *f, struct image *img)
       return 0;
     }
 
-  buf = (uint32 *) xmalloc (width * height * sizeof *buf);
+  /* Create the X image and pixmap.  */
+  if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
+        && x_create_x_image_and_pixmap (f, width, height, 0,
+                                        &ximg, &img->pixmap)))
+    {
+      fn_TIFFClose (tiff);
+      return 0;
+    }
+
+  buf = (uint32 *) xmalloc (sizeof *buf * width * height);
 
   rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
 
@@ -6821,9 +6887,9 @@ tiff_load (struct frame *f, struct image *img)
     continue;
 
   if (count > 1)
-    img->data.lisp_val = Fcons (Qcount,
-                               Fcons (make_number (count),
-                                      img->data.lisp_val));
+    img->lisp_data = Fcons (Qcount,
+                           Fcons (make_number (count),
+                                  img->lisp_data));
 
   fn_TIFFClose (tiff);
   if (!rc)
@@ -6833,13 +6899,6 @@ tiff_load (struct frame *f, struct image *img)
       return 0;
     }
 
-  /* Create the X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    {
-      xfree (buf);
-      return 0;
-    }
-
   /* Initialize the color table.  */
   init_color_table ();
 
@@ -6962,8 +7021,7 @@ static struct image_type gif_type =
 static void
 gif_clear_image (struct frame *f, struct image *img)
 {
-  /* IMG->data.ptr_val may contain metadata with extension data.  */
-  img->data.lisp_val = Qnil;
+  img->lisp_data = Qnil;
   x_clear_image (f, img);
 }
 
@@ -7042,8 +7100,8 @@ init_gif_functions (Lisp_Object libraries)
 typedef struct
 {
   unsigned char *bytes;
-  size_t len;
-  int index;
+  ptrdiff_t len;
+  ptrdiff_t index;
 }
 gif_memory_source;
 
@@ -7077,22 +7135,19 @@ static const int interlace_increment[] = {8, 8, 4, 2};
 static int
 gif_load (struct frame *f, struct image *img)
 {
-  Lisp_Object file, specified_file;
-  Lisp_Object specified_data;
-  int rc, width, height, x, y, i;
-  boolean transparent_p = 0;
+  Lisp_Object file;
+  int rc, width, height, x, y, i, j;
   XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
-  Lisp_Object image;
-  int ino, image_height, image_width;
+  int image_height, image_width;
   gif_memory_source memsrc;
-  unsigned char *raster;
-  unsigned int transparency_color_index IF_LINT (= 0);
-
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
+  Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
+  Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
+  unsigned long bgcolor = 0;
+  EMACS_INT idx;
 
   if (NILP (specified_data))
     {
@@ -7143,40 +7198,31 @@ gif_load (struct frame *f, struct image *img)
 
   /* Read entire contents.  */
   rc = fn_DGifSlurp (gif);
-  if (rc == GIF_ERROR)
+  if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
       image_error ("Error reading `%s'", img->spec, Qnil);
       fn_DGifCloseFile (gif);
       return 0;
     }
 
-  image = image_spec_value (img->spec, QCindex, NULL);
-  ino = INTEGERP (image) ? XFASTINT (image) : 0;
-  if (ino >= gif->ImageCount)
-    {
-      image_error ("Invalid image number `%s' in image `%s'",
-                  image, img->spec);
-      fn_DGifCloseFile (gif);
-      return 0;
-    }
-
-  for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++)
-    if ((gif->SavedImages[ino].ExtensionBlocks[i].Function
-        == GIF_LOCAL_DESCRIPTOR_EXTENSION)
-       && gif->SavedImages[ino].ExtensionBlocks[i].ByteCount == 4
-       /* Transparency enabled?  */
-       && gif->SavedImages[ino].ExtensionBlocks[i].Bytes[0] & 1)
+  /* Which sub-image are we to display?  */
+  {
+    Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
+    idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
+    if (idx < 0 || idx >= gif->ImageCount)
       {
-       transparent_p = 1;
-       transparency_color_index
-         = (unsigned char) gif->SavedImages[ino].ExtensionBlocks[i].Bytes[3];
+       image_error ("Invalid image number `%s' in image `%s'",
+                    image_number, img->spec);
+       fn_DGifCloseFile (gif);
+       return 0;
       }
+  }
 
-  img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
-  img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
-  image_height = gif->SavedImages[ino].ImageDesc.Height;
+  img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
+  image_height = gif->SavedImages[idx].ImageDesc.Height;
   img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
-  image_width = gif->SavedImages[ino].ImageDesc.Width;
+  image_width = gif->SavedImages[idx].ImageDesc.Width;
   img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
 
   width = img->width = max (gif->SWidth,
@@ -7200,44 +7246,10 @@ gif_load (struct frame *f, struct image *img)
       return 0;
     }
 
-  /* Allocate colors.  */
-  gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
-  if (!gif_color_map)
-    gif_color_map = gif->SColorMap;
-  init_color_table ();
-  memset (pixel_colors, 0, sizeof pixel_colors);
-
-  if (gif_color_map)
-    for (i = 0; i < gif_color_map->ColorCount; ++i)
-      {
-       if (transparent_p && transparency_color_index == i)
-         {
-           Lisp_Object specified_bg
-             = image_spec_value (img->spec, QCbackground, NULL);
-           pixel_colors[i] = STRINGP (specified_bg)
-             ? x_alloc_image_color (f, img, specified_bg,
-                                    FRAME_BACKGROUND_PIXEL (f))
-             : FRAME_BACKGROUND_PIXEL (f);
-         }
-       else
-         {
-           int r = gif_color_map->Colors[i].Red << 8;
-           int g = gif_color_map->Colors[i].Green << 8;
-           int b = gif_color_map->Colors[i].Blue << 8;
-           pixel_colors[i] = lookup_rgb_color (f, r, g, b);
-         }
-      }
-
-#ifdef COLOR_TABLE_SUPPORT
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
-
-  /* Clear the part of the screen image that are not covered by
-     the image from the GIF file.  Full animated GIF support
-     requires more than can be done here (see the gif89 spec,
-     disposal methods).  Let's simply assume that the part
-     not covered by a sub-image is in the frame's background color.  */
+  /* Clear the part of the screen image not covered by the image.
+     Full animated GIF support requires more here (see the gif89 spec,
+     disposal methods).  Let's simply assume that the part not covered
+     by a sub-image is in the frame's background color.  */
   for (y = 0; y < img->corners[TOP_CORNER]; ++y)
     for (x = 0; x < width; ++x)
       XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
@@ -7254,67 +7266,146 @@ gif_load (struct frame *f, struct image *img)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
 
-  /* Read the GIF image into the X image.  We use a local variable
-     `raster' here because RasterBits below is a char *, and invites
-     problems with bytes >= 0x80.  */
-  raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+  /* Read the GIF image into the X image.   */
 
-  if (gif->SavedImages[ino].ImageDesc.Interlace)
-    {
-      int pass;
-      int row = interlace_start[0];
-
-      pass = 0;
+  /* FIXME: With the current implementation, loading an animated gif
+     is quadratic in the number of animation frames, since each frame
+     is a separate struct image.  We must provide a way for a single
+     gif_load call to construct and save all animation frames.  */
 
-      for (y = 0; y < image_height; y++)
+  init_color_table ();
+  if (STRINGP (specified_bg))
+    bgcolor = x_alloc_image_color (f, img, specified_bg,
+                                  FRAME_BACKGROUND_PIXEL (f));
+  for (j = 0; j <= idx; ++j)
+    {
+      /* We use a local variable `raster' here because RasterBits is a
+        char *, which invites problems with bytes >= 0x80.  */
+      struct SavedImage *subimage = gif->SavedImages + j;
+      unsigned char *raster = (unsigned char *) subimage->RasterBits;
+      int transparency_color_index = -1;
+      int disposal = 0;
+
+      /* Find the Graphic Control Extension block for this sub-image.
+        Extract the disposal method and transparency color.  */
+      for (i = 0; i < subimage->ExtensionBlockCount; i++)
        {
-         if (row >= image_height)
-           {
-             row = interlace_start[++pass];
-             while (row >= image_height)
-               row = interlace_start[++pass];
-           }
+         ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
 
-         for (x = 0; x < image_width; x++)
+         if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
+             && extblock->ByteCount == 4
+             && extblock->Bytes[0] & 1)
            {
-             int c = raster[(y * image_width) + x];
-             XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                        row + img->corners[TOP_CORNER], pixel_colors[c]);
+             /* From gif89a spec: 1 = "keep in place", 2 = "restore
+                to background".  Treat any other value like 2.  */
+             disposal = (extblock->Bytes[0] >> 2) & 7;
+             transparency_color_index = (unsigned char) extblock->Bytes[3];
+             break;
            }
-
-         row += interlace_increment[pass];
        }
-    }
-  else
-    {
-      for (y = 0; y < image_height; ++y)
-       for (x = 0; x < image_width; ++x)
+
+      /* We can't "keep in place" the first subimage.  */
+      if (j == 0)
+       disposal = 2;
+
+      /* Allocate subimage colors.  */
+      memset (pixel_colors, 0, sizeof pixel_colors);
+      gif_color_map = subimage->ImageDesc.ColorMap;
+      if (!gif_color_map)
+       gif_color_map = gif->SColorMap;
+
+      if (gif_color_map)
+       for (i = 0; i < gif_color_map->ColorCount; ++i)
          {
-           int c = raster[y * image_width + x];
-           XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                      y + img->corners[TOP_CORNER], pixel_colors[c]);
+           if (transparency_color_index == i)
+             pixel_colors[i] = STRINGP (specified_bg)
+               ? bgcolor : FRAME_BACKGROUND_PIXEL (f);
+           else
+             {
+               int r = gif_color_map->Colors[i].Red << 8;
+               int g = gif_color_map->Colors[i].Green << 8;
+               int b = gif_color_map->Colors[i].Blue << 8;
+               pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+             }
          }
+
+      /* Apply the pixel values.  */
+      if (gif->SavedImages[j].ImageDesc.Interlace)
+       {
+         int row, pass;
+
+         for (y = 0, row = interlace_start[0], pass = 0;
+              y < image_height;
+              y++, row += interlace_increment[pass])
+           {
+             if (row >= image_height)
+               {
+                 row = interlace_start[++pass];
+                 while (row >= image_height)
+                   row = interlace_start[++pass];
+               }
+
+             for (x = 0; x < image_width; x++)
+               {
+                 int c = raster[y * image_width + x];
+                 if (transparency_color_index != c || disposal != 1)
+                   XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                              row + img->corners[TOP_CORNER], pixel_colors[c]);
+               }
+           }
+       }
+      else
+       {
+         for (y = 0; y < image_height; ++y)
+           for (x = 0; x < image_width; ++x)
+             {
+               int c = raster[y * image_width + x];
+               if (transparency_color_index != c || disposal != 1)
+                 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                            y + img->corners[TOP_CORNER], pixel_colors[c]);
+             }
+       }
     }
 
+#ifdef COLOR_TABLE_SUPPORT
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
   /* Save GIF image extension data for `image-metadata'.
      Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)).  */
-  img->data.lisp_val = Qnil;
-  if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+  img->lisp_data = Qnil;
+  if (gif->SavedImages[idx].ExtensionBlockCount > 0)
     {
-      ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
-      for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+      int delay = 0;
+      ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
+      for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
        /* Append (... FUNCTION "BYTES") */
-       img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
-                                   Fcons (make_number (ext->Function),
-                                          img->data.lisp_val));
-      img->data.lisp_val = Fcons (Qextension_data,
-                                 Fcons (Fnreverse (img->data.lisp_val),
-                                        Qnil));
+       {
+         img->lisp_data
+           = Fcons (make_number (ext->Function),
+                    Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+                           img->lisp_data));
+         if (ext->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION
+             && ext->ByteCount == 4)
+           {
+             delay = ext->Bytes[2] << CHAR_BIT;
+             delay |= ext->Bytes[1];
+           }
+       }
+      img->lisp_data = Fcons (Qextension_data,
+                             Fcons (img->lisp_data, Qnil));
+      if (delay)
+       img->lisp_data
+         = Fcons (Qdelay,
+                  Fcons (make_float (delay / 100.0),
+                         img->lisp_data));
     }
+
   if (gif->ImageCount > 1)
-    img->data.lisp_val = Fcons (Qcount,
-                               Fcons (make_number (gif->ImageCount),
-                                      img->data.lisp_val));
+    img->lisp_data = Fcons (Qcount,
+                           Fcons (make_number (gif->ImageCount),
+                                  img->lisp_data));
 
   fn_DGifCloseFile (gif);
 
@@ -7350,7 +7441,7 @@ gif_load (struct frame *f, struct image *img)
 ***********************************************************************/
 #if defined (HAVE_IMAGEMAGICK)
 
-Lisp_Object Qimagemagick;
+static Lisp_Object Qimagemagick;
 
 static int imagemagick_image_p (Lisp_Object);
 static int imagemagick_load (struct frame *, struct image *);
@@ -7441,6 +7532,14 @@ imagemagick_image_p (Lisp_Object object)
 #define DrawRectangle DrawRectangleGif
 #include <wand/MagickWand.h>
 
+/* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
+   Emacs seems to work fine with the hidden version, so unhide it.  */
+#include <magick/version.h>
+#if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
+extern WandExport void PixelGetMagickColor (const PixelWand *,
+                                           MagickPixelPacket *);
+#endif
+
 /* Helper function for imagemagick_load, which does the actual loading
    given contents and size, apart from frame and image structures,
    passed from imagemagick_load.  Uses librimagemagick to do most of
@@ -7456,16 +7555,14 @@ imagemagick_image_p (Lisp_Object object)
 static int
 imagemagick_load_image (struct frame *f, struct image *img,
                        unsigned char *contents, unsigned int size,
-                       unsigned char *filename)
+                       char *filename)
 {
-  unsigned long width;
-  unsigned long height;
+  size_t width;
+  size_t height;
 
   MagickBooleanType status;
 
   XImagePtr ximg;
-  Lisp_Object specified_bg;
-  XColor background;
   int x;
   int y;
 
@@ -7476,11 +7573,11 @@ imagemagick_load_image (struct frame *f, struct image *img,
   MagickPixelPacket  pixel;
   Lisp_Object image;
   Lisp_Object value;
-  Lisp_Object crop, geometry;
-  long ino;
+  Lisp_Object crop;
+  EMACS_INT ino;
   int desired_width, desired_height;
   double rotation;
-  int imagemagick_rendermethod;
+  EMACS_INT imagemagick_rendermethod;
   int pixelwidth;
   ImageInfo  *image_info;
   ExceptionInfo *exception;
@@ -7507,7 +7604,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
       status = MagickPingImageBlob (ping_wand, contents, size);
     }
 
-  if (ino >= MagickGetNumberImages (ping_wand))
+  if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand)))
     {
       image_error ("Invalid image number `%s' in image `%s'",
                   image, img->spec);
@@ -7516,10 +7613,10 @@ imagemagick_load_image (struct frame *f, struct image *img,
     }
 
   if (MagickGetNumberImages(ping_wand) > 1)
-    img->data.lisp_val =
+    img->lisp_data =
       Fcons (Qcount,
              Fcons (make_number (MagickGetNumberImages (ping_wand)),
-                    img->data.lisp_val));
+                    img->lisp_data));
 
   DestroyMagickWand (ping_wand);
 
@@ -7537,23 +7634,18 @@ imagemagick_load_image (struct frame *f, struct image *img,
       im_image = ReadImage (image_info, exception);
       DestroyExceptionInfo (exception);
 
-      if (im_image != NULL)
-       {
-         image_wand = NewMagickWandFromImage (im_image);
-          DestroyImage(im_image);
-         status = MagickTrue;
-       }
-      else
-       status = MagickFalse;
+      if (im_image == NULL)
+       goto imagemagick_no_wand;
+      image_wand = NewMagickWandFromImage (im_image);
+      DestroyImage(im_image);
     }
   else
     {
       image_wand = NewMagickWand ();
-      status = MagickReadImageBlob (image_wand, contents, size);
+      if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
+       goto imagemagick_error;
     }
 
-  if (status == MagickFalse) goto imagemagick_error;
-
   /* If width and/or height is set in the display spec assume we want
      to scale to those values.  If either h or w is unspecified, the
      unspecified should be calculated from the specified to preserve
@@ -7587,28 +7679,28 @@ imagemagick_load_image (struct frame *f, struct image *img,
      efficient.  */
   crop = image_spec_value (img->spec, QCcrop, NULL);
 
-  if (CONSP (crop) && INTEGERP (XCAR (crop)))
+  if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
     {
       /* After some testing, it seems MagickCropImage is the fastest crop
          function in ImageMagick.  This crop function seems to do less copying
          than the alternatives, but it still reads the entire image into memory
-         before croping, which is aparently difficult to avoid when using
+         before cropping, which is apparently difficult to avoid when using
          imagemagick.  */
-      int w, h, x, y;
-      w = XFASTINT (XCAR (crop));
+      size_t crop_width = XINT (XCAR (crop));
       crop = XCDR (crop);
-      if (CONSP (crop) && INTEGERP (XCAR (crop)))
+      if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
        {
-         h = XFASTINT (XCAR (crop));
+         size_t crop_height = XINT (XCAR (crop));
          crop = XCDR (crop);
-         if (CONSP (crop) && INTEGERP (XCAR (crop)))
+         if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
            {
-             x = XFASTINT (XCAR (crop));
+             ssize_t crop_x = XINT (XCAR (crop));
              crop = XCDR (crop);
-             if (CONSP (crop) && INTEGERP (XCAR (crop)))
+             if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
                {
-                 y = XFASTINT (XCAR (crop));
-                 MagickCropImage (image_wand, w, h, x, y);
+                 ssize_t crop_y = XINT (XCAR (crop));
+                 MagickCropImage (image_wand, crop_width, crop_height,
+                                  crop_x, crop_y);
                }
            }
        }
@@ -7642,7 +7734,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
 
-  if (! check_image_size (f, width, height))
+  if (! (width <= INT_MAX && height <= INT_MAX
+        && check_image_size (f, width, height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       goto imagemagick_error;
@@ -7653,9 +7746,11 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   init_color_table ();
   imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type)
-                              ? XFASTINT (Vimagemagick_render_type) : 0);
+                              ? XINT (Vimagemagick_render_type) : 0);
   if (imagemagick_rendermethod == 0)
     {
+      size_t image_height;
+
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                         &ximg, &img->pixmap))
@@ -7684,7 +7779,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
           goto imagemagick_error;
         }
 
-      for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++)
+      image_height = MagickGetImageHeight (image_wand);
+      for (y = 0; y < image_height; y++)
         {
           pixels = PixelGetNextIteratorRow (iterator, &width);
           if (pixels == (PixelWand **) NULL)
@@ -7708,7 +7804,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
          method is also well tested. Some aspects of this method are
          ad-hoc and needs to be more researched. */
       int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
-      char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
+      const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
                                         &ximg, &img->pixmap))
@@ -7781,6 +7877,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
  imagemagick_error:
   DestroyMagickWand (image_wand);
+ imagemagick_no_wand:
   MagickWandTerminus ();
   /* TODO more cleanup.  */
   image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
@@ -7810,7 +7907,7 @@ imagemagick_load (struct frame *f, struct image *img)
          image_error ("Cannot find image file `%s'", file_name, Qnil);
          return 0;
        }
-      success_p = imagemagick_load_image (f, img, 0, 0, SDATA (file));
+      success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
     }
   /* Else its not a file, its a lisp object.  Load the image from a
      lisp object rather than a file.  */
@@ -7842,10 +7939,10 @@ recognize as images, such as C.  See `imagemagick-types-inhibit'.  */)
   (void)
 {
   Lisp_Object typelist = Qnil;
-  unsigned long numf = 0;
+  size_t numf = 0;
   ExceptionInfo ex;
   char **imtypes = GetMagickList ("*", &numf, &ex);
-  int i;
+  size_t i;
   Lisp_Object Qimagemagicktype;
   for (i = 0; i < numf; i++)
     {
@@ -7871,11 +7968,11 @@ static int svg_image_p (Lisp_Object object);
 static int svg_load (struct frame *f, struct image *img);
 
 static int svg_load_image (struct frame *, struct image *,
-                           unsigned char *, unsigned int);
+                           unsigned char *, ptrdiff_t);
 
 /* The symbol `svg' identifying images of this type. */
 
-Lisp_Object Qsvg;
+static Lisp_Object Qsvg;
 
 /* Indices of image specification fields in svg_format, below.  */
 
@@ -7958,7 +8055,6 @@ DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
 DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
 DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
-DEF_IMGLIB_FN (void, rsvg_handle_free);
 
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
 DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
@@ -7991,7 +8087,6 @@ init_svg_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, rsvg_handle_write);
   LOAD_IMGLIB_FN (library, rsvg_handle_close);
   LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
-  LOAD_IMGLIB_FN (library, rsvg_handle_free);
 
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
@@ -8017,7 +8112,6 @@ init_svg_functions (Lisp_Object libraries)
 #define fn_rsvg_handle_write           rsvg_handle_write
 #define fn_rsvg_handle_close           rsvg_handle_close
 #define fn_rsvg_handle_get_pixbuf      rsvg_handle_get_pixbuf
-#define fn_rsvg_handle_free            rsvg_handle_free
 
 #define fn_gdk_pixbuf_get_width                  gdk_pixbuf_get_width
 #define fn_gdk_pixbuf_get_height         gdk_pixbuf_get_height
@@ -8049,7 +8143,7 @@ svg_load (struct frame *f, struct image *img)
     {
       Lisp_Object file;
       unsigned char *contents;
-      int size;
+      ptrdiff_t size;
 
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
@@ -8059,7 +8153,7 @@ svg_load (struct frame *f, struct image *img)
        }
 
       /* Read the entire file into memory.  */
-      contents = slurp_file (SDATA (file), &size);
+      contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error loading SVG image `%s'", img->spec, Qnil);
@@ -8098,11 +8192,11 @@ static int
 svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  */
                struct image *img,       /* Pointer to emacs image structure.  */
                unsigned char *contents, /* String containing the SVG XML data to be parsed.  */
-               unsigned int size)       /* Size of data in bytes.  */
+               ptrdiff_t size)          /* Size of data in bytes.  */
 {
   RsvgHandle *rsvg_handle;
   RsvgDimensionData dimension_data;
-  GError *error = NULL;
+  GError *err = NULL;
   GdkPixbuf *pixbuf;
   int width;
   int height;
@@ -8121,13 +8215,13 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   rsvg_handle = fn_rsvg_handle_new ();
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
-  fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+  if (err) goto rsvg_error;
 
   /* The parsing is complete, rsvg_handle is ready to used, close it
      for further writes.  */
-  fn_rsvg_handle_close (rsvg_handle, &error);
-  if (error) goto rsvg_error;
+  fn_rsvg_handle_close (rsvg_handle, &err);
+  if (err) goto rsvg_error;
 
   fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
@@ -8167,7 +8261,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
      color.  */
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   if (!STRINGP (specified_bg)
-      || !x_defined_color (f, SDATA (specified_bg), &background, 0))
+      || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
     {
 #ifndef HAVE_NS
       background.pixel = FRAME_BACKGROUND_PIXEL (f);
@@ -8192,10 +8286,10 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
     {
       for (x = 0; x < width; ++x)
        {
-         unsigned red;
-         unsigned green;
-         unsigned blue;
-         unsigned opacity;
+         int red;
+         int green;
+         int blue;
+         int opacity;
 
          red     = *pixels++;
          green   = *pixels++;
@@ -8242,7 +8336,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
-  fn_g_error_free (error);
+  fn_g_error_free (err);
   return 0;
 }
 
@@ -8326,8 +8420,6 @@ static struct image_type gs_type =
 static void
 gs_clear_image (struct frame *f, struct image *img)
 {
-  /* IMG->data.ptr_val may contain a recorded colormap.  */
-  xfree (img->data.ptr_val);
   x_clear_image (f, img);
 }
 
@@ -8378,7 +8470,8 @@ gs_image_p (Lisp_Object object)
 static int
 gs_load (struct frame *f, struct image *img)
 {
-  char buffer[100];
+  uprintmax_t printnum1, printnum2;
+  char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
   Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
   Lisp_Object frame;
   double in_width, in_height;
@@ -8390,26 +8483,32 @@ gs_load (struct frame *f, struct image *img)
      info.  */
   pt_width = image_spec_value (img->spec, QCpt_width, NULL);
   in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
-  img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
+  in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
   pt_height = image_spec_value (img->spec, QCpt_height, NULL);
   in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
-  img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
+  in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
 
-  if (!check_image_size (f, img->width, img->height))
+  if (! (in_width <= INT_MAX && in_height <= INT_MAX
+        && check_image_size (f, in_width, in_height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       return 0;
     }
+  img->width = in_width;
+  img->height = in_height;
 
   /* Create the pixmap.  */
   xassert (img->pixmap == NO_PIXMAP);
 
-  /* Only W32 version did BLOCK_INPUT here.  ++kfs */
-  BLOCK_INPUT;
-  img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                              img->width, img->height,
-                              DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
-  UNBLOCK_INPUT;
+  if (x_check_image_size (0, img->width, img->height))
+    {
+      /* Only W32 version did BLOCK_INPUT here.  ++kfs */
+      BLOCK_INPUT;
+      img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                                  img->width, img->height,
+                                  DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+      UNBLOCK_INPUT;
+    }
 
   if (!img->pixmap)
     {
@@ -8421,14 +8520,14 @@ gs_load (struct frame *f, struct image *img)
      if successful.  We do not record_unwind_protect here because
      other places in redisplay like calling window scroll functions
      don't either.  Let the Lisp loader use `unwind-protect' instead.  */
-  sprintf (buffer, "%lu %lu",
-          (unsigned long) FRAME_X_WINDOW (f),
-          (unsigned long) img->pixmap);
+  printnum1 = FRAME_X_WINDOW (f);
+  printnum2 = img->pixmap;
+  sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
   window_and_pixmap_id = build_string (buffer);
 
-  sprintf (buffer, "%lu %lu",
-          FRAME_FOREGROUND_PIXEL (f),
-          FRAME_BACKGROUND_PIXEL (f));
+  printnum1 = FRAME_FOREGROUND_PIXEL (f);
+  printnum2 = FRAME_BACKGROUND_PIXEL (f);
+  sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
   pixel_colors = build_string (buffer);
 
   XSETFRAME (frame, f);
@@ -8436,12 +8535,12 @@ gs_load (struct frame *f, struct image *img)
   if (NILP (loader))
     loader = intern ("gs-load-image");
 
-  img->data.lisp_val = call6 (loader, frame, img->spec,
-                             make_number (img->width),
-                             make_number (img->height),
-                             window_and_pixmap_id,
-                             pixel_colors);
-  return PROCESSP (img->data.lisp_val);
+  img->lisp_data = call6 (loader, frame, img->spec,
+                         make_number (img->width),
+                         make_number (img->height),
+                         window_and_pixmap_id,
+                         pixel_colors);
+  return PROCESSP (img->lisp_data);
 }
 
 
@@ -8453,7 +8552,8 @@ void
 x_kill_gs_process (Pixmap pixmap, struct frame *f)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int class, i;
+  int class;
+  ptrdiff_t i;
   struct image *img;
 
   /* Find the image containing PIXMAP.  */
@@ -8469,9 +8569,9 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
   img = c->images[i];
-  xassert (PROCESSP (img->data.lisp_val));
-  Fkill_process (img->data.lisp_val, Qnil);
-  img->data.lisp_val = Qnil;
+  xassert (PROCESSP (img->lisp_data));
+  Fkill_process (img->lisp_data, Qnil);
+  img->lisp_data = Qnil;
 
 #if defined (HAVE_X_WINDOWS)
 
@@ -8557,7 +8657,7 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
   (Lisp_Object spec)
 {
-  int id = -1;
+  ptrdiff_t id = -1;
 
   if (valid_image_p (spec))
     id = lookup_image (SELECTED_FRAME (), spec);
@@ -8677,75 +8777,49 @@ as a ratio to the frame height and width.  If the value is
 non-numeric, there is no explicit limit on the size of images.  */);
   Vmax_image_size = make_float (MAX_IMAGE_SIZE);
 
-  Qpbm = intern_c_string ("pbm");
-  staticpro (&Qpbm);
+  DEFSYM (Qpbm, "pbm");
   ADD_IMAGE_TYPE (Qpbm);
 
-  Qxbm = intern_c_string ("xbm");
-  staticpro (&Qxbm);
+  DEFSYM (Qxbm, "xbm");
   ADD_IMAGE_TYPE (Qxbm);
 
   define_image_type (&xbm_type, 1);
   define_image_type (&pbm_type, 1);
 
-  Qcount = intern_c_string ("count");
-  staticpro (&Qcount);
-  Qextension_data = intern_c_string ("extension-data");
-  staticpro (&Qextension_data);
-
-  QCascent = intern_c_string (":ascent");
-  staticpro (&QCascent);
-  QCmargin = intern_c_string (":margin");
-  staticpro (&QCmargin);
-  QCrelief = intern_c_string (":relief");
-  staticpro (&QCrelief);
-  QCconversion = intern_c_string (":conversion");
-  staticpro (&QCconversion);
-  QCcolor_symbols = intern_c_string (":color-symbols");
-  staticpro (&QCcolor_symbols);
-  QCheuristic_mask = intern_c_string (":heuristic-mask");
-  staticpro (&QCheuristic_mask);
-  QCindex = intern_c_string (":index");
-  staticpro (&QCindex);
-  QCgeometry = intern_c_string (":geometry");
-  staticpro (&QCgeometry);
-  QCcrop = intern_c_string (":crop");
-  staticpro (&QCcrop);
-  QCrotation = intern_c_string (":rotation");
-  staticpro (&QCrotation);
-  QCmatrix = intern_c_string (":matrix");
-  staticpro (&QCmatrix);
-  QCcolor_adjustment = intern_c_string (":color-adjustment");
-  staticpro (&QCcolor_adjustment);
-  QCmask = intern_c_string (":mask");
-  staticpro (&QCmask);
-
-  Qlaplace = intern_c_string ("laplace");
-  staticpro (&Qlaplace);
-  Qemboss = intern_c_string ("emboss");
-  staticpro (&Qemboss);
-  Qedge_detection = intern_c_string ("edge-detection");
-  staticpro (&Qedge_detection);
-  Qheuristic = intern_c_string ("heuristic");
-  staticpro (&Qheuristic);
-
-  Qpostscript = intern_c_string ("postscript");
-  staticpro (&Qpostscript);
+  DEFSYM (Qcount, "count");
+  DEFSYM (Qextension_data, "extension-data");
+  DEFSYM (Qdelay, "delay");
+
+  DEFSYM (QCascent, ":ascent");
+  DEFSYM (QCmargin, ":margin");
+  DEFSYM (QCrelief, ":relief");
+  DEFSYM (QCconversion, ":conversion");
+  DEFSYM (QCcolor_symbols, ":color-symbols");
+  DEFSYM (QCheuristic_mask, ":heuristic-mask");
+  DEFSYM (QCindex, ":index");
+  DEFSYM (QCgeometry, ":geometry");
+  DEFSYM (QCcrop, ":crop");
+  DEFSYM (QCrotation, ":rotation");
+  DEFSYM (QCmatrix, ":matrix");
+  DEFSYM (QCcolor_adjustment, ":color-adjustment");
+  DEFSYM (QCmask, ":mask");
+
+  DEFSYM (Qlaplace, "laplace");
+  DEFSYM (Qemboss, "emboss");
+  DEFSYM (Qedge_detection, "edge-detection");
+  DEFSYM (Qheuristic, "heuristic");
+
+  DEFSYM (Qpostscript, "postscript");
 #ifdef HAVE_GHOSTSCRIPT
   ADD_IMAGE_TYPE (Qpostscript);
-  QCloader = intern_c_string (":loader");
-  staticpro (&QCloader);
-  QCbounding_box = intern_c_string (":bounding-box");
-  staticpro (&QCbounding_box);
-  QCpt_width = intern_c_string (":pt-width");
-  staticpro (&QCpt_width);
-  QCpt_height = intern_c_string (":pt-height");
-  staticpro (&QCpt_height);
+  DEFSYM (QCloader, ":loader");
+  DEFSYM (QCbounding_box, ":bounding-box");
+  DEFSYM (QCpt_width, ":pt-width");
+  DEFSYM (QCpt_height, ":pt-height");
 #endif /* HAVE_GHOSTSCRIPT */
 
 #ifdef HAVE_NTGUI
-  Qlibpng_version = intern_c_string ("libpng-version");
-  staticpro (&Qlibpng_version);
+  DEFSYM (Qlibpng_version, "libpng-version");
   Fset (Qlibpng_version,
 #if HAVE_PNG
        make_number (PNG_LIBPNG_VER)
@@ -8756,53 +8830,43 @@ non-numeric, there is no explicit limit on the size of images.  */);
 #endif
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
-  Qxpm = intern_c_string ("xpm");
-  staticpro (&Qxpm);
+  DEFSYM (Qxpm, "xpm");
   ADD_IMAGE_TYPE (Qxpm);
 #endif
 
 #if defined (HAVE_JPEG) || defined (HAVE_NS)
-  Qjpeg = intern_c_string ("jpeg");
-  staticpro (&Qjpeg);
+  DEFSYM (Qjpeg, "jpeg");
   ADD_IMAGE_TYPE (Qjpeg);
 #endif
 
 #if defined (HAVE_TIFF) || defined (HAVE_NS)
-  Qtiff = intern_c_string ("tiff");
-  staticpro (&Qtiff);
+  DEFSYM (Qtiff, "tiff");
   ADD_IMAGE_TYPE (Qtiff);
 #endif
 
 #if defined (HAVE_GIF) || defined (HAVE_NS)
-  Qgif = intern_c_string ("gif");
-  staticpro (&Qgif);
+  DEFSYM (Qgif, "gif");
   ADD_IMAGE_TYPE (Qgif);
 #endif
 
 #if defined (HAVE_PNG) || defined (HAVE_NS)
-  Qpng = intern_c_string ("png");
-  staticpro (&Qpng);
+  DEFSYM (Qpng, "png");
   ADD_IMAGE_TYPE (Qpng);
 #endif
 
 #if defined (HAVE_IMAGEMAGICK)
-  Qimagemagick = intern_c_string ("imagemagick");
-  staticpro (&Qimagemagick);
+  DEFSYM (Qimagemagick, "imagemagick");
   ADD_IMAGE_TYPE (Qimagemagick);
 #endif
 
 #if defined (HAVE_RSVG)
-  Qsvg = intern_c_string ("svg");
-  staticpro (&Qsvg);
+  DEFSYM (Qsvg, "svg");
   ADD_IMAGE_TYPE (Qsvg);
 #ifdef HAVE_NTGUI
   /* Other libraries used directly by svg code.  */
-  Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
-  staticpro (&Qgdk_pixbuf);
-  Qglib = intern_c_string ("glib");
-  staticpro (&Qglib);
-  Qgobject = intern_c_string ("gobject");
-  staticpro (&Qgobject);
+  DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
+  DEFSYM (Qglib, "glib");
+  DEFSYM (Qgobject, "gobject");
 #endif /* HAVE_NTGUI  */
 #endif /* HAVE_RSVG  */