diff options
| author | Paul Eggert | 2015-11-08 22:47:01 -0800 |
|---|---|---|
| committer | Paul Eggert | 2015-11-08 22:48:28 -0800 |
| commit | 1087305574fd61256d66eb0c995f8bb74bd91afe (patch) | |
| tree | 9f0052e41a56c785575727931ff4abb8e7dfa7e0 /src/alloc.c | |
| parent | bcca6a2a028d05af3cb5b31a5a2c997f3f1f1d31 (diff) | |
| download | emacs-1087305574fd61256d66eb0c995f8bb74bd91afe.tar.gz emacs-1087305574fd61256d66eb0c995f8bb74bd91afe.zip | |
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 * | |||
| 802 | xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) | 802 | xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) |
| 803 | { | 803 | { |
| 804 | eassert (0 <= nitems && 0 < item_size); | 804 | eassert (0 <= nitems && 0 < item_size); |
| 805 | if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems) | 805 | ptrdiff_t nbytes; |
| 806 | if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes) | ||
| 806 | memory_full (SIZE_MAX); | 807 | memory_full (SIZE_MAX); |
| 807 | return xmalloc (nitems * item_size); | 808 | return xmalloc (nbytes); |
| 808 | } | 809 | } |
| 809 | 810 | ||
| 810 | 811 | ||
| @@ -815,9 +816,10 @@ void * | |||
| 815 | xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) | 816 | xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) |
| 816 | { | 817 | { |
| 817 | eassert (0 <= nitems && 0 < item_size); | 818 | eassert (0 <= nitems && 0 < item_size); |
| 818 | if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems) | 819 | ptrdiff_t nbytes; |
| 820 | if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes) | ||
| 819 | memory_full (SIZE_MAX); | 821 | memory_full (SIZE_MAX); |
| 820 | return xrealloc (pa, nitems * item_size); | 822 | return xrealloc (pa, nbytes); |
| 821 | } | 823 | } |
| 822 | 824 | ||
| 823 | 825 | ||
| @@ -848,33 +850,43 @@ void * | |||
| 848 | xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, | 850 | xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, |
| 849 | ptrdiff_t nitems_max, ptrdiff_t item_size) | 851 | ptrdiff_t nitems_max, ptrdiff_t item_size) |
| 850 | { | 852 | { |
| 853 | ptrdiff_t n0 = *nitems; | ||
| 854 | eassume (0 < item_size && 0 < nitems_incr_min && 0 <= n0 && -1 <= nitems_max); | ||
| 855 | |||
| 851 | /* The approximate size to use for initial small allocation | 856 | /* The approximate size to use for initial small allocation |
| 852 | requests. This is the largest "small" request for the GNU C | 857 | requests. This is the largest "small" request for the GNU C |
| 853 | library malloc. */ | 858 | library malloc. */ |
| 854 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; | 859 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; |
| 855 | 860 | ||
| 856 | /* If the array is tiny, grow it to about (but no greater than) | 861 | /* If the array is tiny, grow it to about (but no greater than) |
| 857 | DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */ | 862 | DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. |
| 858 | ptrdiff_t n = *nitems; | 863 | Adjust the growth according to three constraints: NITEMS_INCR_MIN, |
| 859 | ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n; | ||
| 860 | ptrdiff_t half_again = n >> 1; | ||
| 861 | ptrdiff_t incr_estimate = max (tiny_max, half_again); | ||
| 862 | |||
| 863 | /* Adjust the increment according to three constraints: NITEMS_INCR_MIN, | ||
| 864 | NITEMS_MAX, and what the C language can represent safely. */ | 864 | NITEMS_MAX, and what the C language can represent safely. */ |
| 865 | ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size; | ||
| 866 | ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max | ||
| 867 | ? nitems_max : C_language_max); | ||
| 868 | ptrdiff_t nitems_incr_max = n_max - n; | ||
| 869 | ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max)); | ||
| 870 | 865 | ||
| 871 | eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max); | 866 | ptrdiff_t n, nbytes; |
| 867 | if (INT_ADD_WRAPV (n0, n0 >> 1, &n)) | ||
| 868 | n = PTRDIFF_MAX; | ||
| 869 | if (0 <= nitems_max && nitems_max < n) | ||
| 870 | n = nitems_max; | ||
| 871 | |||
| 872 | ptrdiff_t adjusted_nbytes | ||
| 873 | = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes) | ||
| 874 | ? min (PTRDIFF_MAX, SIZE_MAX) | ||
| 875 | : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0); | ||
| 876 | if (adjusted_nbytes) | ||
| 877 | { | ||
| 878 | n = adjusted_nbytes / item_size; | ||
| 879 | nbytes = adjusted_nbytes - adjusted_nbytes % item_size; | ||
| 880 | } | ||
| 881 | |||
| 872 | if (! pa) | 882 | if (! pa) |
| 873 | *nitems = 0; | 883 | *nitems = 0; |
| 874 | if (nitems_incr_max < incr) | 884 | if (n - n0 < nitems_incr_min |
| 885 | && (INT_ADD_WRAPV (n0, nitems_incr_min, &n) | ||
| 886 | || (0 <= nitems_max && nitems_max < n) | ||
| 887 | || INT_MULTIPLY_WRAPV (n, item_size, &nbytes))) | ||
| 875 | memory_full (SIZE_MAX); | 888 | memory_full (SIZE_MAX); |
| 876 | n += incr; | 889 | pa = xrealloc (pa, nbytes); |
| 877 | pa = xrealloc (pa, n * item_size); | ||
| 878 | *nitems = n; | 890 | *nitems = n; |
| 879 | return pa; | 891 | return pa; |
| 880 | } | 892 | } |
| @@ -2104,9 +2116,8 @@ INIT must be an integer that represents a character. */) | |||
| 2104 | EMACS_INT string_len = XINT (length); | 2116 | EMACS_INT string_len = XINT (length); |
| 2105 | unsigned char *p, *beg, *end; | 2117 | unsigned char *p, *beg, *end; |
| 2106 | 2118 | ||
| 2107 | if (string_len > STRING_BYTES_MAX / len) | 2119 | if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes)) |
| 2108 | string_overflow (); | 2120 | string_overflow (); |
| 2109 | nbytes = len * string_len; | ||
| 2110 | val = make_uninit_multibyte_string (string_len, nbytes); | 2121 | val = make_uninit_multibyte_string (string_len, nbytes); |
| 2111 | for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len) | 2122 | for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len) |
| 2112 | { | 2123 | { |