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