aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-07-13 23:20:53 -0700
committerPaul Eggert2011-07-13 23:20:53 -0700
commitca4aa9359160557f8103639fc3c0ccb16c6ba8d2 (patch)
tree5b939640079b6fe042c9509fb0d03bb72495aa2a /src
parent5f8f9cc26998b1b74d9ac5c8b68000d53aae31cc (diff)
downloademacs-ca4aa9359160557f8103639fc3c0ccb16c6ba8d2.tar.gz
emacs-ca4aa9359160557f8103639fc3c0ccb16c6ba8d2.zip
* image.c: Improve checking for integer overflow.
(check_image_size): Assume that f is nonnull, since it is always nonnull in practice. This is one less thing to worry about when checking for integer overflow later. (x_check_image_size): New function, which checks for integer overflow issues inside X. (x_create_x_image_and_pixmap, xbm_read_bitmap_data): Use it. This removes the need for a memory_full check. (xbm_image_p): Rewrite to avoid integer multiplication overflow. (Create_Pixmap_From_Bitmap_Data, xbm_load): Use x_check_image_size. (xbm_read_bitmap_data): Change locals back to 'int', since their values must fit in 'int'. (xpm_load_image, png_load, tiff_load): Invoke x_create_x_image_and_pixmap earlier, to avoid much needless work if the image is too large. (tiff_load): Treat overly large images as if x_create_x_image_and_pixmap failed, not as malloc failures. (gs_load): Use x_check_image_size.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog21
-rw-r--r--src/image.c160
2 files changed, 129 insertions, 52 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c986030fcf8..e07b906b56d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,24 @@
12011-07-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 * image.c: Improve checking for integer overflow.
4 (check_image_size): Assume that f is nonnull, since
5 it is always nonnull in practice. This is one less thing to
6 worry about when checking for integer overflow later.
7 (x_check_image_size): New function, which checks for integer
8 overflow issues inside X.
9 (x_create_x_image_and_pixmap, xbm_read_bitmap_data): Use it.
10 This removes the need for a memory_full check.
11 (xbm_image_p): Rewrite to avoid integer multiplication overflow.
12 (Create_Pixmap_From_Bitmap_Data, xbm_load): Use x_check_image_size.
13 (xbm_read_bitmap_data): Change locals back to 'int', since
14 their values must fit in 'int'.
15 (xpm_load_image, png_load, tiff_load):
16 Invoke x_create_x_image_and_pixmap earlier,
17 to avoid much needless work if the image is too large.
18 (tiff_load): Treat overly large images as if
19 x_create_x_image_and_pixmap failed, not as malloc failures.
20 (gs_load): Use x_check_image_size.
21
12011-07-13 Paul Eggert <eggert@cs.ucla.edu> 222011-07-13 Paul Eggert <eggert@cs.ucla.edu>
2 23
3 * gtkutil.c: Omit integer casts. 24 * gtkutil.c: Omit integer casts.
diff --git a/src/image.c b/src/image.c
index 1b6e67b4404..7a5ac40b3d2 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1053,13 +1053,9 @@ check_image_size (struct frame *f, int width, int height)
1053 && height <= XINT (Vmax_image_size)); 1053 && height <= XINT (Vmax_image_size));
1054 else if (FLOATP (Vmax_image_size)) 1054 else if (FLOATP (Vmax_image_size))
1055 { 1055 {
1056 if (f != NULL) 1056 xassert (f);
1057 { 1057 w = FRAME_PIXEL_WIDTH (f);
1058 w = FRAME_PIXEL_WIDTH (f); 1058 h = FRAME_PIXEL_HEIGHT (f);
1059 h = FRAME_PIXEL_HEIGHT (f);
1060 }
1061 else
1062 w = h = 1024; /* Arbitrary size for unknown frame. */
1063 return (width <= XFLOAT_DATA (Vmax_image_size) * w 1059 return (width <= XFLOAT_DATA (Vmax_image_size) * w
1064 && height <= XFLOAT_DATA (Vmax_image_size) * h); 1060 && height <= XFLOAT_DATA (Vmax_image_size) * h);
1065 } 1061 }
@@ -1910,6 +1906,38 @@ static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
1910static void x_destroy_x_image (XImagePtr); 1906static void x_destroy_x_image (XImagePtr);
1911static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int); 1907static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
1912 1908
1909/* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break X.
1910 WIDTH and HEIGHT must both be positive.
1911 If XIMG is null, assume it is a bitmap. */
1912static int
1913x_check_image_size (XImagePtr ximg, int width, int height)
1914{
1915 /* Respect Xlib's limits: it cannot deal with images that have more
1916 than INT_MAX (and/or UINT_MAX) bytes. And respect Emacs's limits
1917 of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object. For now,
1918 assume all windowing systems have the same limits that X does. */
1919 enum
1920 {
1921 XLIB_BYTES_MAX = min (INT_MAX, UINT_MAX),
1922 X_IMAGE_BYTES_MAX = min (XLIB_BYTES_MAX, min (PTRDIFF_MAX, SIZE_MAX))
1923 };
1924
1925 int bitmap_pad, depth, bytes_per_line;
1926 if (ximg)
1927 {
1928 bitmap_pad = ximg->bitmap_pad;
1929 depth = ximg->depth;
1930 bytes_per_line = ximg->bytes_per_line;
1931 }
1932 else
1933 {
1934 bitmap_pad = 8;
1935 depth = 1;
1936 bytes_per_line = (width >> 3) + ((width & 7) != 0);
1937 }
1938 return (width <= (INT_MAX - (bitmap_pad - 1)) / depth
1939 && height <= X_IMAGE_BYTES_MAX / bytes_per_line);
1940}
1913 1941
1914/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on 1942/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1915 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created. 1943 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
@@ -1942,9 +1970,16 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
1942 return 0; 1970 return 0;
1943 } 1971 }
1944 1972
1973 if (! x_check_image_size (*ximg, width, height))
1974 {
1975 x_destroy_x_image (*ximg);
1976 *ximg = NULL;
1977 image_error ("Image too large (%dx%d)",
1978 make_number (width), make_number (height));
1979 return 0;
1980 }
1981
1945 /* Allocate image raster. */ 1982 /* Allocate image raster. */
1946 if (min (PTRDIFF_MAX, SIZE_MAX) / height < (*ximg)->bytes_per_line)
1947 memory_full (SIZE_MAX);
1948 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height); 1983 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
1949 1984
1950 /* Allocate a pixmap of the same size. */ 1985 /* Allocate a pixmap of the same size. */
@@ -2361,7 +2396,7 @@ xbm_image_p (Lisp_Object object)
2361 } 2396 }
2362 else if (BOOL_VECTOR_P (data)) 2397 else if (BOOL_VECTOR_P (data))
2363 { 2398 {
2364 if (XBOOL_VECTOR (data)->size < width * height) 2399 if (XBOOL_VECTOR (data)->size / height < width)
2365 return 0; 2400 return 0;
2366 } 2401 }
2367 else 2402 else
@@ -2557,13 +2592,15 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
2557 img->pixmap = ns_image_from_XBM (data, img->width, img->height); 2592 img->pixmap = ns_image_from_XBM (data, img->width, img->height);
2558 2593
2559#else 2594#else
2560 img->pixmap 2595 img->pixmap =
2561 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), 2596 (x_check_image_size (0, img->width, img->height)
2597 ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2562 FRAME_X_WINDOW (f), 2598 FRAME_X_WINDOW (f),
2563 data, 2599 data,
2564 img->width, img->height, 2600 img->width, img->height,
2565 fg, bg, 2601 fg, bg,
2566 DefaultDepthOfScreen (FRAME_X_SCREEN (f))); 2602 DefaultDepthOfScreen (FRAME_X_SCREEN (f)))
2603 : NO_PIXMAP);
2567#endif /* !HAVE_NTGUI && !HAVE_NS */ 2604#endif /* !HAVE_NTGUI && !HAVE_NS */
2568} 2605}
2569 2606
@@ -2587,8 +2624,7 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
2587 char buffer[BUFSIZ]; 2624 char buffer[BUFSIZ];
2588 int padding_p = 0; 2625 int padding_p = 0;
2589 int v10 = 0; 2626 int v10 = 0;
2590 int bytes_per_line; 2627 int bytes_per_line, i, nbytes;
2591 ptrdiff_t i, nbytes;
2592 char *p; 2628 char *p;
2593 int value; 2629 int value;
2594 int LA1; 2630 int LA1;
@@ -2671,9 +2707,14 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
2671 expect ('='); 2707 expect ('=');
2672 expect ('{'); 2708 expect ('{');
2673 2709
2710 if (! x_check_image_size (0, *width, *height))
2711 {
2712 if (!inhibit_image_error)
2713 image_error ("Image too large (%dx%d)",
2714 make_number (*width), make_number (*height));
2715 goto failure;
2716 }
2674 bytes_per_line = (*width + 7) / 8 + padding_p; 2717 bytes_per_line = (*width + 7) / 8 + padding_p;
2675 if (min (PTRDIFF_MAX - 1, SIZE_MAX) / *height < bytes_per_line)
2676 memory_full (SIZE_MAX);
2677 nbytes = bytes_per_line * *height; 2718 nbytes = bytes_per_line * *height;
2678 p = *data = (char *) xmalloc (nbytes); 2719 p = *data = (char *) xmalloc (nbytes);
2679 2720
@@ -2863,6 +2904,12 @@ xbm_load (struct frame *f, struct image *img)
2863 img->width = XFASTINT (fmt[XBM_WIDTH].value); 2904 img->width = XFASTINT (fmt[XBM_WIDTH].value);
2864 img->height = XFASTINT (fmt[XBM_HEIGHT].value); 2905 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
2865 xassert (img->width > 0 && img->height > 0); 2906 xassert (img->width > 0 && img->height > 0);
2907 if (!check_image_size (f, img->width, img->height))
2908 {
2909 image_error ("Invalid image size (see `max-image-size')",
2910 Qnil, Qnil);
2911 return 0;
2912 }
2866 } 2913 }
2867 2914
2868 /* Get foreground and background colors, maybe allocate colors. */ 2915 /* Get foreground and background colors, maybe allocate colors. */
@@ -2924,9 +2971,13 @@ xbm_load (struct frame *f, struct image *img)
2924#endif 2971#endif
2925 /* Create the pixmap. */ 2972 /* Create the pixmap. */
2926 2973
2927 Create_Pixmap_From_Bitmap_Data (f, img, bits, 2974 if (x_check_image_size (0, img->width, img->height))
2928 foreground, background, 2975 Create_Pixmap_From_Bitmap_Data (f, img, bits,
2929 non_default_colors); 2976 foreground, background,
2977 non_default_colors);
2978 else
2979 img->pixmap = NO_PIXMAP;
2980
2930 if (img->pixmap) 2981 if (img->pixmap)
2931 success_p = 1; 2982 success_p = 1;
2932 else 2983 else
@@ -3844,6 +3895,18 @@ xpm_load_image (struct frame *f,
3844 goto failure; 3895 goto failure;
3845 } 3896 }
3846 3897
3898 if (!x_create_x_image_and_pixmap (f, width, height, 0,
3899 &ximg, &img->pixmap)
3900#ifndef HAVE_NS
3901 || !x_create_x_image_and_pixmap (f, width, height, 1,
3902 &mask_img, &img->mask)
3903#endif
3904 )
3905 {
3906 image_error ("Image too large", Qnil, Qnil);
3907 goto failure;
3908 }
3909
3847 expect (','); 3910 expect (',');
3848 3911
3849 XSETFRAME (frame, f); 3912 XSETFRAME (frame, f);
@@ -3937,18 +4000,6 @@ xpm_load_image (struct frame *f,
3937 expect (','); 4000 expect (',');
3938 } 4001 }
3939 4002
3940 if (!x_create_x_image_and_pixmap (f, width, height, 0,
3941 &ximg, &img->pixmap)
3942#ifndef HAVE_NS
3943 || !x_create_x_image_and_pixmap (f, width, height, 1,
3944 &mask_img, &img->mask)
3945#endif
3946 )
3947 {
3948 image_error ("Out of memory (%s)", img->spec, Qnil);
3949 goto error;
3950 }
3951
3952 for (y = 0; y < height; y++) 4003 for (y = 0; y < height; y++)
3953 { 4004 {
3954 expect (XPM_TK_STRING); 4005 expect (XPM_TK_STRING);
@@ -5685,6 +5736,13 @@ png_load (struct frame *f, struct image *img)
5685 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); 5736 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5686 goto error; 5737 goto error;
5687 } 5738 }
5739
5740 /* Create the X image and pixmap now, so that the work below can be
5741 omitted if the image is too large for X. */
5742 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5743 &img->pixmap))
5744 goto error;
5745
5688 /* If image contains simply transparency data, we prefer to 5746 /* If image contains simply transparency data, we prefer to
5689 construct a clipping mask. */ 5747 construct a clipping mask. */
5690 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) 5748 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
@@ -5790,11 +5848,6 @@ png_load (struct frame *f, struct image *img)
5790 fp = NULL; 5848 fp = NULL;
5791 } 5849 }
5792 5850
5793 /* Create the X image and pixmap. */
5794 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5795 &img->pixmap))
5796 goto error;
5797
5798 /* Create an image and pixmap serving as mask if the PNG image 5851 /* Create an image and pixmap serving as mask if the PNG image
5799 contains an alpha channel. */ 5852 contains an alpha channel. */
5800 if (channels == 4 5853 if (channels == 4
@@ -6804,8 +6857,15 @@ tiff_load (struct frame *f, struct image *img)
6804 return 0; 6857 return 0;
6805 } 6858 }
6806 6859
6807 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width < height) 6860 /* Create the X image and pixmap. */
6808 memory_full (SIZE_MAX); 6861 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
6862 && x_create_x_image_and_pixmap (f, width, height, 0,
6863 &ximg, &img->pixmap)))
6864 {
6865 fn_TIFFClose (tiff);
6866 return 0;
6867 }
6868
6809 buf = (uint32 *) xmalloc (sizeof *buf * width * height); 6869 buf = (uint32 *) xmalloc (sizeof *buf * width * height);
6810 6870
6811 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); 6871 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
@@ -6827,13 +6887,6 @@ tiff_load (struct frame *f, struct image *img)
6827 return 0; 6887 return 0;
6828 } 6888 }
6829 6889
6830 /* Create the X image and pixmap. */
6831 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6832 {
6833 xfree (buf);
6834 return 0;
6835 }
6836
6837 /* Initialize the color table. */ 6890 /* Initialize the color table. */
6838 init_color_table (); 6891 init_color_table ();
6839 6892
@@ -8428,12 +8481,15 @@ gs_load (struct frame *f, struct image *img)
8428 /* Create the pixmap. */ 8481 /* Create the pixmap. */
8429 xassert (img->pixmap == NO_PIXMAP); 8482 xassert (img->pixmap == NO_PIXMAP);
8430 8483
8431 /* Only W32 version did BLOCK_INPUT here. ++kfs */ 8484 if (x_check_image_size (0, img->width, img->height))
8432 BLOCK_INPUT; 8485 {
8433 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 8486 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8434 img->width, img->height, 8487 BLOCK_INPUT;
8435 DefaultDepthOfScreen (FRAME_X_SCREEN (f))); 8488 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8436 UNBLOCK_INPUT; 8489 img->width, img->height,
8490 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8491 UNBLOCK_INPUT;
8492 }
8437 8493
8438 if (!img->pixmap) 8494 if (!img->pixmap)
8439 { 8495 {