diff options
Diffstat (limited to 'src/util/common_allocation.c')
-rw-r--r-- | src/util/common_allocation.c | 520 |
1 files changed, 0 insertions, 520 deletions
diff --git a/src/util/common_allocation.c b/src/util/common_allocation.c deleted file mode 100644 index f48f87167..000000000 --- a/src/util/common_allocation.c +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001, 2002, 2003, 2005, 2006 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file util/common_allocation.c | ||
23 | * @brief wrapper around malloc/free | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_crypto_lib.h" | ||
28 | #if HAVE_MALLOC_H | ||
29 | #include <malloc.h> | ||
30 | #endif | ||
31 | #if HAVE_MALLOC_MALLOC_H | ||
32 | #include <malloc/malloc.h> | ||
33 | #endif | ||
34 | |||
35 | #define LOG(kind, ...) \ | ||
36 | GNUNET_log_from (kind, "util-common-allocation", __VA_ARGS__) | ||
37 | |||
38 | #define LOG_STRERROR(kind, syscall) \ | ||
39 | GNUNET_log_from_strerror (kind, "util-common-allocation", syscall) | ||
40 | |||
41 | #ifndef INT_MAX | ||
42 | #define INT_MAX 0x7FFFFFFF | ||
43 | #endif | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Allocate memory. Checks the return value, aborts if no more | ||
48 | * memory is available. | ||
49 | * | ||
50 | * @param size how many bytes of memory to allocate, do NOT use | ||
51 | * this function (or GNUNET_malloc()) to allocate more than several MB | ||
52 | * of memory, if you are possibly needing a very large chunk use | ||
53 | * #GNUNET_xmalloc_unchecked_() instead. | ||
54 | * @param filename where in the code was the call to GNUNET_malloc() | ||
55 | * @param linenumber where in the code was the call to GNUNET_malloc() | ||
56 | * @return pointer to size bytes of memory | ||
57 | */ | ||
58 | void * | ||
59 | GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber) | ||
60 | { | ||
61 | void *ret; | ||
62 | |||
63 | /* As a security precaution, we generally do not allow very large | ||
64 | * allocations using the default 'GNUNET_malloc()' macro */ | ||
65 | GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); | ||
66 | ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber); | ||
67 | if (NULL == ret) | ||
68 | { | ||
69 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); | ||
70 | GNUNET_assert (0); | ||
71 | } | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Allocate memory for a two dimensional array in one block | ||
78 | * and set up pointers. Aborts if no more memory is available. | ||
79 | * Don't use GNUNET_xnew_array_2d_ directly. Use the | ||
80 | * #GNUNET_new_array_2d macro. | ||
81 | * The memory of the elements will be zero'ed out. | ||
82 | * | ||
83 | * @param n size of the first dimension | ||
84 | * @param m size of the second dimension | ||
85 | * @param elementSize size of a single element in bytes | ||
86 | * @param filename where is this call being made (for debugging) | ||
87 | * @param linenumber line where this call is being made (for debugging) | ||
88 | * @return allocated memory, never NULL | ||
89 | */ | ||
90 | void ** | ||
91 | GNUNET_xnew_array_2d_ (size_t n, | ||
92 | size_t m, | ||
93 | size_t elementSize, | ||
94 | const char *filename, | ||
95 | int linenumber) | ||
96 | { | ||
97 | /* use char pointer internally to avoid void pointer arithmetic warnings */ | ||
98 | char **ret = GNUNET_xmalloc_ (n * sizeof(void *) /* 1. dim header */ | ||
99 | + n * m * elementSize, /* element data */ | ||
100 | filename, | ||
101 | linenumber); | ||
102 | |||
103 | for (size_t i = 0; i < n; i++) | ||
104 | ret[i] = (char *) ret /* base address */ | ||
105 | + n * sizeof(void *) /* skip 1. dim header */ | ||
106 | + i * m * elementSize; /* skip to 2. dim row header */ | ||
107 | return (void **) ret; | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Allocate memory for a three dimensional array in one block | ||
113 | * and set up pointers. Aborts if no more memory is available. | ||
114 | * Don't use GNUNET_xnew_array_3d_ directly. Use the | ||
115 | * #GNUNET_new_array_3d macro. | ||
116 | * The memory of the elements will be zero'ed out. | ||
117 | * | ||
118 | * @param n size of the first dimension | ||
119 | * @param m size of the second dimension | ||
120 | * @param o size of the third dimension | ||
121 | * @param elementSize size of a single element in bytes | ||
122 | * @param filename where is this call being made (for debugging) | ||
123 | * @param linenumber line where this call is being made (for debugging) | ||
124 | * @return allocated memory, never NULL | ||
125 | */ | ||
126 | void *** | ||
127 | GNUNET_xnew_array_3d_ (size_t n, | ||
128 | size_t m, | ||
129 | size_t o, | ||
130 | size_t elementSize, | ||
131 | const char *filename, | ||
132 | int linenumber) | ||
133 | { | ||
134 | /* use char pointer internally to avoid void pointer arithmetic warnings */ | ||
135 | char ***ret = GNUNET_xmalloc_ (n * sizeof(void **) /* 1. dim header */ | ||
136 | + n * m * sizeof(void *) /* 2. dim header */ | ||
137 | + n * m * o * elementSize, /* element data */ | ||
138 | filename, | ||
139 | linenumber); | ||
140 | |||
141 | for (size_t i = 0; i < n; i++) | ||
142 | { | ||
143 | /* need to cast to (char *) temporarily for byte level accuracy */ | ||
144 | ret[i] = (char **) ((char *) ret /* base address */ | ||
145 | + n * sizeof(void **) /* skip 1. dim header */ | ||
146 | + i * m * sizeof(void *)); /* skip to 2. dim header */ | ||
147 | for (size_t j = 0; j < m; j++) | ||
148 | ret[i][j] = (char *) ret /* base address */ | ||
149 | + n * sizeof(void **) /* skip 1. dim header */ | ||
150 | + n * m * sizeof(void *) /* skip 2. dim header */ | ||
151 | + i * m * o * elementSize /* skip to 2. dim part */ | ||
152 | + j * o * elementSize; /* skip to 3. dim row data */ | ||
153 | } | ||
154 | return (void ***) ret; | ||
155 | } | ||
156 | |||
157 | |||
158 | /** | ||
159 | * Allocate and initialize memory. Checks the return value, aborts if no more | ||
160 | * memory is available. Don't use #GNUNET_xmemdup_() directly. Use the | ||
161 | * GNUNET_memdup() macro. | ||
162 | * | ||
163 | * @param buf buffer to initialize from (must contain size bytes) | ||
164 | * @param size number of bytes to allocate | ||
165 | * @param filename where is this call being made (for debugging) | ||
166 | * @param linenumber line where this call is being made (for debugging) | ||
167 | * @return allocated memory, never NULL | ||
168 | */ | ||
169 | void * | ||
170 | GNUNET_xmemdup_ (const void *buf, | ||
171 | size_t size, | ||
172 | const char *filename, | ||
173 | int linenumber) | ||
174 | { | ||
175 | void *ret; | ||
176 | |||
177 | /* As a security precaution, we generally do not allow very large | ||
178 | * allocations here */ | ||
179 | GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); | ||
180 | GNUNET_assert_at (size < INT_MAX, filename, linenumber); | ||
181 | ret = malloc (size); | ||
182 | if (ret == NULL) | ||
183 | { | ||
184 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); | ||
185 | GNUNET_assert (0); | ||
186 | } | ||
187 | GNUNET_memcpy (ret, buf, size); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | |||
192 | /** | ||
193 | * Wrapper around malloc(). Allocates size bytes of memory. | ||
194 | * The memory will be zero'ed out. | ||
195 | * | ||
196 | * @param size the number of bytes to allocate | ||
197 | * @param filename where in the code was the call to GNUNET_malloc_unchecked() | ||
198 | * @param linenumber where in the code was the call to GNUNET_malloc_unchecked() | ||
199 | * @return pointer to size bytes of memory, NULL if we do not have enough memory | ||
200 | */ | ||
201 | void * | ||
202 | GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber) | ||
203 | { | ||
204 | void *result; | ||
205 | |||
206 | (void) filename; | ||
207 | (void) linenumber; | ||
208 | |||
209 | result = malloc (size); | ||
210 | if (NULL == result) | ||
211 | return NULL; | ||
212 | memset (result, 0, size); | ||
213 | |||
214 | return result; | ||
215 | } | ||
216 | |||
217 | |||
218 | /** | ||
219 | * Reallocate memory. Checks the return value, aborts if no more | ||
220 | * memory is available. | ||
221 | * The content of the intersection of the new and old size will be unchanged. | ||
222 | * | ||
223 | * @param ptr the pointer to reallocate | ||
224 | * @param n how many bytes of memory to allocate | ||
225 | * @param filename where in the code was the call to GNUNET_realloc() | ||
226 | * @param linenumber where in the code was the call to GNUNET_realloc() | ||
227 | * @return pointer to size bytes of memory | ||
228 | */ | ||
229 | void * | ||
230 | GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) | ||
231 | { | ||
232 | (void) filename; | ||
233 | (void) linenumber; | ||
234 | |||
235 | #if defined(M_SIZE) | ||
236 | #if ENABLE_POISONING | ||
237 | { | ||
238 | uint64_t *base = ptr; | ||
239 | size_t s = M_SIZE (ptr); | ||
240 | |||
241 | if (s > n) | ||
242 | { | ||
243 | const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); | ||
244 | char *cbase = ptr; | ||
245 | |||
246 | GNUNET_memcpy (&cbase[n], | ||
247 | &baadfood, | ||
248 | GNUNET_MIN (8 - (n % 8), | ||
249 | s - n)); | ||
250 | for (size_t i = 1 + (n + 7) / 8; i < s / 8; i++) | ||
251 | base[i] = baadfood; | ||
252 | GNUNET_memcpy (&base[s / 8], | ||
253 | &baadfood, | ||
254 | s % 8); | ||
255 | } | ||
256 | } | ||
257 | #endif | ||
258 | #endif | ||
259 | ptr = realloc (ptr, n); | ||
260 | if ((NULL == ptr) && (n > 0)) | ||
261 | { | ||
262 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "realloc"); | ||
263 | GNUNET_assert (0); | ||
264 | } | ||
265 | return ptr; | ||
266 | } | ||
267 | |||
268 | |||
269 | #if __BYTE_ORDER == __LITTLE_ENDIAN | ||
270 | #define BAADFOOD_STR "\x0D\xF0\xAD\xBA" | ||
271 | #endif | ||
272 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
273 | #define BAADFOOD_STR "\xBA\xAD\xF0\x0D" | ||
274 | #endif | ||
275 | |||
276 | #if HAVE_MALLOC_NP_H | ||
277 | #include <malloc_np.h> | ||
278 | #endif | ||
279 | #if HAVE_MALLOC_USABLE_SIZE | ||
280 | #define M_SIZE(p) malloc_usable_size (p) | ||
281 | #elif HAVE_MALLOC_SIZE | ||
282 | #define M_SIZE(p) malloc_size (p) | ||
283 | #endif | ||
284 | |||
285 | /** | ||
286 | * Free memory. Merely a wrapper for the case that we | ||
287 | * want to keep track of allocations. | ||
288 | * | ||
289 | * @param ptr the pointer to free | ||
290 | * @param filename where in the code was the call to GNUNET_free() | ||
291 | * @param linenumber where in the code was the call to GNUNET_free() | ||
292 | */ | ||
293 | void | ||
294 | GNUNET_xfree_ (void *ptr, | ||
295 | const char *filename, | ||
296 | int linenumber) | ||
297 | { | ||
298 | if (NULL == ptr) | ||
299 | return; | ||
300 | #if defined(M_SIZE) | ||
301 | #if ENABLE_POISONING | ||
302 | { | ||
303 | const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); | ||
304 | uint64_t *base = ptr; | ||
305 | size_t s = M_SIZE (ptr); | ||
306 | |||
307 | for (size_t i = 0; i < s / 8; i++) | ||
308 | base[i] = baadfood; | ||
309 | GNUNET_memcpy (&base[s / 8], &baadfood, s % 8); | ||
310 | } | ||
311 | #endif | ||
312 | #endif | ||
313 | free (ptr); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Dup a string (same semantics as strdup). | ||
319 | * | ||
320 | * @param str the string to dup | ||
321 | * @param filename where in the code was the call to GNUNET_strdup() | ||
322 | * @param linenumber where in the code was the call to GNUNET_strdup() | ||
323 | * @return `strdup(@a str)` | ||
324 | */ | ||
325 | char * | ||
326 | GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber) | ||
327 | { | ||
328 | char *res; | ||
329 | size_t slen; | ||
330 | |||
331 | GNUNET_assert_at (str != NULL, filename, linenumber); | ||
332 | slen = strlen (str) + 1; | ||
333 | res = GNUNET_xmalloc_ (slen, filename, linenumber); | ||
334 | GNUNET_memcpy (res, str, slen); | ||
335 | return res; | ||
336 | } | ||
337 | |||
338 | |||
339 | #if ! HAVE_STRNLEN | ||
340 | static size_t | ||
341 | strnlen (const char *s, size_t n) | ||
342 | { | ||
343 | const char *e; | ||
344 | |||
345 | e = memchr (s, '\0', n); | ||
346 | if (NULL == e) | ||
347 | return n; | ||
348 | return e - s; | ||
349 | } | ||
350 | |||
351 | |||
352 | #endif | ||
353 | |||
354 | |||
355 | /** | ||
356 | * Dup partially a string (same semantics as strndup). | ||
357 | * | ||
358 | * @param str the string to dup | ||
359 | * @param len the length of the string to dup | ||
360 | * @param filename where in the code was the call to GNUNET_strndup() | ||
361 | * @param linenumber where in the code was the call to GNUNET_strndup() | ||
362 | * @return `strndup(@a str,@a len)` | ||
363 | */ | ||
364 | char * | ||
365 | GNUNET_xstrndup_ (const char *str, | ||
366 | size_t len, | ||
367 | const char *filename, | ||
368 | int linenumber) | ||
369 | { | ||
370 | char *res; | ||
371 | |||
372 | if (0 == len) | ||
373 | return GNUNET_strdup (""); | ||
374 | GNUNET_assert_at (NULL != str, filename, linenumber); | ||
375 | len = strnlen (str, len); | ||
376 | res = GNUNET_xmalloc_ (len + 1, filename, linenumber); | ||
377 | GNUNET_memcpy (res, str, len); | ||
378 | /* res[len] = '\0'; 'malloc' zeros out anyway */ | ||
379 | return res; | ||
380 | } | ||
381 | |||
382 | |||
383 | /** | ||
384 | * Grow an array. Grows old by (*oldCount-newCount)*elementSize bytes | ||
385 | * and sets *oldCount to newCount. | ||
386 | * | ||
387 | * @param old address of the pointer to the array | ||
388 | * *old may be NULL | ||
389 | * @param elementSize the size of the elements of the array | ||
390 | * @param oldCount address of the number of elements in the *old array | ||
391 | * @param newCount number of elements in the new array, may be 0 | ||
392 | * @param filename where in the code was the call to GNUNET_array_grow() | ||
393 | * @param linenumber where in the code was the call to GNUNET_array_grow() | ||
394 | */ | ||
395 | void | ||
396 | GNUNET_xgrow_ (void **old, | ||
397 | size_t elementSize, | ||
398 | unsigned int *oldCount, | ||
399 | unsigned int newCount, | ||
400 | const char *filename, | ||
401 | int linenumber) | ||
402 | { | ||
403 | void *tmp; | ||
404 | size_t size; | ||
405 | |||
406 | GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber); | ||
407 | size = newCount * elementSize; | ||
408 | if (0 == size) | ||
409 | { | ||
410 | tmp = NULL; | ||
411 | } | ||
412 | else | ||
413 | { | ||
414 | tmp = GNUNET_xmalloc_ (size, filename, linenumber); | ||
415 | if (NULL != *old) | ||
416 | { | ||
417 | GNUNET_memcpy (tmp, *old, elementSize * GNUNET_MIN (*oldCount, newCount)); | ||
418 | } | ||
419 | } | ||
420 | |||
421 | if (NULL != *old) | ||
422 | { | ||
423 | GNUNET_xfree_ (*old, filename, linenumber); | ||
424 | } | ||
425 | *old = tmp; | ||
426 | *oldCount = newCount; | ||
427 | } | ||
428 | |||
429 | |||
430 | /** | ||
431 | * Like asprintf(), just portable. | ||
432 | * | ||
433 | * @param buf set to a buffer of sufficient size (allocated, caller must free) | ||
434 | * @param format format string (see printf(), fprintf(), etc.) | ||
435 | * @param ... data for format string | ||
436 | * @return number of bytes in `*@a buf`, excluding 0-termination | ||
437 | */ | ||
438 | int | ||
439 | GNUNET_asprintf (char **buf, const char *format, ...) | ||
440 | { | ||
441 | int ret; | ||
442 | va_list args; | ||
443 | |||
444 | va_start (args, format); | ||
445 | ret = vsnprintf (NULL, 0, format, args); | ||
446 | va_end (args); | ||
447 | GNUNET_assert (ret >= 0); | ||
448 | *buf = GNUNET_malloc (ret + 1); | ||
449 | va_start (args, format); | ||
450 | ret = vsprintf (*buf, format, args); | ||
451 | va_end (args); | ||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Like snprintf(), just aborts if the buffer is of insufficient size. | ||
458 | * | ||
459 | * @param buf pointer to buffer that is written to | ||
460 | * @param size number of bytes in buf | ||
461 | * @param format format strings | ||
462 | * @param ... data for format string | ||
463 | * @return number of bytes written to buf or negative value on error | ||
464 | */ | ||
465 | int | ||
466 | GNUNET_snprintf (char *buf, size_t size, const char *format, ...) | ||
467 | { | ||
468 | int ret; | ||
469 | va_list args; | ||
470 | |||
471 | va_start (args, format); | ||
472 | ret = vsnprintf (buf, size, format, args); | ||
473 | va_end (args); | ||
474 | GNUNET_assert ((ret >= 0) && (((size_t) ret) < size)); | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Create a copy of the given message. | ||
481 | * | ||
482 | * @param msg message to copy | ||
483 | * @return duplicate of the message | ||
484 | */ | ||
485 | struct GNUNET_MessageHeader * | ||
486 | GNUNET_copy_message (const struct GNUNET_MessageHeader *msg) | ||
487 | { | ||
488 | struct GNUNET_MessageHeader *ret; | ||
489 | uint16_t msize; | ||
490 | |||
491 | msize = ntohs (msg->size); | ||
492 | GNUNET_assert (msize >= sizeof(struct GNUNET_MessageHeader)); | ||
493 | ret = GNUNET_malloc (msize); | ||
494 | GNUNET_memcpy (ret, msg, msize); | ||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | |||
499 | /** | ||
500 | * Check that memory in @a a is all zeros. @a a must be a pointer. | ||
501 | * | ||
502 | * @param a pointer to @a n bytes which should be tested for the | ||
503 | * entire memory being zero'ed out. | ||
504 | * @param n number of bytes in @a to be tested | ||
505 | * @return GNUNET_YES if a is zero, GNUNET_NO otherwise | ||
506 | */ | ||
507 | enum GNUNET_GenericReturnValue | ||
508 | GNUNET_is_zero_ (const void *a, | ||
509 | size_t n) | ||
510 | { | ||
511 | const char *b = a; | ||
512 | |||
513 | for (size_t i = 0; i < n; i++) | ||
514 | if (b[i]) | ||
515 | return GNUNET_NO; | ||
516 | return GNUNET_YES; | ||
517 | } | ||
518 | |||
519 | |||
520 | /* end of common_allocation.c */ | ||