aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2000-01-01 10:09:45 +0000
committerGerd Moellmann2000-01-01 10:09:45 +0000
commit63cec32f8d8c30fb562e946f4c66713905dee081 (patch)
treed88fe5847e34f8bbfe3b1344b1cee0a56fc1faf2 /src
parent3998eed0c79c6b68e94e8739fa1f1e08e8f09a69 (diff)
downloademacs-63cec32f8d8c30fb562e946f4c66713905dee081.tar.gz
emacs-63cec32f8d8c30fb562e946f4c66713905dee081.zip
(gif_load): Avoid sign extension and thus out of bounds
color indices when accessing raster pixels. (gif_image_p, png_image_p, jpeg_image_p, tiff_image_p): Allow only one of :file or :data. (enum pbm_keyword_index): Add PBM_DATA. (pbm_format): Add :data. (pbm_image_p): Allow either :file or :data. (pbm_read_file): New function. (pbm_scan_number): Rewritten to read from string. (pbm_load): Support :data.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/xfns.c208
2 files changed, 124 insertions, 92 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 3eaef5446c6..ac718260d59 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -2,6 +2,14 @@
2 2
3 * xfns.c (gif_load): Avoid sign extension and thus out of bounds 3 * xfns.c (gif_load): Avoid sign extension and thus out of bounds
4 color indices when accessing raster pixels. 4 color indices when accessing raster pixels.
5 (gif_image_p, png_image_p, jpeg_image_p, tiff_image_p): Allow only
6 one of :file or :data.
7 (enum pbm_keyword_index): Add PBM_DATA.
8 (pbm_format): Add :data.
9 (pbm_image_p): Allow either :file or :data.
10 (pbm_read_file): New function.
11 (pbm_scan_number): Rewritten to read from string.
12 (pbm_load): Support :data.
5 13
61999-12-31 Gerd Moellmann <gerd@gnu.org> 141999-12-31 Gerd Moellmann <gerd@gnu.org>
7 15
diff --git a/src/xfns.c b/src/xfns.c
index a1c30944c32..dc88ebe0fb8 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -19,17 +19,6 @@ along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */ 20Boston, MA 02111-1307, USA. */
21 21
22/* Ability to read images from memory instead of a file added by
23 William Perry <wmperry@gnu.org> */
24
25/* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
26 tool-bars, busy-cursor, file selection dialog added by Gerd
27 Moellmann <gerd@gnu.org>. */
28
29/* Completely rewritten by Richard Stallman. */
30
31/* Rewritten for X11 by Joseph Arceneaux */
32
33#include <config.h> 22#include <config.h>
34#include <signal.h> 23#include <signal.h>
35#include <stdio.h> 24#include <stdio.h>
@@ -57,6 +46,8 @@ Boston, MA 02111-1307, USA. */
57#ifdef HAVE_X_WINDOWS 46#ifdef HAVE_X_WINDOWS
58 47
59#include <ctype.h> 48#include <ctype.h>
49#include <sys/types.h>
50#include <sys/stat.h>
60 51
61/* On some systems, the character-composition stuff is broken in X11R5. */ 52/* On some systems, the character-composition stuff is broken in X11R5. */
62 53
@@ -7599,7 +7590,7 @@ x_build_heuristic_mask (f, file, img, how)
7599 7590
7600static int pbm_image_p P_ ((Lisp_Object object)); 7591static int pbm_image_p P_ ((Lisp_Object object));
7601static int pbm_load P_ ((struct frame *f, struct image *img)); 7592static int pbm_load P_ ((struct frame *f, struct image *img));
7602static int pbm_scan_number P_ ((FILE *fp)); 7593static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
7603 7594
7604/* The symbol `pbm' identifying images of this type. */ 7595/* The symbol `pbm' identifying images of this type. */
7605 7596
@@ -7611,6 +7602,7 @@ enum pbm_keyword_index
7611{ 7602{
7612 PBM_TYPE, 7603 PBM_TYPE,
7613 PBM_FILE, 7604 PBM_FILE,
7605 PBM_DATA,
7614 PBM_ASCENT, 7606 PBM_ASCENT,
7615 PBM_MARGIN, 7607 PBM_MARGIN,
7616 PBM_RELIEF, 7608 PBM_RELIEF,
@@ -7625,7 +7617,8 @@ enum pbm_keyword_index
7625static struct image_keyword pbm_format[PBM_LAST] = 7617static struct image_keyword pbm_format[PBM_LAST] =
7626{ 7618{
7627 {":type", IMAGE_SYMBOL_VALUE, 1}, 7619 {":type", IMAGE_SYMBOL_VALUE, 1},
7628 {":file", IMAGE_STRING_VALUE, 1}, 7620 {":file", IMAGE_STRING_VALUE, 0},
7621 {":data", IMAGE_STRING_VALUE, 0},
7629 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 7622 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7630 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 7623 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
7631 {":relief", IMAGE_INTEGER_VALUE, 0}, 7624 {":relief", IMAGE_INTEGER_VALUE, 0},
@@ -7659,36 +7652,39 @@ pbm_image_p (object)
7659 || (fmt[PBM_ASCENT].count 7652 || (fmt[PBM_ASCENT].count
7660 && XFASTINT (fmt[PBM_ASCENT].value) > 100)) 7653 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
7661 return 0; 7654 return 0;
7662 return 1; 7655
7656 /* Must specify either :data or :file. */
7657 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
7663} 7658}
7664 7659
7665 7660
7666/* Scan a decimal number from PBM input file FP and return it. Value 7661/* Scan a decimal number from *S and return it. Advance *S while
7667 is -1 at end of file or if an error occurs. */ 7662 reading the number. END is the end of the string. Value is -1 at
7663 end of input. */
7668 7664
7669static int 7665static int
7670pbm_scan_number (fp) 7666pbm_scan_number (s, end)
7671 FILE *fp; 7667 unsigned char **s, *end;
7672{ 7668{
7673 int c, val = -1; 7669 int c, val = -1;
7674 7670
7675 while (!feof (fp)) 7671 while (*s < end)
7676 { 7672 {
7677 /* Skip white-space. */ 7673 /* Skip white-space. */
7678 while ((c = fgetc (fp)) != EOF && isspace (c)) 7674 while (*s < end && (c = *(*s)++, isspace (c)))
7679 ; 7675 ;
7680 7676
7681 if (c == '#') 7677 if (c == '#')
7682 { 7678 {
7683 /* Skip comment to end of line. */ 7679 /* Skip comment to end of line. */
7684 while ((c = fgetc (fp)) != EOF && c != '\n') 7680 while (*s < end && (c = *(*s)++, c != '\n'))
7685 ; 7681 ;
7686 } 7682 }
7687 else if (isdigit (c)) 7683 else if (isdigit (c))
7688 { 7684 {
7689 /* Read decimal number. */ 7685 /* Read decimal number. */
7690 val = c - '0'; 7686 val = c - '0';
7691 while ((c = fgetc (fp)) != EOF && isdigit (c)) 7687 while (*s < end && (c = *(*s)++, isdigit (c)))
7692 val = 10 * val + c - '0'; 7688 val = 10 * val + c - '0';
7693 break; 7689 break;
7694 } 7690 }
@@ -7700,6 +7696,42 @@ pbm_scan_number (fp)
7700} 7696}
7701 7697
7702 7698
7699/* Read FILE into memory. Value is a pointer to a buffer allocated
7700 with xmalloc holding FILE's contents. Value is null if an error
7701 occured. *SIZE is set to the size of the file. */
7702
7703static char *
7704pbm_read_file (file, size)
7705 Lisp_Object file;
7706 int *size;
7707{
7708 FILE *fp = NULL;
7709 char *buf = NULL;
7710 struct stat st;
7711
7712 if (stat (XSTRING (file)->data, &st) == 0
7713 && (fp = fopen (XSTRING (file)->data, "r")) != NULL
7714 && (buf = (char *) xmalloc (st.st_size),
7715 fread (buf, 1, st.st_size, fp) == st.st_size))
7716 {
7717 *size = st.st_size;
7718 fclose (fp);
7719 }
7720 else
7721 {
7722 if (fp)
7723 fclose (fp);
7724 if (buf)
7725 {
7726 xfree (buf);
7727 buf = NULL;
7728 }
7729 }
7730
7731 return buf;
7732}
7733
7734
7703/* Load PBM image IMG for use on frame F. */ 7735/* Load PBM image IMG for use on frame F. */
7704 7736
7705static int 7737static int
@@ -7707,50 +7739,60 @@ pbm_load (f, img)
7707 struct frame *f; 7739 struct frame *f;
7708 struct image *img; 7740 struct image *img;
7709{ 7741{
7710 FILE *fp;
7711 char magic[2];
7712 int raw_p, x, y; 7742 int raw_p, x, y;
7713 int width, height, max_color_idx = 0; 7743 int width, height, max_color_idx = 0;
7714 XImage *ximg; 7744 XImage *ximg;
7715 Lisp_Object file, specified_file; 7745 Lisp_Object file, specified_file;
7716 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; 7746 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
7717 struct gcpro gcpro1; 7747 struct gcpro gcpro1;
7748 unsigned char *contents = NULL;
7749 unsigned char *end, *p;
7750 int size;
7718 7751
7719 specified_file = image_spec_value (img->spec, QCfile, NULL); 7752 specified_file = image_spec_value (img->spec, QCfile, NULL);
7720 file = x_find_image_file (specified_file); 7753 file = Qnil;
7721 GCPRO1 (file); 7754 GCPRO1 (file);
7722 if (!STRINGP (file))
7723 {
7724 image_error ("Cannot find image file %s", specified_file, Qnil);
7725 UNGCPRO;
7726 return 0;
7727 }
7728 7755
7729 fp = fopen (XSTRING (file)->data, "r"); 7756 if (STRINGP (specified_file))
7730 if (fp == NULL)
7731 { 7757 {
7732 UNGCPRO; 7758 file = x_find_image_file (specified_file);
7733 return 0; 7759 if (!STRINGP (file))
7734 } 7760 {
7761 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7762 UNGCPRO;
7763 return 0;
7764 }
7735 7765
7736 /* Read first two characters. */ 7766 contents = pbm_read_file (file, &size);
7737 if (fread (magic, sizeof *magic, 2, fp) != 2) 7767 if (contents == NULL)
7768 {
7769 image_error ("Error reading `%s'", file, Qnil);
7770 UNGCPRO;
7771 return 0;
7772 }
7773
7774 p = contents;
7775 end = contents + size;
7776 }
7777 else
7738 { 7778 {
7739 fclose (fp); 7779 Lisp_Object data;
7740 image_error ("Not a PBM image file: %s", file, Qnil); 7780 data = image_spec_value (img->spec, QCdata, NULL);
7741 UNGCPRO; 7781 p = XSTRING (data)->data;
7742 return 0; 7782 end = p + STRING_BYTES (XSTRING (data));
7743 } 7783 }
7744 7784
7745 if (*magic != 'P') 7785 /* Check magic number. */
7786 if (end - p < 2 || *p++ != 'P')
7746 { 7787 {
7747 fclose (fp); 7788 image_error ("Not a PBM image: %s", file, Qnil);
7748 image_error ("Not a PBM image file: %s", file, Qnil); 7789 error:
7790 xfree (contents);
7749 UNGCPRO; 7791 UNGCPRO;
7750 return 0; 7792 return 0;
7751 } 7793 }
7752 7794
7753 switch (magic[1]) 7795 switch (*p++)
7754 { 7796 {
7755 case '1': 7797 case '1':
7756 raw_p = 0, type = PBM_MONO; 7798 raw_p = 0, type = PBM_MONO;
@@ -7777,40 +7819,33 @@ pbm_load (f, img)
7777 break; 7819 break;
7778 7820
7779 default: 7821 default:
7780 fclose (fp); 7822 image_error ("Not a PBM image: %s", file, Qnil);
7781 image_error ("Not a PBM image file: %s", file, Qnil); 7823 goto error;
7782 UNGCPRO;
7783 return 0;
7784 } 7824 }
7785 7825
7786 /* Read width, height, maximum color-component. Characters 7826 /* Read width, height, maximum color-component. Characters
7787 starting with `#' up to the end of a line are ignored. */ 7827 starting with `#' up to the end of a line are ignored. */
7788 width = pbm_scan_number (fp); 7828 width = pbm_scan_number (&p, end);
7789 height = pbm_scan_number (fp); 7829 height = pbm_scan_number (&p, end);
7790 7830
7791 if (type != PBM_MONO) 7831 if (type != PBM_MONO)
7792 { 7832 {
7793 max_color_idx = pbm_scan_number (fp); 7833 max_color_idx = pbm_scan_number (&p, end);
7794 if (raw_p && max_color_idx > 255) 7834 if (raw_p && max_color_idx > 255)
7795 max_color_idx = 255; 7835 max_color_idx = 255;
7796 } 7836 }
7797 7837
7798 if (width < 0 || height < 0 7838 if (width < 0
7839 || height < 0
7799 || (type != PBM_MONO && max_color_idx < 0)) 7840 || (type != PBM_MONO && max_color_idx < 0))
7800 { 7841 goto error;
7801 fclose (fp);
7802 UNGCPRO;
7803 return 0;
7804 }
7805 7842
7806 BLOCK_INPUT; 7843 BLOCK_INPUT;
7807 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, 7844 if (!x_create_x_image_and_pixmap (f, file, width, height, 0,
7808 &ximg, &img->pixmap)) 7845 &ximg, &img->pixmap))
7809 { 7846 {
7810 fclose (fp);
7811 UNBLOCK_INPUT; 7847 UNBLOCK_INPUT;
7812 UNGCPRO; 7848 goto error;
7813 return 0;
7814 } 7849 }
7815 7850
7816 /* Initialize the color hash table. */ 7851 /* Initialize the color hash table. */
@@ -7826,12 +7861,12 @@ pbm_load (f, img)
7826 if (raw_p) 7861 if (raw_p)
7827 { 7862 {
7828 if ((x & 7) == 0) 7863 if ((x & 7) == 0)
7829 c = fgetc (fp); 7864 c = *p++;
7830 g = c & 0x80; 7865 g = c & 0x80;
7831 c <<= 1; 7866 c <<= 1;
7832 } 7867 }
7833 else 7868 else
7834 g = pbm_scan_number (fp); 7869 g = pbm_scan_number (&p, end);
7835 7870
7836 XPutPixel (ximg, x, y, (g 7871 XPutPixel (ximg, x, y, (g
7837 ? FRAME_FOREGROUND_PIXEL (f) 7872 ? FRAME_FOREGROUND_PIXEL (f)
@@ -7846,31 +7881,29 @@ pbm_load (f, img)
7846 int r, g, b; 7881 int r, g, b;
7847 7882
7848 if (type == PBM_GRAY) 7883 if (type == PBM_GRAY)
7849 r = g = b = raw_p ? fgetc (fp) : pbm_scan_number (fp); 7884 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
7850 else if (raw_p) 7885 else if (raw_p)
7851 { 7886 {
7852 r = fgetc (fp); 7887 r = *p++;
7853 g = fgetc (fp); 7888 g = *p++;
7854 b = fgetc (fp); 7889 b = *p++;
7855 } 7890 }
7856 else 7891 else
7857 { 7892 {
7858 r = pbm_scan_number (fp); 7893 r = pbm_scan_number (&p, end);
7859 g = pbm_scan_number (fp); 7894 g = pbm_scan_number (&p, end);
7860 b = pbm_scan_number (fp); 7895 b = pbm_scan_number (&p, end);
7861 } 7896 }
7862 7897
7863 if (r < 0 || g < 0 || b < 0) 7898 if (r < 0 || g < 0 || b < 0)
7864 { 7899 {
7865 fclose (fp);
7866 xfree (ximg->data); 7900 xfree (ximg->data);
7867 ximg->data = NULL; 7901 ximg->data = NULL;
7868 XDestroyImage (ximg); 7902 XDestroyImage (ximg);
7869 UNBLOCK_INPUT; 7903 UNBLOCK_INPUT;
7870 image_error ("Invalid pixel value in file `%s'", 7904 image_error ("Invalid pixel value in file `%s'",
7871 file, Qnil); 7905 file, Qnil);
7872 UNGCPRO; 7906 goto error;
7873 return 0;
7874 } 7907 }
7875 7908
7876 /* RGB values are now in the range 0..max_color_idx. 7909 /* RGB values are now in the range 0..max_color_idx.
@@ -7882,8 +7915,6 @@ pbm_load (f, img)
7882 } 7915 }
7883 } 7916 }
7884 7917
7885 fclose (fp);
7886
7887 /* Store in IMG->colors the colors allocated for the image, and 7918 /* Store in IMG->colors the colors allocated for the image, and
7888 free the color table. */ 7919 free the color table. */
7889 img->colors = colors_in_color_table (&img->ncolors); 7920 img->colors = colors_in_color_table (&img->ncolors);
@@ -7898,6 +7929,7 @@ pbm_load (f, img)
7898 img->height = height; 7929 img->height = height;
7899 7930
7900 UNGCPRO; 7931 UNGCPRO;
7932 xfree (contents);
7901 return 1; 7933 return 1;
7902} 7934}
7903 7935
@@ -7976,10 +8008,8 @@ png_image_p (object)
7976 && XFASTINT (fmt[PNG_ASCENT].value) > 100)) 8008 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
7977 return 0; 8009 return 0;
7978 8010
7979 /* Must specify either the :data or :file keyword. This should 8011 /* Must specify either the :data or :file keyword. */
7980 probably be moved up into parse_image_spec, since it seems to be 8012 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
7981 a general requirement. */
7982 return fmt[PNG_FILE].count || fmt[PNG_DATA].count;
7983} 8013}
7984 8014
7985 8015
@@ -8465,10 +8495,8 @@ jpeg_image_p (object)
8465 && XFASTINT (fmt[JPEG_ASCENT].value) > 100)) 8495 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
8466 return 0; 8496 return 0;
8467 8497
8468 /* Must specify either the :data or :file keyword. This should 8498 /* Must specify either the :data or :file keyword. */
8469 probably be moved up into parse_image_spec, since it seems to be 8499 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
8470 a general requirement. */
8471 return fmt[JPEG_FILE].count || fmt[JPEG_DATA].count;
8472} 8500}
8473 8501
8474 8502
@@ -8830,10 +8858,8 @@ tiff_image_p (object)
8830 && XFASTINT (fmt[TIFF_ASCENT].value) > 100)) 8858 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
8831 return 0; 8859 return 0;
8832 8860
8833 /* Must specify either the :data or :file keyword. This should 8861 /* Must specify either the :data or :file keyword. */
8834 probably be moved up into parse_image_spec, since it seems to be 8862 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
8835 a general requirement. */
8836 return fmt[TIFF_FILE].count || fmt[TIFF_DATA].count;
8837} 8863}
8838 8864
8839 8865
@@ -9154,10 +9180,8 @@ gif_image_p (object)
9154 && XFASTINT (fmt[GIF_ASCENT].value) > 100)) 9180 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
9155 return 0; 9181 return 0;
9156 9182
9157 /* Must specify either the :data or :file keyword. This should 9183 /* Must specify either the :data or :file keyword. */
9158 probably be moved up into parse_image_spec, since it seems to be 9184 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
9159 a general requirement. */
9160 return fmt[GIF_FILE].count || fmt[GIF_DATA].count;
9161} 9185}
9162 9186
9163/* Reading a GIF image from memory 9187/* Reading a GIF image from memory