emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 1087305: Use INT_ADD_WRAPV etc. to check integer ov


From: Paul Eggert
Subject: [Emacs-diffs] master 1087305: Use INT_ADD_WRAPV etc. to check integer overflow
Date: Mon, 09 Nov 2015 06:48:35 +0000

branch: master
commit 1087305574fd61256d66eb0c995f8bb74bd91afe
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    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.
---
 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 8f94d2b..60751bc 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 c0179c7..ab91aaa 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 8755353..b94ea8e 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 bf2aa12..9792717 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 3e2bf1e..bc2fa4a 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 0b42a36..85b97ce 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 4db93f5..ccec15f 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 1a822f0..64c84ae 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 050eb2a..316d940 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 f545066..4695666 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 fb1addb..57ded17 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 864cac5..0c69b00 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 701bcab..90683eb 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 928eb5c..41687eb 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 c988d12..c28885ab 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 a1409d1..784ab18 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 245712e..6ab611d 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 02047db..3a64059 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 9d178a5..41bd2bc 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 b84f2ac..8c4a6d3 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 5e9c16b..5756378 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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]