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