summaryrefslogtreecommitdiff
path: root/src/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c209
1 files changed, 112 insertions, 97 deletions
diff --git a/src/image.c b/src/image.c
index aedec7954ee..c1c1671899b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -15,12 +15,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <fcntl.h>
-#include <stdio.h>
#include <unistd.h>
/* Include this before including <setjmp.h> to work around bugs with
@@ -41,6 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "dispextern.h"
#include "blockinput.h"
+#include "sysstdio.h"
#include "systime.h"
#include <epaths.h>
#include "coding.h"
@@ -2361,7 +2361,7 @@ slurp_file (int fd, ptrdiff_t *size)
This can happen if the file grows as we read it. */
ptrdiff_t buflen = st.st_size;
buf = xmalloc (buflen + 1);
- if (fread (buf, 1, buflen + 1, fp) == buflen)
+ if (fread_unlocked (buf, 1, buflen + 1, fp) == buflen)
*size = buflen;
else
{
@@ -2444,7 +2444,8 @@ static struct image_type xbm_type =
enum xbm_token
{
XBM_TK_IDENT = 256,
- XBM_TK_NUMBER
+ XBM_TK_NUMBER,
+ XBM_TK_OVERFLOW
};
@@ -2573,7 +2574,7 @@ xbm_image_p (Lisp_Object object)
static int
xbm_scan (char **s, char *end, char *sval, int *ival)
{
- unsigned char c;
+ unsigned char c UNINIT;
loop:
@@ -2586,6 +2587,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
else if (c_isdigit (c))
{
int value = 0, digit;
+ bool overflow = false;
if (c == '0' && *s < end)
{
@@ -2595,23 +2597,22 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
while (*s < end)
{
c = *(*s)++;
- if (c_isdigit (c))
- digit = c - '0';
- else if (c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
- else
+ digit = char_hexdigit (c);
+ if (digit < 0)
break;
- value = 16 * value + digit;
+ overflow |= INT_MULTIPLY_WRAPV (value, 16, &value);
+ value += digit;
}
}
- else if (c_isdigit (c))
+ else if ('0' <= c && c <= '7')
{
value = c - '0';
while (*s < end
- && (c = *(*s)++, c_isdigit (c)))
- value = 8 * value + c - '0';
+ && (c = *(*s)++, '0' <= c && c <= '7'))
+ {
+ overflow |= INT_MULTIPLY_WRAPV (value, 8, &value);
+ value += c - '0';
+ }
}
}
else
@@ -2619,13 +2620,16 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
value = c - '0';
while (*s < end
&& (c = *(*s)++, c_isdigit (c)))
- value = 10 * value + c - '0';
+ {
+ overflow |= INT_MULTIPLY_WRAPV (value, 10, &value);
+ overflow |= INT_ADD_WRAPV (value, c - '0', &value);
+ }
}
if (*s < end)
*s = *s - 1;
*ival = value;
- return XBM_TK_NUMBER;
+ return overflow ? XBM_TK_OVERFLOW : XBM_TK_NUMBER;
}
else if (c_isalpha (c) || c == '_')
{
@@ -4227,7 +4231,7 @@ xpm_load_image (struct frame *f,
color_val = Qnil;
if (!NILP (color_symbols) && !NILP (symbol_color))
{
- Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
+ Lisp_Object specified_color = Fassoc (symbol_color, color_symbols, Qnil);
if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
{
@@ -5273,6 +5277,25 @@ pbm_scan_number (char **s, char *end)
return val;
}
+/* Scan an index from *S and return it. It is a one-byte unsigned
+ index if !TWO_BYTE, and a two-byte big-endian unsigned index if
+ TWO_BYTE. */
+
+static int
+pbm_scan_index (char **s, bool two_byte)
+{
+ char *p = *s;
+ unsigned char c0 = *p++;
+ int n = c0;
+ if (two_byte)
+ {
+ unsigned char c1 = *p++;
+ n = (n << 8) + c1;
+ }
+ *s = p;
+ return n;
+}
+
/* Load PBM image IMG for use on frame F. */
@@ -5495,7 +5518,8 @@ pbm_load (struct frame *f, struct image *img)
else
{
int expected_size = height * width;
- if (max_color_idx > 255)
+ bool two_byte = 255 < max_color_idx;
+ if (two_byte)
expected_size *= 2;
if (type == PBM_COLOR)
expected_size *= 3;
@@ -5518,24 +5542,14 @@ pbm_load (struct frame *f, struct image *img)
int r, g, b;
if (type == PBM_GRAY && raw_p)
- {
- r = g = b = *p++;
- if (max_color_idx > 255)
- r = g = b = r * 256 + *p++;
- }
+ r = g = b = pbm_scan_index (&p, two_byte);
else if (type == PBM_GRAY)
r = g = b = pbm_scan_number (&p, end);
else if (raw_p)
{
- r = *p++;
- if (max_color_idx > 255)
- r = r * 256 + *p++;
- g = *p++;
- if (max_color_idx > 255)
- g = g * 256 + *p++;
- b = *p++;
- if (max_color_idx > 255)
- b = b * 256 + *p++;
+ r = pbm_scan_index (&p, two_byte);
+ g = pbm_scan_index (&p, two_byte);
+ b = pbm_scan_index (&p, two_byte);
}
else
{
@@ -5890,7 +5904,7 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
{
FILE *fp = png_get_io_ptr (png_ptr);
- if (fread (data, 1, length, fp) < length)
+ if (fread_unlocked (data, 1, length, fp) < length)
png_error (png_ptr, "Read error");
}
@@ -5959,7 +5973,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
}
/* Check PNG signature. */
- if (fread (sig, 1, sizeof sig, fp) != sizeof sig
+ if (fread_unlocked (sig, 1, sizeof sig, fp) != sizeof sig
|| png_sig_cmp (sig, 0, sizeof sig))
{
fclose (fp);
@@ -6598,7 +6612,8 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
{
ptrdiff_t bytes;
- bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
+ bytes = fread_unlocked (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE,
+ src->file);
if (bytes > 0)
src->mgr.bytes_in_buffer = bytes;
else
@@ -7143,7 +7158,7 @@ tiff_size_of_memory (thandle_t data)
/* GCC 3.x on x86 Windows targets has a bug that triggers an internal
compiler error compiling tiff_handler, see Bugzilla bug #17406
- (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring
+ (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring
this function as external works around that problem. */
# if defined (__MINGW32__) && __GNUC__ == 3
# define MINGW_STATIC
@@ -7834,7 +7849,7 @@ gif_load (struct frame *f, struct image *img)
init_color_table ();
#ifndef USE_CAIRO
- unsigned long bgcolor;
+ unsigned long bgcolor UNINIT;
if (STRINGP (specified_bg))
bgcolor = x_alloc_image_color (f, img, specified_bg,
FRAME_BACKGROUND_PIXEL (f));
@@ -8081,83 +8096,76 @@ compute_image_size (size_t width, size_t height,
int *d_width, int *d_height)
{
Lisp_Object value;
- int desired_width, desired_height;
+ int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1;
double scale = 1;
value = image_spec_value (spec, QCscale, NULL);
if (NUMBERP (value))
scale = XFLOATINT (value);
+ value = image_spec_value (spec, QCmax_width, NULL);
+ if (NATNUMP (value))
+ max_width = min (XFASTINT (value), INT_MAX);
+
+ value = image_spec_value (spec, QCmax_height, NULL);
+ if (NATNUMP (value))
+ max_height = min (XFASTINT (value), INT_MAX);
+
/* 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
aspect ratio. */
value = image_spec_value (spec, QCwidth, NULL);
- desired_width = NATNUMP (value) ?
- min (XFASTINT (value) * scale, INT_MAX) : -1;
+ if (NATNUMP (value))
+ {
+ desired_width = min (XFASTINT (value) * scale, INT_MAX);
+ /* :width overrides :max-width. */
+ max_width = -1;
+ }
+
value = image_spec_value (spec, QCheight, NULL);
- desired_height = NATNUMP (value) ?
- min (XFASTINT (value) * scale, INT_MAX) : -1;
+ if (NATNUMP (value))
+ {
+ desired_height = min (XFASTINT (value) * scale, INT_MAX);
+ /* :height overrides :max-height. */
+ max_height = -1;
+ }
+
+ /* If we have both width/height set explicitly, we skip past all the
+ aspect ratio-preserving computations below. */
+ if (desired_width != -1 && desired_height != -1)
+ goto out;
width = width * scale;
height = height * scale;
- if (desired_width == -1)
+ if (desired_width != -1)
+ /* Width known, calculate height. */
+ desired_height = scale_image_size (desired_width, width, height);
+ else if (desired_height != -1)
+ /* Height known, calculate width. */
+ desired_width = scale_image_size (desired_height, height, width);
+ else
{
- value = image_spec_value (spec, QCmax_width, NULL);
- if (NATNUMP (value))
- {
- int max_width = min (XFASTINT (value), INT_MAX);
- if (max_width < width)
- {
- /* The image is wider than :max-width. */
- desired_width = max_width;
- if (desired_height == -1)
- {
- desired_height = scale_image_size (desired_width,
- width, height);
- value = image_spec_value (spec, QCmax_height, NULL);
- if (NATNUMP (value))
- {
- int max_height = min (XFASTINT (value), INT_MAX);
- if (max_height < desired_height)
- {
- desired_height = max_height;
- desired_width = scale_image_size (desired_height,
- height, width);
- }
- }
- }
- }
- }
+ desired_width = width;
+ desired_height = height;
}
- if (desired_height == -1)
+ if (max_width != -1 && desired_width > max_width)
{
- value = image_spec_value (spec, QCmax_height, NULL);
- if (NATNUMP (value))
- {
- int max_height = min (XFASTINT (value), INT_MAX);
- if (max_height < height)
- desired_height = max_height;
- }
+ /* The image is wider than :max-width. */
+ desired_width = max_width;
+ desired_height = scale_image_size (desired_width, width, height);
}
- if (desired_width != -1 && desired_height == -1)
- /* w known, calculate h. */
- desired_height = scale_image_size (desired_width, width, height);
-
- if (desired_width == -1 && desired_height != -1)
- /* h known, calculate w. */
- desired_width = scale_image_size (desired_height, height, width);
-
- /* We have no width/height settings, so just apply the scale. */
- if (desired_width == -1 && desired_height == -1)
+ if (max_height != -1 && desired_height > max_height)
{
- desired_width = width;
- desired_height = height;
+ /* The image is higher than :max-height. */
+ desired_height = max_height;
+ desired_width = scale_image_size (desired_height, height, width);
}
+ out:
*d_width = desired_width;
*d_height = desired_height;
}
@@ -8544,13 +8552,19 @@ imagemagick_load_image (struct frame *f, struct image *img,
char hint_buffer[MaxTextExtent];
char *filename_hint = NULL;
+ /* Initialize the ImageMagick environment. */
+ static bool imagemagick_initialized;
+ if (!imagemagick_initialized)
+ {
+ imagemagick_initialized = true;
+ MagickWandGenesis ();
+ }
+
/* Handle image index for image types who can contain more than one image.
Interface :index is same as for GIF. First we "ping" the image to see how
many sub-images it contains. Pinging is faster than loading the image to
find out things about it. */
- /* Initialize the imagemagick environment. */
- MagickWandGenesis ();
image = image_spec_value (img->spec, QCindex, NULL);
ino = INTEGERP (image) ? XFASTINT (image) : 0;
image_wand = NewMagickWand ();
@@ -8851,8 +8865,10 @@ imagemagick_load_image (struct frame *f, struct image *img,
DestroyMagickWand (image_wand);
if (bg_wand) DestroyPixelWand (bg_wand);
- /* `MagickWandTerminus' terminates the imagemagick environment. */
- MagickWandTerminus ();
+ /* Do not call MagickWandTerminus, to work around ImageMagick bug 825. See:
+ https://github.com/ImageMagick/ImageMagick/issues/825
+ Although this bug was introduced in ImageMagick 6.9.9-14 and
+ fixed in 6.9.9-18, it's simpler to work around it in all versions. */
return 1;
@@ -8860,7 +8876,6 @@ imagemagick_load_image (struct frame *f, struct image *img,
DestroyMagickWand (image_wand);
if (bg_wand) DestroyPixelWand (bg_wand);
- MagickWandTerminus ();
/* TODO more cleanup. */
image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec);
return 0;
@@ -8920,7 +8935,7 @@ their descriptions (http://www.imagemagick.org/script/formats.php).
You can also try the shell command: `identify -list format'.
Note that ImageMagick recognizes many file-types that Emacs does not
-recognize as images, such as C. See `imagemagick-types-enable'
+recognize as images, such as C. See `imagemagick-enabled-types'
and `imagemagick-types-inhibit'. */)
(void)
{