summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-11-08 22:47:01 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2015-11-08 22:48:28 -0800
commit1087305574fd61256d66eb0c995f8bb74bd91afe (patch)
tree9f0052e41a56c785575727931ff4abb8e7dfa7e0
parentbcca6a2a028d05af3cb5b31a5a2c997f3f1f1d31 (diff)
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.
-rw-r--r--src/alloc.c55
-rw-r--r--src/buffer.c11
-rw-r--r--src/casefiddle.c8
-rw-r--r--src/ccl.c8
-rw-r--r--src/character.c63
-rw-r--r--src/coding.c21
-rw-r--r--src/data.c31
-rw-r--r--src/dispnew.c12
-rw-r--r--src/editfns.c7
-rw-r--r--src/fns.c4
-rw-r--r--src/ftfont.c18
-rw-r--r--src/gnutls.c7
-rw-r--r--src/gtkutil.c7
-rw-r--r--src/image.c20
-rw-r--r--src/keymap.c5
-rw-r--r--src/lisp.h32
-rw-r--r--src/term.c4
-rw-r--r--src/tparam.c4
-rw-r--r--src/xselect.c5
-rw-r--r--src/xsmfns.c3
-rw-r--r--src/xterm.c9
21 files changed, 150 insertions, 184 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 8f94d2b609..60751bcfe2 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -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)
{
diff --git a/src/buffer.c b/src/buffer.c
index c0179c7584..ab91aaa4e8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -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);
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 8755353240..b94ea8e212 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -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)
diff --git a/src/ccl.c b/src/ccl.c
index bf2aa1254d..9792717378 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -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;
diff --git a/src/character.c b/src/character.c
index 3e2bf1e70c..bc2fa4a12d 100644
--- a/src/character.c
+++ b/src/character.c
@@ -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 */
diff --git a/src/coding.c b/src/coding.c
index 0b42a36543..85b97ce617 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -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);
diff --git a/src/data.c b/src/data.c
index 4db93f5625..ccec15f430 100644
--- a/src/data.c
+++ b/src/data.c
@@ -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:
diff --git a/src/dispnew.c b/src/dispnew.c
index 1a822f0636..64c84aec6f 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -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);
}
diff --git a/src/editfns.c b/src/editfns.c
index 050eb2ac6e..316d940806 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -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);
diff --git a/src/fns.c b/src/fns.c
index f545066fb0..4695666877 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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];
diff --git a/src/ftfont.c b/src/ftfont.c
index fb1addb7a0..57ded171de 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -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;
diff --git a/src/gnutls.c b/src/gnutls.c
index 864cac5f51..0c69b0001e 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -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);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 701bcab706..90683eba7b 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -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,
diff --git a/src/image.c b/src/image.c
index 928eb5cfa3..41687eb885 100644
--- a/src/image.c
+++ b/src/image.c
@@ -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;
diff --git a/src/keymap.c b/src/keymap.c
index c988d12fe8..c28885ab13 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -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 " ")
diff --git a/src/lisp.h b/src/lisp.h
index a1409d1af8..784ab18c0e 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4447,40 +4447,24 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
} \
} while (false)
-
-/* Return floor (NBYTES / WORD_SIZE). */
-
-INLINE ptrdiff_t
-lisp_word_count (ptrdiff_t nbytes)
-{
- if (-1 >> 1 == -1)
- switch (word_size + 0)
- {
- case 2: return nbytes >> 1;
- case 4: return nbytes >> 2;
- case 8: return nbytes >> 3;
- case 16: return nbytes >> 4;
- default: break;
- }
- return nbytes / word_size - (nbytes % word_size < 0);
-}
-
/* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects. */
#define SAFE_ALLOCA_LISP(buf, nelt) \
do { \
- if ((nelt) <= lisp_word_count (sa_avail)) \
- (buf) = AVAIL_ALLOCA ((nelt) * word_size); \
- else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
+ ptrdiff_t alloca_nbytes; \
+ if (INT_MULTIPLY_WRAPV (nelt, word_size, &alloca_nbytes) \
+ || SIZE_MAX < alloca_nbytes) \
+ memory_full (SIZE_MAX); \
+ else if (alloca_nbytes <= sa_avail) \
+ (buf) = AVAIL_ALLOCA (alloca_nbytes); \
+ else \
{ \
Lisp_Object arg_; \
- (buf) = xmalloc ((nelt) * word_size); \
+ (buf) = xmalloc (alloca_nbytes); \
arg_ = make_save_memory (buf, nelt); \
sa_must_free = true; \
record_unwind_protect (free_save_value, arg_); \
} \
- else \
- memory_full (SIZE_MAX); \
} while (false)
diff --git a/src/term.c b/src/term.c
index 245712ecfc..6ab611d51e 100644
--- a/src/term.c
+++ b/src/term.c
@@ -532,10 +532,8 @@ encode_terminal_code (struct glyph *src, int src_len,
multibyte-form. But, it may be enlarged on demand if
Vglyph_table contains a string or a composite glyph is
encountered. */
- if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len)
+ if (INT_MULTIPLY_WRAPV (src_len, MAX_MULTIBYTE_LENGTH, &required))
memory_full (SIZE_MAX);
- required = src_len;
- required *= MAX_MULTIBYTE_LENGTH;
if (encode_terminal_src_size < required)
encode_terminal_src = xpalloc (encode_terminal_src,
&encode_terminal_src_size,
diff --git a/src/tparam.c b/src/tparam.c
index 02047db209..3a64059e0e 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -167,9 +167,9 @@ tparam1 (const char *string, char *outstring, int len,
doup++, append_len_incr = strlen (up);
else
doleft++, append_len_incr = strlen (left);
- if (INT_ADD_OVERFLOW (append_len, append_len_incr))
+ if (INT_ADD_WRAPV (append_len_incr,
+ append_len, &append_len))
memory_full (SIZE_MAX);
- append_len += append_len_incr;
}
}
*op++ = tem ? tem : 0200;
diff --git a/src/xselect.c b/src/xselect.c
index 9d178a50d7..41bd2bc40d 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -2330,10 +2330,11 @@ x_property_data_to_lisp (struct frame *f, const unsigned char *data,
Atom type, int format, unsigned long size)
{
ptrdiff_t format_bytes = format >> 3;
- if (PTRDIFF_MAX / format_bytes < size)
+ ptrdiff_t data_bytes;
+ if (INT_MULTIPLY_WRAPV (size, format_bytes, &data_bytes))
memory_full (SIZE_MAX);
return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data,
- size * format_bytes, type, format);
+ data_bytes, type, format);
}
DEFUN ("x-get-atom-name", Fx_get_atom_name,
diff --git a/src/xsmfns.c b/src/xsmfns.c
index b84f2ac58d..8c4a6d3462 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -223,9 +223,8 @@ smc_save_yourself_CB (SmcConn smcConn,
props[props_idx]->name = xstrdup (SmRestartCommand);
props[props_idx]->type = xstrdup (SmLISTofARRAY8);
/* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */
- if (INT_MAX - 3 < initial_argc)
+ if (INT_ADD_WRAPV (initial_argc, 3, &i))
memory_full (SIZE_MAX);
- i = 3 + initial_argc;
props[props_idx]->num_vals = i;
vp = xnmalloc (i, sizeof *vp);
props[props_idx]->vals = vp;
diff --git a/src/xterm.c b/src/xterm.c
index 5e9c16b8af..5756378bd3 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -11773,7 +11773,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
- ptrdiff_t lim;
block_input ();
@@ -11974,13 +11973,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
- lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
Lisp_Object system_name = Fsystem_name ();
- if (lim - SBYTES (Vinvocation_name) < SBYTES (system_name))
+ ptrdiff_t nbytes;
+ if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
+ &nbytes))
memory_full (SIZE_MAX);
dpyinfo->x_id = ++x_display_id;
- dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
- + SBYTES (system_name) + 2);
+ dpyinfo->x_id_name = xmalloc (nbytes);
char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
*nametail++ = '@';
lispstpcpy (nametail, system_name);