xref: /freebsd-src/contrib/diff/lib/xmalloc.c (revision 18fd37a72c3a7549d2d4f6c6ea00bdcd2bdaca01)
1*18fd37a7SXin LI /* xmalloc.c -- malloc with out of memory checking
2*18fd37a7SXin LI 
3*18fd37a7SXin LI    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
4*18fd37a7SXin LI    1999, 2000, 2002, 2003 Free Software Foundation, Inc.
5*18fd37a7SXin LI 
6*18fd37a7SXin LI    This program is free software; you can redistribute it and/or modify
7*18fd37a7SXin LI    it under the terms of the GNU General Public License as published by
8*18fd37a7SXin LI    the Free Software Foundation; either version 2, or (at your option)
9*18fd37a7SXin LI    any later version.
10*18fd37a7SXin LI 
11*18fd37a7SXin LI    This program is distributed in the hope that it will be useful,
12*18fd37a7SXin LI    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*18fd37a7SXin LI    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*18fd37a7SXin LI    GNU General Public License for more details.
15*18fd37a7SXin LI 
16*18fd37a7SXin LI    You should have received a copy of the GNU General Public License
17*18fd37a7SXin LI    along with this program; if not, write to the Free Software Foundation,
18*18fd37a7SXin LI    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19*18fd37a7SXin LI 
20*18fd37a7SXin LI #if HAVE_CONFIG_H
21*18fd37a7SXin LI # include <config.h>
22*18fd37a7SXin LI #endif
23*18fd37a7SXin LI 
24*18fd37a7SXin LI #include "xalloc.h"
25*18fd37a7SXin LI 
26*18fd37a7SXin LI #include <stdlib.h>
27*18fd37a7SXin LI #include <string.h>
28*18fd37a7SXin LI 
29*18fd37a7SXin LI #include "gettext.h"
30*18fd37a7SXin LI #define _(msgid) gettext (msgid)
31*18fd37a7SXin LI #define N_(msgid) msgid
32*18fd37a7SXin LI 
33*18fd37a7SXin LI #include "error.h"
34*18fd37a7SXin LI #include "exitfail.h"
35*18fd37a7SXin LI 
36*18fd37a7SXin LI #ifndef SIZE_MAX
37*18fd37a7SXin LI # define SIZE_MAX ((size_t) -1)
38*18fd37a7SXin LI #endif
39*18fd37a7SXin LI 
40*18fd37a7SXin LI #ifndef HAVE_MALLOC
41*18fd37a7SXin LI "you must run the autoconf test for a GNU libc compatible malloc"
42*18fd37a7SXin LI #endif
43*18fd37a7SXin LI 
44*18fd37a7SXin LI #ifndef HAVE_REALLOC
45*18fd37a7SXin LI "you must run the autoconf test for a GNU libc compatible realloc"
46*18fd37a7SXin LI #endif
47*18fd37a7SXin LI 
48*18fd37a7SXin LI /* If non NULL, call this function when memory is exhausted. */
49*18fd37a7SXin LI void (*xalloc_fail_func) (void) = 0;
50*18fd37a7SXin LI 
51*18fd37a7SXin LI /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
52*18fd37a7SXin LI    before exiting when memory is exhausted.  Goes through gettext. */
53*18fd37a7SXin LI char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
54*18fd37a7SXin LI 
55*18fd37a7SXin LI void
xalloc_die(void)56*18fd37a7SXin LI xalloc_die (void)
57*18fd37a7SXin LI {
58*18fd37a7SXin LI   if (xalloc_fail_func)
59*18fd37a7SXin LI     (*xalloc_fail_func) ();
60*18fd37a7SXin LI   error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
61*18fd37a7SXin LI   /* The `noreturn' cannot be given to error, since it may return if
62*18fd37a7SXin LI      its first argument is 0.  To help compilers understand the
63*18fd37a7SXin LI      xalloc_die does terminate, call abort.  */
64*18fd37a7SXin LI   abort ();
65*18fd37a7SXin LI }
66*18fd37a7SXin LI 
67*18fd37a7SXin LI /* Allocate an array of N objects, each with S bytes of memory,
68*18fd37a7SXin LI    dynamically, with error checking.  S must be nonzero.  */
69*18fd37a7SXin LI 
70*18fd37a7SXin LI static inline void *
xnmalloc_inline(size_t n,size_t s)71*18fd37a7SXin LI xnmalloc_inline (size_t n, size_t s)
72*18fd37a7SXin LI {
73*18fd37a7SXin LI   void *p;
74*18fd37a7SXin LI   if (xalloc_oversized (n, s) || ! (p = malloc (n * s)))
75*18fd37a7SXin LI     xalloc_die ();
76*18fd37a7SXin LI   return p;
77*18fd37a7SXin LI }
78*18fd37a7SXin LI 
79*18fd37a7SXin LI void *
xnmalloc(size_t n,size_t s)80*18fd37a7SXin LI xnmalloc (size_t n, size_t s)
81*18fd37a7SXin LI {
82*18fd37a7SXin LI   return xnmalloc_inline (n, s);
83*18fd37a7SXin LI }
84*18fd37a7SXin LI 
85*18fd37a7SXin LI /* Allocate N bytes of memory dynamically, with error checking.  */
86*18fd37a7SXin LI 
87*18fd37a7SXin LI void *
xmalloc(size_t n)88*18fd37a7SXin LI xmalloc (size_t n)
89*18fd37a7SXin LI {
90*18fd37a7SXin LI   return xnmalloc_inline (n, 1);
91*18fd37a7SXin LI }
92*18fd37a7SXin LI 
93*18fd37a7SXin LI /* Change the size of an allocated block of memory P to an array of N
94*18fd37a7SXin LI    objects each of S bytes, with error checking.  S must be nonzero.  */
95*18fd37a7SXin LI 
96*18fd37a7SXin LI static inline void *
xnrealloc_inline(void * p,size_t n,size_t s)97*18fd37a7SXin LI xnrealloc_inline (void *p, size_t n, size_t s)
98*18fd37a7SXin LI {
99*18fd37a7SXin LI   if (xalloc_oversized (n, s) || ! (p = realloc (p, n * s)))
100*18fd37a7SXin LI     xalloc_die ();
101*18fd37a7SXin LI   return p;
102*18fd37a7SXin LI }
103*18fd37a7SXin LI 
104*18fd37a7SXin LI void *
xnrealloc(void * p,size_t n,size_t s)105*18fd37a7SXin LI xnrealloc (void *p, size_t n, size_t s)
106*18fd37a7SXin LI {
107*18fd37a7SXin LI   return xnrealloc_inline (p, n, s);
108*18fd37a7SXin LI }
109*18fd37a7SXin LI 
110*18fd37a7SXin LI /* Change the size of an allocated block of memory P to N bytes,
111*18fd37a7SXin LI    with error checking.  */
112*18fd37a7SXin LI 
113*18fd37a7SXin LI void *
xrealloc(void * p,size_t n)114*18fd37a7SXin LI xrealloc (void *p, size_t n)
115*18fd37a7SXin LI {
116*18fd37a7SXin LI   return xnrealloc_inline (p, n, 1);
117*18fd37a7SXin LI }
118*18fd37a7SXin LI 
119*18fd37a7SXin LI 
120*18fd37a7SXin LI /* If P is null, allocate a block of at least *PN such objects;
121*18fd37a7SXin LI    otherwise, reallocate P so that it contains more than *PN objects
122*18fd37a7SXin LI    each of S bytes.  *PN must be nonzero unless P is null, and S must
123*18fd37a7SXin LI    be nonzero.  Set *PN to the new number of objects, and return the
124*18fd37a7SXin LI    pointer to the new block.  *PN is never set to zero, and the
125*18fd37a7SXin LI    returned pointer is never null.
126*18fd37a7SXin LI 
127*18fd37a7SXin LI    Repeated reallocations are guaranteed to make progress, either by
128*18fd37a7SXin LI    allocating an initial block with a nonzero size, or by allocating a
129*18fd37a7SXin LI    larger block.
130*18fd37a7SXin LI 
131*18fd37a7SXin LI    In the following implementation, nonzero sizes are doubled so that
132*18fd37a7SXin LI    repeated reallocations have O(N log N) overall cost rather than
133*18fd37a7SXin LI    O(N**2) cost, but the specification for this function does not
134*18fd37a7SXin LI    guarantee that sizes are doubled.
135*18fd37a7SXin LI 
136*18fd37a7SXin LI    Here is an example of use:
137*18fd37a7SXin LI 
138*18fd37a7SXin LI      int *p = NULL;
139*18fd37a7SXin LI      size_t used = 0;
140*18fd37a7SXin LI      size_t allocated = 0;
141*18fd37a7SXin LI 
142*18fd37a7SXin LI      void
143*18fd37a7SXin LI      append_int (int value)
144*18fd37a7SXin LI        {
145*18fd37a7SXin LI 	 if (used == allocated)
146*18fd37a7SXin LI 	   p = x2nrealloc (p, &allocated, sizeof *p);
147*18fd37a7SXin LI 	 p[used++] = value;
148*18fd37a7SXin LI        }
149*18fd37a7SXin LI 
150*18fd37a7SXin LI    This causes x2nrealloc to allocate a block of some nonzero size the
151*18fd37a7SXin LI    first time it is called.
152*18fd37a7SXin LI 
153*18fd37a7SXin LI    To have finer-grained control over the initial size, set *PN to a
154*18fd37a7SXin LI    nonzero value before calling this function with P == NULL.  For
155*18fd37a7SXin LI    example:
156*18fd37a7SXin LI 
157*18fd37a7SXin LI      int *p = NULL;
158*18fd37a7SXin LI      size_t used = 0;
159*18fd37a7SXin LI      size_t allocated = 0;
160*18fd37a7SXin LI      size_t allocated1 = 1000;
161*18fd37a7SXin LI 
162*18fd37a7SXin LI      void
163*18fd37a7SXin LI      append_int (int value)
164*18fd37a7SXin LI        {
165*18fd37a7SXin LI 	 if (used == allocated)
166*18fd37a7SXin LI 	   {
167*18fd37a7SXin LI 	     p = x2nrealloc (p, &allocated1, sizeof *p);
168*18fd37a7SXin LI 	     allocated = allocated1;
169*18fd37a7SXin LI 	   }
170*18fd37a7SXin LI 	 p[used++] = value;
171*18fd37a7SXin LI        }
172*18fd37a7SXin LI 
173*18fd37a7SXin LI    */
174*18fd37a7SXin LI 
175*18fd37a7SXin LI static inline void *
x2nrealloc_inline(void * p,size_t * pn,size_t s)176*18fd37a7SXin LI x2nrealloc_inline (void *p, size_t *pn, size_t s)
177*18fd37a7SXin LI {
178*18fd37a7SXin LI   size_t n = *pn;
179*18fd37a7SXin LI 
180*18fd37a7SXin LI   if (! p)
181*18fd37a7SXin LI     {
182*18fd37a7SXin LI       if (! n)
183*18fd37a7SXin LI 	{
184*18fd37a7SXin LI 	  /* The approximate size to use for initial small allocation
185*18fd37a7SXin LI 	     requests, when the invoking code specifies an old size of
186*18fd37a7SXin LI 	     zero.  64 bytes is the largest "small" request for the
187*18fd37a7SXin LI 	     GNU C library malloc.  */
188*18fd37a7SXin LI 	  enum { DEFAULT_MXFAST = 64 };
189*18fd37a7SXin LI 
190*18fd37a7SXin LI 	  n = DEFAULT_MXFAST / s;
191*18fd37a7SXin LI 	  n += !n;
192*18fd37a7SXin LI 	}
193*18fd37a7SXin LI     }
194*18fd37a7SXin LI   else
195*18fd37a7SXin LI     {
196*18fd37a7SXin LI       if (SIZE_MAX / 2 / s < n)
197*18fd37a7SXin LI 	xalloc_die ();
198*18fd37a7SXin LI       n *= 2;
199*18fd37a7SXin LI     }
200*18fd37a7SXin LI 
201*18fd37a7SXin LI   *pn = n;
202*18fd37a7SXin LI   return xrealloc (p, n * s);
203*18fd37a7SXin LI }
204*18fd37a7SXin LI 
205*18fd37a7SXin LI void *
x2nrealloc(void * p,size_t * pn,size_t s)206*18fd37a7SXin LI x2nrealloc (void *p, size_t *pn, size_t s)
207*18fd37a7SXin LI {
208*18fd37a7SXin LI   return x2nrealloc_inline (p, pn, s);
209*18fd37a7SXin LI }
210*18fd37a7SXin LI 
211*18fd37a7SXin LI /* If P is null, allocate a block of at least *PN bytes; otherwise,
212*18fd37a7SXin LI    reallocate P so that it contains more than *PN bytes.  *PN must be
213*18fd37a7SXin LI    nonzero unless P is null.  Set *PN to the new block's size, and
214*18fd37a7SXin LI    return the pointer to the new block.  *PN is never set to zero, and
215*18fd37a7SXin LI    the returned pointer is never null.  */
216*18fd37a7SXin LI 
217*18fd37a7SXin LI void *
x2realloc(void * p,size_t * pn)218*18fd37a7SXin LI x2realloc (void *p, size_t *pn)
219*18fd37a7SXin LI {
220*18fd37a7SXin LI   return x2nrealloc_inline (p, pn, 1);
221*18fd37a7SXin LI }
222*18fd37a7SXin LI 
223*18fd37a7SXin LI /* Allocate S bytes of zeroed memory dynamically, with error checking.
224*18fd37a7SXin LI    There's no need for xnzalloc (N, S), since it would be equivalent
225*18fd37a7SXin LI    to xcalloc (N, S).  */
226*18fd37a7SXin LI 
227*18fd37a7SXin LI void *
xzalloc(size_t s)228*18fd37a7SXin LI xzalloc (size_t s)
229*18fd37a7SXin LI {
230*18fd37a7SXin LI   return memset (xmalloc (s), 0, s);
231*18fd37a7SXin LI }
232*18fd37a7SXin LI 
233*18fd37a7SXin LI /* Allocate zeroed memory for N elements of S bytes, with error
234*18fd37a7SXin LI    checking.  S must be nonzero.  */
235*18fd37a7SXin LI 
236*18fd37a7SXin LI void *
xcalloc(size_t n,size_t s)237*18fd37a7SXin LI xcalloc (size_t n, size_t s)
238*18fd37a7SXin LI {
239*18fd37a7SXin LI   void *p;
240*18fd37a7SXin LI   /* Test for overflow, since some calloc implementations don't have
241*18fd37a7SXin LI      proper overflow checks.  */
242*18fd37a7SXin LI   if (xalloc_oversized (n, s) || ! (p = calloc (n, s)))
243*18fd37a7SXin LI     xalloc_die ();
244*18fd37a7SXin LI   return p;
245*18fd37a7SXin LI }
246*18fd37a7SXin LI 
247*18fd37a7SXin LI /* Clone an object P of size S, with error checking.  There's no need
248*18fd37a7SXin LI    for xnclone (P, N, S), since xclone (P, N * S) works without any
249*18fd37a7SXin LI    need for an arithmetic overflow check.  */
250*18fd37a7SXin LI 
251*18fd37a7SXin LI void *
xclone(void const * p,size_t s)252*18fd37a7SXin LI xclone (void const *p, size_t s)
253*18fd37a7SXin LI {
254*18fd37a7SXin LI   return memcpy (xmalloc (s), p, s);
255*18fd37a7SXin LI }
256