From 1087305574fd61256d66eb0c995f8bb74bd91afe Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 8 Nov 2015 22:47:01 -0800 Subject: [PATCH] Use INT_ADD_WRAPV etc. to check integer overflow MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * 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. --- src/alloc.c | 55 +++++++++++++++++++++++++----------------- src/buffer.c | 11 ++++----- src/casefiddle.c | 8 +++--- src/ccl.c | 8 +++--- src/character.c | 63 +++++++++++++++--------------------------------- src/coding.c | 21 ++++++++-------- src/data.c | 31 ++++++++---------------- src/dispnew.c | 12 ++++----- src/editfns.c | 7 ++++-- src/fns.c | 4 +-- src/ftfont.c | 18 ++++++++------ src/gnutls.c | 7 +++--- src/gtkutil.c | 7 ++++-- src/image.c | 20 +++++++++------ src/keymap.c | 5 ++-- src/lisp.h | 32 ++++++------------------ src/term.c | 4 +-- src/tparam.c | 4 +-- src/xselect.c | 5 ++-- src/xsmfns.c | 3 +-- src/xterm.c | 9 +++---- 21 files changed, 150 insertions(+), 184 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 8f94d2b6097..60751bcfe2b 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 c0179c7584e..ab91aaa4e81 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 8755353240a..b94ea8e212e 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 bf2aa1254d4..9792717378d 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 3e2bf1e70c2..bc2fa4a12da 100644 --- a/src/character.c +++ b/src/character.c @@ -25,14 +25,10 @@ along with GNU Emacs. If not, see . */ /* At first, see the document in `character.h' to understand the code in this file. */ -#ifdef emacs #include -#endif #include -#ifdef emacs - #include #include #include "lisp.h" @@ -41,12 +37,6 @@ along with GNU Emacs. If not, see . */ #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 0b42a36543c..85b97ce6174 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 4db93f5625f..ccec15f430a 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 1a822f06365..64c84aec6f9 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 050eb2ac6ec..316d9408065 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 f545066fb07..46956668777 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 fb1addb7a0c..57ded171de4 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 864cac5f511..0c69b0001ee 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 701bcab7060..90683eba7b8 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 928eb5cfa37..41687eb885c 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 c988d12fe80..c28885ab132 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 a1409d1af8c..784ab18c0ee 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 245712ecfc4..6ab611d51e2 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 02047db2095..3a64059e0eb 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 9d178a50d7a..41bd2bc40de 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 b84f2ac58d9..8c4a6d3462c 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 5e9c16b8af4..5756378bd3a 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); -- 2.39.5