diff options
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 109 |
1 files changed, 102 insertions, 7 deletions
diff --git a/src/image.c b/src/image.c index 2463c24a33a..1996d8477e9 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -1099,7 +1099,10 @@ or omitted means use the selected frame. */) | |||
| 1099 | 1099 | ||
| 1100 | static struct image *make_image P_ ((Lisp_Object spec, unsigned hash)); | 1100 | static struct image *make_image P_ ((Lisp_Object spec, unsigned hash)); |
| 1101 | static void free_image P_ ((struct frame *f, struct image *img)); | 1101 | static void free_image P_ ((struct frame *f, struct image *img)); |
| 1102 | static int check_image_size P_ ((struct frame *f, int width, int height)); | ||
| 1102 | 1103 | ||
| 1104 | #define MAX_IMAGE_SIZE 6.0 | ||
| 1105 | Lisp_Object Vmax_image_size; | ||
| 1103 | 1106 | ||
| 1104 | /* Allocate and return a new image structure for image specification | 1107 | /* Allocate and return a new image structure for image specification |
| 1105 | SPEC. SPEC has a hash value of HASH. */ | 1108 | SPEC. SPEC has a hash value of HASH. */ |
| @@ -1151,6 +1154,39 @@ free_image (f, img) | |||
| 1151 | } | 1154 | } |
| 1152 | } | 1155 | } |
| 1153 | 1156 | ||
| 1157 | /* Return 1 if the given widths and heights are valid for display; | ||
| 1158 | otherwise, return 0. */ | ||
| 1159 | |||
| 1160 | int | ||
| 1161 | check_image_size (f, width, height) | ||
| 1162 | struct frame *f; | ||
| 1163 | int width; | ||
| 1164 | int height; | ||
| 1165 | { | ||
| 1166 | int w, h; | ||
| 1167 | |||
| 1168 | if (width <= 0 || height <= 0) | ||
| 1169 | return 0; | ||
| 1170 | |||
| 1171 | if (INTEGERP (Vmax_image_size)) | ||
| 1172 | w = h = XINT (Vmax_image_size); | ||
| 1173 | else if (FLOATP (Vmax_image_size)) | ||
| 1174 | { | ||
| 1175 | if (f != NULL) | ||
| 1176 | { | ||
| 1177 | w = FRAME_PIXEL_WIDTH (f); | ||
| 1178 | h = FRAME_PIXEL_HEIGHT (f); | ||
| 1179 | } | ||
| 1180 | else | ||
| 1181 | w = h = 1024; /* Arbitrary size for unknown frame. */ | ||
| 1182 | w = (int) (XFLOAT_DATA (Vmax_image_size) * w); | ||
| 1183 | h = (int) (XFLOAT_DATA (Vmax_image_size) * h); | ||
| 1184 | } | ||
| 1185 | else | ||
| 1186 | return 1; | ||
| 1187 | |||
| 1188 | return (width <= w && height <= h); | ||
| 1189 | } | ||
| 1154 | 1190 | ||
| 1155 | /* Prepare image IMG for display on frame F. Must be called before | 1191 | /* Prepare image IMG for display on frame F. Must be called before |
| 1156 | drawing an image. */ | 1192 | drawing an image. */ |
| @@ -1708,6 +1744,12 @@ lookup_image (f, spec) | |||
| 1708 | if (img->hash == hash && !NILP (Fequal (img->spec, spec))) | 1744 | if (img->hash == hash && !NILP (Fequal (img->spec, spec))) |
| 1709 | break; | 1745 | break; |
| 1710 | 1746 | ||
| 1747 | if (img && img->load_failed_p) | ||
| 1748 | { | ||
| 1749 | free_image (f, img); | ||
| 1750 | img = NULL; | ||
| 1751 | } | ||
| 1752 | |||
| 1711 | /* If not found, create a new image and cache it. */ | 1753 | /* If not found, create a new image and cache it. */ |
| 1712 | if (img == NULL) | 1754 | if (img == NULL) |
| 1713 | { | 1755 | { |
| @@ -2551,7 +2593,8 @@ static int xbm_load P_ ((struct frame *f, struct image *img)); | |||
| 2551 | static int xbm_load_image P_ ((struct frame *f, struct image *img, | 2593 | static int xbm_load_image P_ ((struct frame *f, struct image *img, |
| 2552 | unsigned char *, unsigned char *)); | 2594 | unsigned char *, unsigned char *)); |
| 2553 | static int xbm_image_p P_ ((Lisp_Object object)); | 2595 | static int xbm_image_p P_ ((Lisp_Object object)); |
| 2554 | static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *, | 2596 | static int xbm_read_bitmap_data P_ ((struct frame *f, |
| 2597 | unsigned char *, unsigned char *, | ||
| 2555 | int *, int *, unsigned char **)); | 2598 | int *, int *, unsigned char **)); |
| 2556 | static int xbm_file_p P_ ((Lisp_Object)); | 2599 | static int xbm_file_p P_ ((Lisp_Object)); |
| 2557 | 2600 | ||
| @@ -2939,7 +2982,8 @@ Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors) | |||
| 2939 | CONTENTS looks like an in-memory XBM file. */ | 2982 | CONTENTS looks like an in-memory XBM file. */ |
| 2940 | 2983 | ||
| 2941 | static int | 2984 | static int |
| 2942 | xbm_read_bitmap_data (contents, end, width, height, data) | 2985 | xbm_read_bitmap_data (f, contents, end, width, height, data) |
| 2986 | struct frame *f; | ||
| 2943 | unsigned char *contents, *end; | 2987 | unsigned char *contents, *end; |
| 2944 | int *width, *height; | 2988 | int *width, *height; |
| 2945 | unsigned char **data; | 2989 | unsigned char **data; |
| @@ -2992,7 +3036,7 @@ xbm_read_bitmap_data (contents, end, width, height, data) | |||
| 2992 | expect (XBM_TK_NUMBER); | 3036 | expect (XBM_TK_NUMBER); |
| 2993 | } | 3037 | } |
| 2994 | 3038 | ||
| 2995 | if (*width < 0 || *height < 0) | 3039 | if (!check_image_size (f, *width, *height)) |
| 2996 | goto failure; | 3040 | goto failure; |
| 2997 | else if (data == NULL) | 3041 | else if (data == NULL) |
| 2998 | goto success; | 3042 | goto success; |
| @@ -3096,7 +3140,7 @@ xbm_load_image (f, img, contents, end) | |||
| 3096 | unsigned char *data; | 3140 | unsigned char *data; |
| 3097 | int success_p = 0; | 3141 | int success_p = 0; |
| 3098 | 3142 | ||
| 3099 | rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data); | 3143 | rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data); |
| 3100 | if (rc) | 3144 | if (rc) |
| 3101 | { | 3145 | { |
| 3102 | unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); | 3146 | unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); |
| @@ -3150,7 +3194,7 @@ xbm_file_p (data) | |||
| 3150 | { | 3194 | { |
| 3151 | int w, h; | 3195 | int w, h; |
| 3152 | return (STRINGP (data) | 3196 | return (STRINGP (data) |
| 3153 | && xbm_read_bitmap_data (SDATA (data), | 3197 | && xbm_read_bitmap_data (NULL, SDATA (data), |
| 3154 | (SDATA (data) | 3198 | (SDATA (data) |
| 3155 | + SBYTES (data)), | 3199 | + SBYTES (data)), |
| 3156 | &w, &h, NULL)); | 3200 | &w, &h, NULL)); |
| @@ -5465,8 +5509,7 @@ pbm_load (f, img) | |||
| 5465 | max_color_idx = 255; | 5509 | max_color_idx = 255; |
| 5466 | } | 5510 | } |
| 5467 | 5511 | ||
| 5468 | if (width < 0 | 5512 | if (!check_image_size (f, width, height) |
| 5469 | || height < 0 | ||
| 5470 | || (type != PBM_MONO && max_color_idx < 0)) | 5513 | || (type != PBM_MONO && max_color_idx < 0)) |
| 5471 | goto error; | 5514 | goto error; |
| 5472 | 5515 | ||
| @@ -5966,6 +6009,9 @@ png_load (f, img) | |||
| 5966 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | 6009 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, |
| 5967 | &interlace_type, NULL, NULL); | 6010 | &interlace_type, NULL, NULL); |
| 5968 | 6011 | ||
| 6012 | if (!check_image_size (f, width, height)) | ||
| 6013 | goto error; | ||
| 6014 | |||
| 5969 | /* If image contains simply transparency data, we prefer to | 6015 | /* If image contains simply transparency data, we prefer to |
| 5970 | construct a clipping mask. */ | 6016 | construct a clipping mask. */ |
| 5971 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) | 6017 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) |
| @@ -6726,6 +6772,12 @@ jpeg_load (f, img) | |||
| 6726 | width = img->width = cinfo.output_width; | 6772 | width = img->width = cinfo.output_width; |
| 6727 | height = img->height = cinfo.output_height; | 6773 | height = img->height = cinfo.output_height; |
| 6728 | 6774 | ||
| 6775 | if (!check_image_size (f, width, height)) | ||
| 6776 | { | ||
| 6777 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 6778 | longjmp (mgr.setjmp_buffer, 2); | ||
| 6779 | } | ||
| 6780 | |||
| 6729 | /* Create X image and pixmap. */ | 6781 | /* Create X image and pixmap. */ |
| 6730 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 6782 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 6731 | longjmp (mgr.setjmp_buffer, 2); | 6783 | longjmp (mgr.setjmp_buffer, 2); |
| @@ -7155,6 +7207,14 @@ tiff_load (f, img) | |||
| 7155 | of width x height 32-bit values. */ | 7207 | of width x height 32-bit values. */ |
| 7156 | fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); | 7208 | fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); |
| 7157 | fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); | 7209 | fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); |
| 7210 | |||
| 7211 | if (!check_image_size (f, width, height)) | ||
| 7212 | { | ||
| 7213 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7214 | UNGCPRO; | ||
| 7215 | return 0; | ||
| 7216 | } | ||
| 7217 | |||
| 7158 | buf = (uint32 *) xmalloc (width * height * sizeof *buf); | 7218 | buf = (uint32 *) xmalloc (width * height * sizeof *buf); |
| 7159 | 7219 | ||
| 7160 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); | 7220 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); |
| @@ -7459,6 +7519,15 @@ gif_load (f, img) | |||
| 7459 | } | 7519 | } |
| 7460 | } | 7520 | } |
| 7461 | 7521 | ||
| 7522 | /* Before reading entire contents, check the declared image size. */ | ||
| 7523 | if (!check_image_size (f, gif->SWidth, gif->SHeight)) | ||
| 7524 | { | ||
| 7525 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7526 | fn_DGifCloseFile (gif); | ||
| 7527 | UNGCPRO; | ||
| 7528 | return 0; | ||
| 7529 | } | ||
| 7530 | |||
| 7462 | /* Read entire contents. */ | 7531 | /* Read entire contents. */ |
| 7463 | rc = fn_DGifSlurp (gif); | 7532 | rc = fn_DGifSlurp (gif); |
| 7464 | if (rc == GIF_ERROR) | 7533 | if (rc == GIF_ERROR) |
| @@ -7492,6 +7561,14 @@ gif_load (f, img) | |||
| 7492 | max (gif->Image.Top + gif->Image.Height, | 7561 | max (gif->Image.Top + gif->Image.Height, |
| 7493 | image_top + image_height)); | 7562 | image_top + image_height)); |
| 7494 | 7563 | ||
| 7564 | if (!check_image_size (f, width, height)) | ||
| 7565 | { | ||
| 7566 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7567 | fn_DGifCloseFile (gif); | ||
| 7568 | UNGCPRO; | ||
| 7569 | return 0; | ||
| 7570 | } | ||
| 7571 | |||
| 7495 | /* Create the X image and pixmap. */ | 7572 | /* Create the X image and pixmap. */ |
| 7496 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 7573 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 7497 | { | 7574 | { |
| @@ -7944,6 +8021,12 @@ gs_load (f, img) | |||
| 7944 | in_height = XFASTINT (pt_height) / 72.0; | 8021 | in_height = XFASTINT (pt_height) / 72.0; |
| 7945 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; | 8022 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; |
| 7946 | 8023 | ||
| 8024 | if (!check_image_size (f, img->width, img->height)) | ||
| 8025 | { | ||
| 8026 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 8027 | return 0; | ||
| 8028 | } | ||
| 8029 | |||
| 7947 | /* Create the pixmap. */ | 8030 | /* Create the pixmap. */ |
| 7948 | xassert (img->pixmap == NO_PIXMAP); | 8031 | xassert (img->pixmap == NO_PIXMAP); |
| 7949 | 8032 | ||
| @@ -8217,6 +8300,18 @@ listed; they're always supported. */); | |||
| 8217 | Vimage_library_alist = Qnil; | 8300 | Vimage_library_alist = Qnil; |
| 8218 | Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt); | 8301 | Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt); |
| 8219 | 8302 | ||
| 8303 | DEFVAR_LISP ("max-image-size", &Vmax_image_size, | ||
| 8304 | doc: /* Maximum size of images. | ||
| 8305 | Emacs will not load an image into memory if its pixel width or | ||
| 8306 | pixel height exceeds this limit. | ||
| 8307 | |||
| 8308 | If the value is an integer, it directly specifies the maximum | ||
| 8309 | image height and width, measured in pixels. If it is a floating | ||
| 8310 | point number, it specifies the maximum image height and width | ||
| 8311 | as a ratio to the frame height and width. If the value is | ||
| 8312 | non-numeric, there is no explicit limit on the size of images. */); | ||
| 8313 | Vmax_image_size = make_float (MAX_IMAGE_SIZE); | ||
| 8314 | |||
| 8220 | Vimage_type_cache = Qnil; | 8315 | Vimage_type_cache = Qnil; |
| 8221 | staticpro (&Vimage_type_cache); | 8316 | staticpro (&Vimage_type_cache); |
| 8222 | 8317 | ||