Line | Count | Source (jump to first uncovered line) |
1 | | /* xmalloc.c -- malloc with out of memory checking |
2 | | |
3 | | Copyright (C) 1990-2000, 2002-2006, 2008-2025 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 "ialloc.h" |
25 | | #include "minmax.h" |
26 | | |
27 | | #include <stdckdint.h> |
28 | | #include <stdlib.h> |
29 | | #include <stdint.h> |
30 | | #include <string.h> |
31 | | |
32 | | static void * _GL_ATTRIBUTE_PURE |
33 | | check_nonnull (void *p) |
34 | 6.77k | { |
35 | 6.77k | if (!p) |
36 | 0 | xalloc_die (); |
37 | 6.77k | return p; |
38 | 6.77k | } |
39 | | |
40 | | /* Allocate S bytes of memory dynamically, with error checking. */ |
41 | | |
42 | | void * |
43 | | xmalloc (size_t s) |
44 | 6.77k | { |
45 | 6.77k | return check_nonnull (malloc (s)); |
46 | 6.77k | } |
47 | | |
48 | | void * |
49 | | ximalloc (idx_t s) |
50 | 0 | { |
51 | 0 | return check_nonnull (imalloc (s)); |
52 | 0 | } |
53 | | |
54 | | char * |
55 | | xcharalloc (size_t n) |
56 | 0 | { |
57 | 0 | return XNMALLOC (n, char); |
58 | 0 | } |
59 | | |
60 | | /* Change the size of an allocated block of memory P to S bytes, |
61 | | with error checking. */ |
62 | | |
63 | | void * |
64 | | xrealloc (void *p, size_t s) |
65 | 0 | { |
66 | 0 | void *r = realloc (p, s); |
67 | 0 | if (!r) |
68 | 0 | xalloc_die (); |
69 | 0 | return r; |
70 | 0 | } |
71 | | |
72 | | void * |
73 | | xirealloc (void *p, idx_t s) |
74 | 0 | { |
75 | 0 | return check_nonnull (irealloc (p, s)); |
76 | 0 | } |
77 | | |
78 | | /* Change the size of an allocated block of memory P to an array of N |
79 | | objects each of S bytes, with error checking. */ |
80 | | |
81 | | void * |
82 | | xreallocarray (void *p, size_t n, size_t s) |
83 | 0 | { |
84 | 0 | void *r = reallocarray (p, n, s); |
85 | 0 | if (!r) |
86 | 0 | xalloc_die (); |
87 | 0 | return r; |
88 | 0 | } |
89 | | |
90 | | void * |
91 | | xireallocarray (void *p, idx_t n, idx_t s) |
92 | 0 | { |
93 | 0 | return check_nonnull (ireallocarray (p, n, s)); |
94 | 0 | } |
95 | | |
96 | | /* Allocate an array of N objects, each with S bytes of memory, |
97 | | dynamically, with error checking. S must be nonzero. */ |
98 | | |
99 | | void * |
100 | | xnmalloc (size_t n, size_t s) |
101 | 0 | { |
102 | 0 | return xreallocarray (NULL, n, s); |
103 | 0 | } |
104 | | |
105 | | void * |
106 | | xinmalloc (idx_t n, idx_t s) |
107 | 0 | { |
108 | 0 | return xireallocarray (NULL, n, s); |
109 | 0 | } |
110 | | |
111 | | /* If P is null, allocate a block of at least *PS bytes; otherwise, |
112 | | reallocate P so that it contains more than *PS bytes. *PS must be |
113 | | nonzero unless P is null. Set *PS to the new block's size, and |
114 | | return the pointer to the new block. *PS is never set to zero, and |
115 | | the returned pointer is never null. */ |
116 | | |
117 | | void * |
118 | | x2realloc (void *p, size_t *ps) |
119 | 0 | { |
120 | 0 | return x2nrealloc (p, ps, 1); |
121 | 0 | } |
122 | | |
123 | | /* If P is null, allocate a block of at least *PN such objects; |
124 | | otherwise, reallocate P so that it contains more than *PN objects |
125 | | each of S bytes. S must be nonzero. Set *PN to the new number of |
126 | | objects, and return the pointer to the new block. *PN is never set |
127 | | to zero, and the returned pointer is never null. |
128 | | |
129 | | Repeated reallocations are guaranteed to make progress, either by |
130 | | allocating an initial block with a nonzero size, or by allocating a |
131 | | larger block. |
132 | | |
133 | | In the following implementation, nonzero sizes are increased by a |
134 | | factor of approximately 1.5 so that repeated reallocations have |
135 | | O(N) overall cost rather than O(N**2) cost, but the |
136 | | specification for this function does not guarantee that rate. |
137 | | |
138 | | Here is an example of use: |
139 | | |
140 | | int *p = NULL; |
141 | | size_t used = 0; |
142 | | size_t allocated = 0; |
143 | | |
144 | | void |
145 | | append_int (int value) |
146 | | { |
147 | | if (used == allocated) |
148 | | p = x2nrealloc (p, &allocated, sizeof *p); |
149 | | p[used++] = value; |
150 | | } |
151 | | |
152 | | This causes x2nrealloc to allocate a block of some nonzero size the |
153 | | first time it is called. |
154 | | |
155 | | To have finer-grained control over the initial size, set *PN to a |
156 | | nonzero value before calling this function with P == NULL. For |
157 | | example: |
158 | | |
159 | | int *p = NULL; |
160 | | size_t used = 0; |
161 | | size_t allocated = 0; |
162 | | size_t allocated1 = 1000; |
163 | | |
164 | | void |
165 | | append_int (int value) |
166 | | { |
167 | | if (used == allocated) |
168 | | { |
169 | | p = x2nrealloc (p, &allocated1, sizeof *p); |
170 | | allocated = allocated1; |
171 | | } |
172 | | p[used++] = value; |
173 | | } |
174 | | |
175 | | */ |
176 | | |
177 | | void * |
178 | | x2nrealloc (void *p, size_t *pn, size_t s) |
179 | 0 | { |
180 | 0 | size_t n = *pn; |
181 | |
|
182 | 0 | if (! p) |
183 | 0 | { |
184 | 0 | if (! n) |
185 | 0 | { |
186 | | /* The approximate size to use for initial small allocation |
187 | | requests, when the invoking code specifies an old size of |
188 | | zero. This is the largest "small" request for the GNU C |
189 | | library malloc. */ |
190 | 0 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; |
191 | |
|
192 | 0 | n = DEFAULT_MXFAST / s; |
193 | 0 | n += !n; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | else |
197 | 0 | { |
198 | | /* Set N = floor (1.5 * N) + 1 to make progress even if N == 0. */ |
199 | 0 | if (ckd_add (&n, n, (n >> 1) + 1)) |
200 | 0 | xalloc_die (); |
201 | 0 | } |
202 | |
|
203 | 0 | p = xreallocarray (p, n, s); |
204 | 0 | *pn = n; |
205 | 0 | return p; |
206 | 0 | } |
207 | | |
208 | | /* Grow PA, which points to an array of *PN items, and return the |
209 | | location of the reallocated array, updating *PN to reflect its |
210 | | new size. The new array will contain at least N_INCR_MIN more |
211 | | items, but will not contain more than N_MAX items total. |
212 | | S is the size of each item, in bytes. |
213 | | |
214 | | S and N_INCR_MIN must be positive. *PN must be |
215 | | nonnegative. If N_MAX is -1, it is treated as if it were |
216 | | infinity. |
217 | | |
218 | | If PA is null, then allocate a new array instead of reallocating |
219 | | the old one. |
220 | | |
221 | | Thus, to grow an array A without saving its old contents, do |
222 | | { free (A); A = xpalloc (NULL, &AITEMS, ...); }. */ |
223 | | |
224 | | void * |
225 | | xpalloc (void *pa, idx_t *pn, idx_t n_incr_min, ptrdiff_t n_max, idx_t s) |
226 | 0 | { |
227 | 0 | idx_t n0 = *pn; |
228 | | |
229 | | /* The approximate size to use for initial small allocation |
230 | | requests. This is the largest "small" request for the GNU C |
231 | | library malloc. */ |
232 | 0 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; |
233 | | |
234 | | /* If the array is tiny, grow it to about (but no greater than) |
235 | | DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. |
236 | | Adjust the growth according to three constraints: N_INCR_MIN, |
237 | | N_MAX, and what the C language can represent safely. */ |
238 | |
|
239 | 0 | idx_t n; |
240 | 0 | if (ckd_add (&n, n0, n0 >> 1)) |
241 | 0 | n = IDX_MAX; |
242 | 0 | if (0 <= n_max && n_max < n) |
243 | 0 | n = n_max; |
244 | | |
245 | | /* NBYTES is of a type suitable for holding the count of bytes in an object. |
246 | | This is typically idx_t, but it should be size_t on (theoretical?) |
247 | | platforms where SIZE_MAX < IDX_MAX so xpalloc does not pass |
248 | | values greater than SIZE_MAX to xrealloc. */ |
249 | 0 | #if IDX_MAX <= SIZE_MAX |
250 | 0 | idx_t nbytes; |
251 | | #else |
252 | | size_t nbytes; |
253 | | #endif |
254 | 0 | idx_t adjusted_nbytes |
255 | 0 | = (ckd_mul (&nbytes, n, s) |
256 | 0 | ? MIN (IDX_MAX, SIZE_MAX) |
257 | 0 | : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0); |
258 | 0 | if (adjusted_nbytes) |
259 | 0 | { |
260 | 0 | n = adjusted_nbytes / s; |
261 | 0 | nbytes = adjusted_nbytes - adjusted_nbytes % s; |
262 | 0 | } |
263 | |
|
264 | 0 | if (! pa) |
265 | 0 | *pn = 0; |
266 | 0 | if (n - n0 < n_incr_min |
267 | 0 | && (ckd_add (&n, n0, n_incr_min) |
268 | 0 | || (0 <= n_max && n_max < n) |
269 | 0 | || ckd_mul (&nbytes, n, s))) |
270 | 0 | xalloc_die (); |
271 | 0 | pa = xrealloc (pa, nbytes); |
272 | 0 | *pn = n; |
273 | 0 | return pa; |
274 | 0 | } |
275 | | |
276 | | /* Allocate S bytes of zeroed memory dynamically, with error checking. |
277 | | There's no need for xnzalloc (N, S), since it would be equivalent |
278 | | to xcalloc (N, S). */ |
279 | | |
280 | | void * |
281 | | xzalloc (size_t s) |
282 | 0 | { |
283 | 0 | return xcalloc (s, 1); |
284 | 0 | } |
285 | | |
286 | | void * |
287 | | xizalloc (idx_t s) |
288 | 0 | { |
289 | 0 | return xicalloc (s, 1); |
290 | 0 | } |
291 | | |
292 | | /* Allocate zeroed memory for N elements of S bytes, with error |
293 | | checking. S must be nonzero. */ |
294 | | |
295 | | void * |
296 | | xcalloc (size_t n, size_t s) |
297 | 0 | { |
298 | 0 | return check_nonnull (calloc (n, s)); |
299 | 0 | } |
300 | | |
301 | | void * |
302 | | xicalloc (idx_t n, idx_t s) |
303 | 0 | { |
304 | 0 | return check_nonnull (icalloc (n, s)); |
305 | 0 | } |
306 | | |
307 | | /* Clone an object P of size S, with error checking. There's no need |
308 | | for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any |
309 | | need for an arithmetic overflow check. */ |
310 | | |
311 | | void * |
312 | | xmemdup (void const *p, size_t s) |
313 | 3.43k | { |
314 | 3.43k | return memcpy (xmalloc (s), p, s); |
315 | 3.43k | } |
316 | | |
317 | | void * |
318 | | ximemdup (void const *p, idx_t s) |
319 | 0 | { |
320 | 0 | return memcpy (ximalloc (s), p, s); |
321 | 0 | } |
322 | | |
323 | | /* Clone an object P of size S, with error checking. Append |
324 | | a terminating NUL byte. */ |
325 | | |
326 | | char * |
327 | | ximemdup0 (void const *p, idx_t s) |
328 | 0 | { |
329 | 0 | char *result = ximalloc (s + 1); |
330 | 0 | result[s] = 0; |
331 | 0 | return memcpy (result, p, s); |
332 | 0 | } |
333 | | |
334 | | /* Clone STRING. */ |
335 | | |
336 | | char * |
337 | | xstrdup (char const *string) |
338 | 3.43k | { |
339 | 3.43k | return xmemdup (string, strlen (string) + 1); |
340 | 3.43k | } |