aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c55
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 *
802xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) 802xnmalloc (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 *
815xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) 816xnrealloc (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 *
848xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, 850xpalloc (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 {