diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-08 22:47:01 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-11-08 22:48:28 -0800 |
commit | 1087305574fd61256d66eb0c995f8bb74bd91afe (patch) | |
tree | 9f0052e41a56c785575727931ff4abb8e7dfa7e0 /src/alloc.c | |
parent | bcca6a2a028d05af3cb5b31a5a2c997f3f1f1d31 (diff) | |
download | emacs-1087305574fd61256d66eb0c995f8bb74bd91afe.tar.gz |
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.
Diffstat (limited to 'src/alloc.c')
-rw-r--r-- | src/alloc.c | 55 |
1 files changed, 33 insertions, 22 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) { |