Commit 10873055 authored by Paul Eggert's avatar Paul Eggert

Use INT_ADD_WRAPV etc. to check integer overflow

* src/alloc.c (xnmalloc, xnrealloc, xpalloc, Fmake_string):
* src/buffer.c (record_overlay_string, overlay_strings):
* src/casefiddle.c (casify_object):
* src/ccl.c (Fccl_execute_on_string):
* src/character.c (char_width, c_string_width, lisp_string_width)
(count_size_as_multibyte, string_escape_byte8):
* src/coding.c (coding_alloc_by_realloc, produce_chars):
* src/data.c (arith_driver):
* src/dispnew.c (realloc_glyph_pool, init_display):
* src/editfns.c (styled_format):
* src/fns.c (Ffillarray):
* src/ftfont.c (ftfont_shape_by_flt):
* src/gnutls.c (gnutls_hex_string):
* src/gtkutil.c (get_utf8_string):
* src/image.c (x_to_xcolors, x_detect_edges, png_load_body):
* src/keymap.c (Fkey_description):
* src/lisp.h (SAFE_ALLOCA_LISP):
* src/term.c (encode_terminal_code):
* src/tparam.c (tparam1):
* src/xselect.c (x_property_data_to_lisp):
* src/xsmfns.c (smc_save_yourself_CB):
* src/xterm.c (x_term_init):
When checking for integer overflow, prefer INT_MULTIPLY_WRAPV to
more-complicated code involving division and/or
INT_MULTIPLY_OVERFLOW, and similarly for INT_ADD_WRAPV and
subtraction and/or INT_ADD_OVERFLOW.
* src/casefiddle.c (casify_object): Simplify multibyte size check.
* src/character.c: Remove some obsolete ‘#ifdef emacs’s.
* src/data.c (arith_driver): Also check for division overflow,
as that’s now possible given that the accumulator can now contain
any Emacs integer.
* src/lisp.h (lisp_word_count): Remove; no longer used.
parent bcca6a2a
......@@ -802,9 +802,10 @@ void *
xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
{
eassert (0 <= nitems && 0 < item_size);
if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
ptrdiff_t nbytes;
if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
return xmalloc (nitems * item_size);
return xmalloc (nbytes);
}
......@@ -815,9 +816,10 @@ void *
xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
{
eassert (0 <= nitems && 0 < item_size);
if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
ptrdiff_t nbytes;
if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
return xrealloc (pa, nitems * item_size);
return xrealloc (pa, nbytes);
}
......@@ -848,33 +850,43 @@ void *
xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
ptrdiff_t nitems_max, ptrdiff_t item_size)
{
ptrdiff_t n0 = *nitems;
eassume (0 < item_size && 0 < nitems_incr_min && 0 <= n0 && -1 <= nitems_max);
/* The approximate size to use for initial small allocation
requests. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
/* If the array is tiny, grow it to about (but no greater than)
DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
ptrdiff_t n = *nitems;
ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
ptrdiff_t half_again = n >> 1;
ptrdiff_t incr_estimate = max (tiny_max, half_again);
/* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%.
Adjust the growth according to three constraints: NITEMS_INCR_MIN,
NITEMS_MAX, and what the C language can represent safely. */
ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
? nitems_max : C_language_max);
ptrdiff_t nitems_incr_max = n_max - n;
ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
ptrdiff_t n, nbytes;
if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
n = PTRDIFF_MAX;
if (0 <= nitems_max && nitems_max < n)
n = nitems_max;
ptrdiff_t adjusted_nbytes
= ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
? min (PTRDIFF_MAX, SIZE_MAX)
: nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
if (adjusted_nbytes)
{
n = adjusted_nbytes / item_size;
nbytes = adjusted_nbytes - adjusted_nbytes % item_size;
}
if (! pa)
*nitems = 0;
if (nitems_incr_max < incr)
if (n - n0 < nitems_incr_min
&& (INT_ADD_WRAPV (n0, nitems_incr_min, &n)
|| (0 <= nitems_max && nitems_max < n)
|| INT_MULTIPLY_WRAPV (n, item_size, &nbytes)))
memory_full (SIZE_MAX);
n += incr;
pa = xrealloc (pa, n * item_size);
pa = xrealloc (pa, nbytes);
*nitems = n;
return pa;
}
......@@ -2104,9 +2116,8 @@ INIT must be an integer that represents a character. */)
EMACS_INT string_len = XINT (length);
unsigned char *p, *beg, *end;
if (string_len > STRING_BYTES_MAX / len)
if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes))
string_overflow ();
nbytes = len * string_len;
val = make_uninit_multibyte_string (string_len, nbytes);
for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
{
......
......@@ -3245,9 +3245,9 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
else
nbytes = SBYTES (str);
if (INT_ADD_OVERFLOW (ssl->bytes, nbytes))
if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
memory_full (SIZE_MAX);
ssl->bytes += nbytes;
ssl->bytes = nbytes;
if (STRINGP (str2))
{
......@@ -3259,9 +3259,9 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
else
nbytes = SBYTES (str2);
if (INT_ADD_OVERFLOW (ssl->bytes, nbytes))
if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
memory_full (SIZE_MAX);
ssl->bytes += nbytes;
ssl->bytes = nbytes;
}
}
......@@ -3357,9 +3357,8 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
unsigned char *p;
ptrdiff_t total;
if (INT_ADD_OVERFLOW (overlay_heads.bytes, overlay_tails.bytes))
if (INT_ADD_WRAPV (overlay_heads.bytes, overlay_tails.bytes, &total))
memory_full (SIZE_MAX);
total = overlay_heads.bytes + overlay_tails.bytes;
if (total > overlay_str_len)
overlay_str_buf = xpalloc (overlay_str_buf, &overlay_str_len,
total - overlay_str_len, -1, 1);
......
......@@ -114,15 +114,15 @@ casify_object (enum case_action flag, Lisp_Object obj)
ptrdiff_t i, i_byte, size = SCHARS (obj);
int len;
USE_SAFE_ALLOCA;
ptrdiff_t o_size = (size < STRING_BYTES_BOUND / MAX_MULTIBYTE_LENGTH
? size * MAX_MULTIBYTE_LENGTH
: STRING_BYTES_BOUND);
ptrdiff_t o_size;
if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &o_size))
o_size = PTRDIFF_MAX;
unsigned char *dst = SAFE_ALLOCA (o_size);
unsigned char *o = dst;
for (i = i_byte = 0; i < size; i++, i_byte += len)
{
if (o_size - (o - dst) < MAX_MULTIBYTE_LENGTH)
if (o_size - MAX_MULTIBYTE_LENGTH < o - dst)
string_overflow ();
c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
if (inword && flag != CASE_CAPITALIZE_UP)
......
......@@ -2071,12 +2071,10 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY
}
buf_magnification = ccl.buf_magnification ? ccl.buf_magnification : 1;
if ((min (PTRDIFF_MAX, SIZE_MAX) - 256) / buf_magnification < str_bytes)
outbufsize = str_bytes;
if (INT_MULTIPLY_WRAPV (buf_magnification, outbufsize, &outbufsize)
|| INT_ADD_WRAPV (256, outbufsize, &outbufsize))
memory_full (SIZE_MAX);
outbufsize = (ccl.buf_magnification
? str_bytes * ccl.buf_magnification + 256
: str_bytes + 256);
outp = outbuf = xmalloc (outbufsize);
consumed_chars = consumed_bytes = 0;
......
......@@ -25,14 +25,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* At first, see the document in `character.h' to understand the code
in this file. */
#ifdef emacs
#include <config.h>
#endif
#include <stdio.h>
#ifdef emacs
#include <sys/types.h>
#include <intprops.h>
#include "lisp.h"
......@@ -41,12 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "composite.h"
#include "disptab.h"
#else /* not emacs */
#include "mulelib.h"
#endif /* emacs */
/* Char-table of information about which character to unify to which
Unicode character. Mainly used by the macro MAYBE_UNIFY_CHAR. */
Lisp_Object Vchar_unify_table;
......@@ -302,9 +292,8 @@ char_width (int c, struct Lisp_Char_Table *dp)
if (CHARACTERP (ch))
{
int w = CHAR_WIDTH (XFASTINT (ch));
if (INT_ADD_OVERFLOW (width, w))
if (INT_ADD_WRAPV (width, w, &width))
string_overflow ();
width += w;
}
}
}
......@@ -349,20 +338,16 @@ c_string_width (const unsigned char *str, ptrdiff_t len, int precision,
int c = STRING_CHAR_AND_LENGTH (str + i_byte, bytes);
ptrdiff_t thiswidth = char_width (c, dp);
if (precision <= 0)
{
if (INT_ADD_OVERFLOW (width, thiswidth))
string_overflow ();
}
else if (precision - width < thiswidth)
if (0 < precision && precision - width < thiswidth)
{
*nchars = i;
*nbytes = i_byte;
return width;
}
if (INT_ADD_WRAPV (thiswidth, width, &width))
string_overflow ();
i++;
i_byte += bytes;
width += thiswidth;
}
if (precision > 0)
......@@ -436,22 +421,16 @@ lisp_string_width (Lisp_Object string, ptrdiff_t precision,
thiswidth = char_width (c, dp);
}
if (precision <= 0)
{
#ifdef emacs
if (INT_ADD_OVERFLOW (width, thiswidth))
string_overflow ();
#endif
}
else if (precision - width < thiswidth)
if (0 < precision && precision - width < thiswidth)
{
*nchars = i;
*nbytes = i_byte;
return width;
}
if (INT_ADD_WRAPV (thiswidth, width, &width))
string_overflow ();
i += chars;
i_byte += bytes;
width += thiswidth;
}
if (precision > 0)
......@@ -657,9 +636,8 @@ count_size_as_multibyte (const unsigned char *str, ptrdiff_t len)
for (bytes = 0; str < endp; str++)
{
int n = *str < 0x80 ? 1 : 2;
if (INT_ADD_OVERFLOW (bytes, n))
if (INT_ADD_WRAPV (bytes, n, &bytes))
string_overflow ();
bytes += n;
}
return bytes;
}
......@@ -795,6 +773,7 @@ string_escape_byte8 (Lisp_Object string)
ptrdiff_t nbytes = SBYTES (string);
bool multibyte = STRING_MULTIBYTE (string);
ptrdiff_t byte8_count;
ptrdiff_t thrice_byte8_count, uninit_nchars, uninit_nbytes;
const unsigned char *src, *src_end;
unsigned char *dst;
Lisp_Object val;
......@@ -808,23 +787,23 @@ string_escape_byte8 (Lisp_Object string)
if (byte8_count == 0)
return string;
if (INT_MULTIPLY_WRAPV (byte8_count, 3, &thrice_byte8_count))
string_overflow ();
if (multibyte)
{
if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count
|| (STRING_BYTES_BOUND - nbytes) / 2 < byte8_count)
string_overflow ();
/* Convert 2-byte sequence of byte8 chars to 4-byte octal. */
val = make_uninit_multibyte_string (nchars + byte8_count * 3,
nbytes + byte8_count * 2);
if (INT_ADD_WRAPV (nchars, thrice_byte8_count, &uninit_nchars)
|| INT_ADD_WRAPV (nbytes, 2 * byte8_count, &uninit_nbytes))
string_overflow ();
val = make_uninit_multibyte_string (uninit_nchars, uninit_nbytes);
}
else
{
if ((STRING_BYTES_BOUND - nbytes) / 3 < byte8_count)
string_overflow ();
/* Convert 1-byte sequence of byte8 chars to 4-byte octal. */
val = make_uninit_string (nbytes + byte8_count * 3);
if (INT_ADD_WRAPV (thrice_byte8_count, nbytes, &uninit_nbytes))
string_overflow ();
val = make_uninit_string (uninit_nbytes);
}
src = SDATA (string);
......@@ -981,8 +960,6 @@ character is not ASCII nor 8-bit character, an error is signaled. */)
return make_number (c);
}
#ifdef emacs
/* Return true if C is an alphabetic character. */
bool
alphabeticp (int c)
......@@ -1131,5 +1108,3 @@ See The Unicode Standard for the meaning of those values. */);
/* The correct char-table is setup in characters.el. */
Vunicode_category_table = Qnil;
}
#endif /* emacs */
......@@ -1008,11 +1008,12 @@ coding_change_destination (struct coding_system *coding)
static void
coding_alloc_by_realloc (struct coding_system *coding, ptrdiff_t bytes)
{
if (STRING_BYTES_BOUND - coding->dst_bytes < bytes)
ptrdiff_t newbytes;
if (INT_ADD_WRAPV (coding->dst_bytes, bytes, &newbytes)
|| SIZE_MAX < newbytes)
string_overflow ();
coding->destination = xrealloc (coding->destination,
coding->dst_bytes + bytes);
coding->dst_bytes += bytes;
coding->destination = xrealloc (coding->destination, newbytes);
coding->dst_bytes = newbytes;
}
static void
......@@ -7048,14 +7049,12 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table,
if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars)
{
eassert (growable_destination (coding));
if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf))
/ MAX_MULTIBYTE_LENGTH)
< to_nchars)
ptrdiff_t dst_size;
if (INT_MULTIPLY_WRAPV (to_nchars, MAX_MULTIBYTE_LENGTH,
&dst_size)
|| INT_ADD_WRAPV (buf_end - buf, dst_size, &dst_size))
memory_full (SIZE_MAX);
dst = alloc_destination (coding,
buf_end - buf
+ MAX_MULTIBYTE_LENGTH * to_nchars,
dst);
dst = alloc_destination (coding, dst_size, dst);
if (EQ (coding->src_object, coding->dst_object))
{
coding_set_source (coding);
......
......@@ -2631,30 +2631,16 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
switch (code)
{
case Aadd:
if (INT_ADD_OVERFLOW (accum, next))
{
overflow = 1;
accum &= INTMASK;
}
accum += next;
overflow |= INT_ADD_WRAPV (accum, next, &accum);
break;
case Asub:
if (INT_SUBTRACT_OVERFLOW (accum, next))
{
overflow = 1;
accum &= INTMASK;
}
accum = argnum ? accum - next : nargs == 1 ? - next : next;
if (! argnum)
accum = nargs == 1 ? - next : next;
else
overflow |= INT_SUBTRACT_WRAPV (accum, next, &accum);
break;
case Amult:
if (INT_MULTIPLY_OVERFLOW (accum, next))
{
EMACS_UINT a = accum, b = next, ab = a * b;
overflow = 1;
accum = ab & INTMASK;
}
else
accum *= next;
overflow |= INT_MULTIPLY_WRAPV (accum, next, &accum);
break;
case Adiv:
if (! (argnum || nargs == 1))
......@@ -2663,7 +2649,10 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
{
if (next == 0)
xsignal0 (Qarith_error);
accum /= next;
if (INT_DIVIDE_OVERFLOW (accum, next))
overflow = true;
else
accum /= next;
}
break;
case Alogand:
......
......@@ -1331,10 +1331,8 @@ realloc_glyph_pool (struct glyph_pool *pool, struct dim matrix_dim)
|| matrix_dim.width != pool->ncolumns);
/* Enlarge the glyph pool. */
needed = matrix_dim.width;
if (INT_MULTIPLY_OVERFLOW (needed, matrix_dim.height))
if (INT_MULTIPLY_WRAPV (matrix_dim.height, matrix_dim.width, &needed))
memory_full (SIZE_MAX);
needed *= matrix_dim.height;
if (needed > pool->nglyphs)
{
ptrdiff_t old_nglyphs = pool->nglyphs;
......@@ -6094,15 +6092,15 @@ init_display (void)
struct frame *sf = SELECTED_FRAME ();
int width = FRAME_TOTAL_COLS (sf);
int height = FRAME_TOTAL_LINES (sf);
int area;
/* If these sizes are so big they cause overflow, just ignore the
change. It's not clear what better we could do. The rest of
the code assumes that (width + 2) * height * sizeof (struct glyph)
does not overflow and does not exceed PTRDIFF_MAX or SIZE_MAX. */
if (INT_ADD_OVERFLOW (width, 2)
|| INT_MULTIPLY_OVERFLOW (width + 2, height)
|| (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph)
< (width + 2) * height))
if (INT_ADD_WRAPV (width, 2, &area)
|| INT_MULTIPLY_WRAPV (height, area, &area)
|| min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < area)
fatal ("screen size %dx%d too big", width, height);
}
......
......@@ -3887,9 +3887,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
ptrdiff_t formatlen = SBYTES (args[0]);
/* Allocate the info and discarded tables. */
if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
ptrdiff_t alloca_size;
if (INT_MULTIPLY_WRAPV (nargs, sizeof *info, &alloca_size)
|| INT_ADD_WRAPV (sizeof *info, alloca_size, &alloca_size)
|| INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size)
|| SIZE_MAX < alloca_size)
memory_full (SIZE_MAX);
size_t alloca_size = (nargs + 1) * sizeof *info + formatlen;
/* info[0] is unused. Unused elements have -1 for start. */
info = SAFE_ALLOCA (alloca_size);
memset (info, 0, alloca_size);
......
......@@ -2389,9 +2389,9 @@ ARRAY is a vector, string, char-table, or bool-vector. */)
unsigned char str[MAX_MULTIBYTE_LENGTH];
int len = CHAR_STRING (charval, str);
ptrdiff_t size_byte = SBYTES (array);
ptrdiff_t product;
if (INT_MULTIPLY_OVERFLOW (SCHARS (array), len)
|| SCHARS (array) * len != size_byte)
if (INT_MULTIPLY_WRAPV (size, len, &product) || product != size_byte)
error ("Attempt to change byte length of a string");
for (idx = 0; idx < size_byte; idx++)
*p++ = str[idx % len];
......
......@@ -2561,20 +2561,21 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
}
}
if (INT_MAX / 2 < len)
int len2;
if (INT_MULTIPLY_WRAPV (len, 2, &len2))
memory_full (SIZE_MAX);
if (gstring.allocated == 0)
{
gstring.glyph_size = sizeof (MFLTGlyphFT);
gstring.glyphs = xnmalloc (len * 2, sizeof (MFLTGlyphFT));
gstring.allocated = len * 2;
gstring.glyphs = xnmalloc (len2, sizeof (MFLTGlyphFT));
gstring.allocated = len2;
}
else if (gstring.allocated < len * 2)
else if (gstring.allocated < len2)
{
gstring.glyphs = xnrealloc (gstring.glyphs, len * 2,
gstring.glyphs = xnrealloc (gstring.glyphs, len2,
sizeof (MFLTGlyphFT));
gstring.allocated = len * 2;
gstring.allocated = len2;
}
glyphs = (MFLTGlyphFT *) (gstring.glyphs);
memset (glyphs, 0, len * sizeof (MFLTGlyphFT));
......@@ -2624,11 +2625,12 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt);
if (result != -2)
break;
if (INT_MAX / 2 < gstring.allocated)
int len2;
if (INT_MULTIPLY_WRAPV (gstring.allocated, 2, &len2))
memory_full (SIZE_MAX);
gstring.glyphs = xnrealloc (gstring.glyphs,
gstring.allocated, 2 * sizeof (MFLTGlyphFT));
gstring.allocated *= 2;
gstring.allocated = len2;
}
if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
return Qnil;
......
......@@ -781,10 +781,11 @@ static Lisp_Object
gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
{
ptrdiff_t prefix_length = strlen (prefix);
if ((STRING_BYTES_BOUND - prefix_length) / 3 < buf_size)
ptrdiff_t retlen;
if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
|| INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
string_overflow ();
Lisp_Object ret = make_uninit_string (prefix_length + 3 * buf_size
- (buf_size != 0));
Lisp_Object ret = make_uninit_string (retlen);
char *string = SSDATA (ret);
strcpy (string, prefix);
......
......@@ -517,9 +517,12 @@ get_utf8_string (const char *str)
if (cp) g_free (cp);
len = strlen (str);
if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad)
ptrdiff_t alloc;
if (INT_MULTIPLY_WRAPV (nr_bad, 4, &alloc)
|| INT_ADD_WRAPV (len + 1, alloc, &alloc)
|| SIZE_MAX < alloc)
memory_full (SIZE_MAX);
up = utf8_str = xmalloc (len + nr_bad * 4 + 1);
up = utf8_str = xmalloc (alloc);
p = (unsigned char *)str;
while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
......
......@@ -4662,13 +4662,16 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
int x, y;
XColor *colors, *p;
XImagePtr_or_DC ximg;
ptrdiff_t nbytes;
#ifdef HAVE_NTGUI
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width)
if (INT_MULTIPLY_WRAPV (sizeof *colors, img->width, &nbytes)
|| INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes)
|| SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
colors = xmalloc (sizeof *colors * img->width * img->height);
colors = xmalloc (nbytes);
/* Get the X image or create a memory device context for IMG. */
ximg = image_get_x_image_or_dc (f, img, 0, &prev);
......@@ -4801,15 +4804,17 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus
XColor *colors = x_to_xcolors (f, img, 1);
XColor *new, *p;
int x, y, i, sum;
ptrdiff_t nbytes;
for (i = sum = 0; i < 9; ++i)
sum += eabs (matrix[i]);
#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width)
if (INT_MULTIPLY_WRAPV (sizeof *new, img->width, &nbytes)
|| INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes))
memory_full (SIZE_MAX);
new = xmalloc (sizeof *new * img->width * img->height);
new = xmalloc (nbytes);
for (y = 0; y < img->height; ++y)
{
......@@ -5898,6 +5903,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
png_uint_32 row_bytes;
bool transparent_p;
struct png_memory_storage tbr; /* Data to be read */
ptrdiff_t nbytes;
#ifdef USE_CAIRO
unsigned char *data = 0;
......@@ -6102,10 +6108,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
row_bytes = png_get_rowbytes (png_ptr, info_ptr);
/* Allocate memory for the image. */
if (height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows
|| row_bytes > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height)
if (INT_MULTIPLY_WRAPV (row_bytes, sizeof *pixels, &nbytes)
|| INT_MULTIPLY_WRAPV (nbytes, height, &nbytes))
memory_full (SIZE_MAX);
c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
c->pixels = pixels = xmalloc (nbytes);
c->rows = rows = xmalloc (height * sizeof *rows);
for (i = 0; i < height; ++i)
rows[i] = pixels + i * row_bytes;
......
......@@ -1984,9 +1984,10 @@ For an approximate inverse of this, see `kbd'. */)
size += XINT (Flength (prefix));
/* This has one extra element at the end that we don't pass to Fconcat. */
if (min (PTRDIFF_MAX, SIZE_MAX) / word_size / 4 < size)
EMACS_INT size4;
if (INT_MULTIPLY_WRAPV (size, 4, &size4))
memory_full (SIZE_MAX);
SAFE_ALLOCA_LISP (args, size * 4);
SAFE_ALLOCA_LISP (args, size4);
/* In effect, this computes
(mapconcat 'single-key-description keys " ")
......
......@@ -4447,40 +4447,24 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
} \
} while (false)