(root)/
m4-1.4.19/
lib/
xmalloc.c
       1  /* xmalloc.c -- malloc with out of memory checking
       2  
       3     Copyright (C) 1990-2000, 2002-2006, 2008-2021 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  #define XALLOC_INLINE _GL_EXTERN_INLINE
      21  
      22  #include "xalloc.h"
      23  
      24  #include "intprops.h"
      25  #include "minmax.h"
      26  
      27  #include <stdlib.h>
      28  #include <string.h>
      29  
      30  /* Allocate N bytes of memory dynamically, with error checking.  */
      31  
      32  void *
      33  xmalloc (size_t n)
      34  {
      35    void *p = malloc (n);
      36    if (!p)
      37      xalloc_die ();
      38    return p;
      39  }
      40  
      41  /* Change the size of an allocated block of memory P to N bytes,
      42     with error checking.  */
      43  
      44  void *
      45  xrealloc (void *p, size_t n)
      46  {
      47    void *r = realloc (p, n);
      48    if (!r && (!p || n))
      49      xalloc_die ();
      50    return r;
      51  }
      52  
      53  /* Change the size of an allocated block of memory P to an array of N
      54     objects each of S bytes, with error checking.  */
      55  
      56  void *
      57  xreallocarray (void *p, size_t n, size_t s)
      58  {
      59    void *r = reallocarray (p, n, s);
      60    if (!r && (!p || (n && s)))
      61      xalloc_die ();
      62    return r;
      63  }
      64  
      65  /* If P is null, allocate a block of at least *PN bytes; otherwise,
      66     reallocate P so that it contains more than *PN bytes.  *PN must be
      67     nonzero unless P is null.  Set *PN to the new block's size, and
      68     return the pointer to the new block.  *PN is never set to zero, and
      69     the returned pointer is never null.  */
      70  
      71  void *
      72  x2realloc (void *p, size_t *pn)
      73  {
      74    return x2nrealloc (p, pn, 1);
      75  }
      76  
      77  /* Grow PA, which points to an array of *NITEMS items, and return the
      78     location of the reallocated array, updating *NITEMS to reflect its
      79     new size.  The new array will contain at least NITEMS_INCR_MIN more
      80     items, but will not contain more than NITEMS_MAX items total.
      81     ITEM_SIZE is the size of each item, in bytes.
      82  
      83     ITEM_SIZE and NITEMS_INCR_MIN must be positive.  *NITEMS must be
      84     nonnegative.  If NITEMS_MAX is -1, it is treated as if it were
      85     infinity.
      86  
      87     If PA is null, then allocate a new array instead of reallocating
      88     the old one.
      89  
      90     Thus, to grow an array A without saving its old contents, do
      91     { free (A); A = xpalloc (NULL, &AITEMS, ...); }.  */
      92  
      93  void *
      94  xpalloc (void *pa, idx_t *nitems, idx_t nitems_incr_min,
      95           ptrdiff_t nitems_max, idx_t item_size)
      96  {
      97    idx_t n0 = *nitems;
      98  
      99    /* The approximate size to use for initial small allocation
     100       requests.  This is the largest "small" request for the GNU C
     101       library malloc.  */
     102    enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
     103  
     104    /* If the array is tiny, grow it to about (but no greater than)
     105       DEFAULT_MXFAST bytes.  Otherwise, grow it by about 50%.
     106       Adjust the growth according to three constraints: NITEMS_INCR_MIN,
     107       NITEMS_MAX, and what the C language can represent safely.  */
     108  
     109    idx_t n;
     110    if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
     111      n = IDX_MAX;
     112    if (0 <= nitems_max && nitems_max < n)
     113      n = nitems_max;
     114  
     115    /* NBYTES is of a type suitable for holding the count of bytes in an object.
     116       This is typically idx_t, but it should be size_t on (theoretical?)
     117       platforms where SIZE_MAX < IDX_MAX so xpalloc does not pass
     118       values greater than SIZE_MAX to xrealloc.  */
     119  #if IDX_MAX <= SIZE_MAX
     120    idx_t nbytes;
     121  #else
     122    size_t nbytes;
     123  #endif
     124    idx_t adjusted_nbytes
     125      = (INT_MULTIPLY_WRAPV (n, item_size, &nbytes)
     126         ? MIN (IDX_MAX, SIZE_MAX)
     127         : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
     128    if (adjusted_nbytes)
     129      {
     130        n = adjusted_nbytes / item_size;
     131        nbytes = adjusted_nbytes - adjusted_nbytes % item_size;
     132      }
     133  
     134    if (! pa)
     135      *nitems = 0;
     136    if (n - n0 < nitems_incr_min
     137        && (INT_ADD_WRAPV (n0, nitems_incr_min, &n)
     138            || (0 <= nitems_max && nitems_max < n)
     139            || INT_MULTIPLY_WRAPV (n, item_size, &nbytes)))
     140      xalloc_die ();
     141    pa = xrealloc (pa, nbytes);
     142    *nitems = n;
     143    return pa;
     144  }
     145  
     146  /* Allocate N bytes of zeroed memory dynamically, with error checking.
     147     There's no need for xnzalloc (N, S), since it would be equivalent
     148     to xcalloc (N, S).  */
     149  
     150  void *
     151  xzalloc (size_t n)
     152  {
     153    return xcalloc (n, 1);
     154  }
     155  
     156  /* Allocate zeroed memory for N elements of S bytes, with error
     157     checking.  S must be nonzero.  */
     158  
     159  void *
     160  xcalloc (size_t n, size_t s)
     161  {
     162    void *p = calloc (n, s);
     163    if (!p)
     164      xalloc_die ();
     165    return p;
     166  }
     167  
     168  /* Clone an object P of size S, with error checking.  There's no need
     169     for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
     170     need for an arithmetic overflow check.  */
     171  
     172  void *
     173  xmemdup (void const *p, size_t s)
     174  {
     175    return memcpy (xmalloc (s), p, s);
     176  }
     177  
     178  /* Clone STRING.  */
     179  
     180  char *
     181  xstrdup (char const *string)
     182  {
     183    return xmemdup (string, strlen (string) + 1);
     184  }