GNUnet 0.21.2
common_allocation.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2005, 2006, 2024 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
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#if HAVE_MALLOC_H
30#include <malloc.h>
31#endif
32#if HAVE_MALLOC_MALLOC_H
33#include <malloc/malloc.h>
34#endif
35
36#define LOG(kind, ...) \
37 GNUNET_log_from (kind, "util-common-allocation", __VA_ARGS__)
38
39#define LOG_STRERROR(kind, syscall) \
40 GNUNET_log_from_strerror (kind, "util-common-allocation", syscall)
41
42#ifndef INT_MAX
43#define INT_MAX 0x7FFFFFFF
44#endif
45
46
47void *
49 const char *filename,
50 int linenumber)
51{
52 void *ret;
53
54 /* As a security precaution, we generally do not allow very large
55 * allocations using the default 'GNUNET_malloc()' macro */
58 linenumber);
61 linenumber);
62 if (NULL == ret)
63 {
65 "malloc");
66 GNUNET_assert (0);
67 }
68 return ret;
69}
70
71
72void **
74 size_t m,
75 size_t elementSize,
76 const char *filename,
77 int linenumber)
78{
79 /* use char pointer internally to avoid void pointer arithmetic warnings */
80 char **ret = GNUNET_xmalloc_ (n * sizeof(void *) /* 1. dim header */
81 + n * m * elementSize, /* element data */
83 linenumber);
84
85 for (size_t i = 0; i < n; i++)
86 ret[i] = (char *) ret /* base address */
87 + n * sizeof(void *) /* skip 1. dim header */
88 + i * m * elementSize; /* skip to 2. dim row header */
89 return (void **) ret;
90}
91
92
93void ***
95 size_t m,
96 size_t o,
97 size_t elementSize,
98 const char *filename,
99 int linenumber)
100{
101 /* use char pointer internally to avoid void pointer arithmetic warnings */
102 char ***ret = GNUNET_xmalloc_ (n * sizeof(void **) /* 1. dim header */
103 + n * m * sizeof(void *) /* 2. dim header */
104 + n * m * o * elementSize, /* element data */
105 filename,
106 linenumber);
107
108 for (size_t i = 0; i < n; i++)
109 {
110 /* need to cast to (char *) temporarily for byte level accuracy */
111 ret[i] = (char **) ((char *) ret /* base address */
112 + n * sizeof(void **) /* skip 1. dim header */
113 + i * m * sizeof(void *)); /* skip to 2. dim header */
114 for (size_t j = 0; j < m; j++)
115 ret[i][j] = (char *) ret /* base address */
116 + n * sizeof(void **) /* skip 1. dim header */
117 + n * m * sizeof(void *) /* skip 2. dim header */
118 + i * m * o * elementSize /* skip to 2. dim part */
119 + j * o * elementSize; /* skip to 3. dim row data */
120 }
121 return (void ***) ret;
122}
123
124
125void *
126GNUNET_xmemdup_ (const void *buf,
127 size_t size,
128 const char *filename,
129 int linenumber)
130{
131 void *ret;
132
133 /* As a security precaution, we generally do not allow very large
134 * allocations here */
136 filename,
137 linenumber);
139 filename,
140 linenumber);
141 ret = malloc (size);
142 if (NULL == ret)
143 {
145 "malloc");
146 GNUNET_assert (0);
147 }
149 buf,
150 size);
151 return ret;
152}
153
154
155void *
157 const char *filename,
158 int linenumber)
159{
160 void *result;
161
162 (void) filename;
163 (void) linenumber;
164 result = malloc (size);
165 if (NULL == result)
166 return NULL;
167 memset (result,
168 0,
169 size);
170 return result;
171}
172
173
174void *
176 size_t n,
177 const char *filename,
178 int linenumber)
179{
180 (void) filename;
181 (void) linenumber;
182
183#if defined(M_SIZE)
184#if ENABLE_POISONING
185 {
186 uint64_t *base = ptr;
187 size_t s = M_SIZE (ptr);
188
189 if (s > n)
190 {
191 const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
192 char *cbase = ptr;
193
194 GNUNET_memcpy (&cbase[n],
195 &baadfood,
196 GNUNET_MIN (8 - (n % 8),
197 s - n));
198 for (size_t i = 1 + (n + 7) / 8; i < s / 8; i++)
199 base[i] = baadfood;
200 GNUNET_memcpy (&base[s / 8],
201 &baadfood,
202 s % 8);
203 }
204 }
205#endif
206#endif
207 ptr = realloc (ptr, n);
208 if ((NULL == ptr) && (n > 0))
209 {
211 "realloc");
212 GNUNET_assert (0);
213 }
214 return ptr;
215}
216
217
218#if __BYTE_ORDER == __LITTLE_ENDIAN
219#define BAADFOOD_STR "\x0D\xF0\xAD\xBA"
220#endif
221#if __BYTE_ORDER == __BIG_ENDIAN
222#define BAADFOOD_STR "\xBA\xAD\xF0\x0D"
223#endif
224
225#if HAVE_MALLOC_NP_H
226#include <malloc_np.h>
227#endif
228#if HAVE_MALLOC_USABLE_SIZE
229#define M_SIZE(p) malloc_usable_size (p)
230#elif HAVE_MALLOC_SIZE
231#define M_SIZE(p) malloc_size (p)
232#endif
233
234void
235GNUNET_xfree_ (void *ptr,
236 const char *filename,
237 int linenumber)
238{
239 if (NULL == ptr)
240 return;
241#if defined(M_SIZE)
242#if ENABLE_POISONING
243 {
244 const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
245 uint64_t *base = ptr;
246 size_t s = M_SIZE (ptr);
247
248 for (size_t i = 0; i < s / 8; i++)
249 base[i] = baadfood;
250 GNUNET_memcpy (&base[s / 8], &baadfood, s % 8);
251 }
252#endif
253#endif
254 free (ptr);
255}
256
257
258char *
259GNUNET_xstrdup_ (const char *str,
260 const char *filename,
261 int linenumber)
262{
263 size_t slen = strlen (str) + 1;
264 char *res;
265
266 GNUNET_assert_at (str != NULL,
267 filename,
268 linenumber);
269 res = GNUNET_xmalloc_ (slen,
270 filename,
271 linenumber);
273 str,
274 slen);
275 return res;
276}
277
278
279#if ! HAVE_STRNLEN
280static size_t
281strnlen (const char *s,
282 size_t n)
283{
284 const char *e;
285
286 e = memchr (s,
287 '\0',
288 n);
289 if (NULL == e)
290 return n;
291 return e - s;
292}
293
294
295#endif
296
297
298char *
299GNUNET_xstrndup_ (const char *str,
300 size_t len,
301 const char *filename,
302 int linenumber)
303{
304 char *res;
305
306 if (0 == len)
307 return GNUNET_strdup ("");
308 GNUNET_assert_at (NULL != str,
309 filename,
310 linenumber);
311 len = strnlen (str, len);
312 res = GNUNET_xmalloc_ (len + 1,
313 filename,
314 linenumber);
315 GNUNET_memcpy (res, str, len);
316 /* res[len] = '\0'; 'malloc' zeros out anyway */
317 return res;
318}
319
320
321void
322GNUNET_xgrow_ (void **old,
323 size_t elementSize,
324 unsigned int *oldCount,
325 unsigned int newCount,
326 const char *filename,
327 int linenumber)
328{
329 void *tmp;
330 size_t size;
331
332 GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
333 size = newCount * elementSize;
334 if (0 == size)
335 {
336 tmp = NULL;
337 }
338 else
339 {
340 tmp = GNUNET_xmalloc_ (size,
341 filename,
342 linenumber);
343 if (NULL != *old)
344 {
345 GNUNET_memcpy (tmp,
346 *old,
347 elementSize * GNUNET_MIN (*oldCount,
348 newCount));
349 }
350 }
351
352 if (NULL != *old)
353 {
354 GNUNET_xfree_ (*old,
355 filename,
356 linenumber);
357 }
358 *old = tmp;
359 *oldCount = newCount;
360}
361
362
363int
364GNUNET_asprintf (char **buf,
365 const char *format,
366 ...)
367{
368 int ret;
369 va_list args;
370
371 va_start (args,
372 format);
373 ret = vsnprintf (NULL,
374 0,
375 format,
376 args);
377 va_end (args);
378 GNUNET_assert (ret >= 0);
379 *buf = GNUNET_malloc (ret + 1);
380 va_start (args, format);
381 ret = vsprintf (*buf,
382 format,
383 args);
384 va_end (args);
385 return ret;
386}
387
388
389int
391 size_t size,
392 const char *format,
393 ...)
394{
395 int ret;
396 va_list args;
397
398 va_start (args,
399 format);
400 ret = vsnprintf (buf,
401 size,
402 format,
403 args);
404 va_end (args);
405 GNUNET_assert ((ret >= 0) && (((size_t) ret) < size));
406 return ret;
407}
408
409
412{
414 uint16_t msize;
415
416 msize = ntohs (msg->size);
417 GNUNET_assert (msize >= sizeof(struct GNUNET_MessageHeader));
418 ret = GNUNET_malloc (msize);
419 GNUNET_memcpy (ret, msg, msize);
420 return ret;
421}
422
423
424bool
425GNUNET_is_zero_ (const void *a,
426 size_t n)
427{
428 const char *b = a;
429
430 for (size_t i = 0; i < n; i++)
431 if (b[i])
432 return false;
433 return true;
434}
435
436
437/* end of common_allocation.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static size_t strnlen(const char *s, size_t n)
#define INT_MAX
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
int GNUNET_asprintf(char **buf, const char *format,...)
#define LOG_STRERROR(kind, syscall)
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static int ret
Final status code.
Definition: gnunet-arm.c:94
static char * filename
static char * res
Currently read line or NULL on EOF.
static int result
Global testing status.
char * GNUNET_xstrndup_(const char *str, size_t len, const char *filename, int linenumber)
Dup partially a string.
void GNUNET_xgrow_(void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber)
Grow an array, the new elements are zeroed out.
char * GNUNET_xstrdup_(const char *str, const char *filename, int linenumber)
Dup a string.
void ** GNUNET_xnew_array_2d_(size_t n, size_t m, size_t elementSize, const char *filename, int linenumber)
Allocate memory for a two dimensional array in one block and set up pointers.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
void * GNUNET_xmalloc_unchecked_(size_t size, const char *filename, int linenumber)
Allocate memory.
void GNUNET_xfree_(void *ptr, const char *filename, int linenumber)
Free memory.
void * GNUNET_xrealloc_(void *ptr, size_t n, const char *filename, int linenumber)
Reallocate memory.
void * GNUNET_xmalloc_(size_t size, const char *filename, int linenumber)
Allocate memory.
bool GNUNET_is_zero_(const void *a, size_t n)
Check that memory in a is all zeros.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
void *** GNUNET_xnew_array_3d_(size_t n, size_t m, size_t o, size_t elementSize, const char *filename, int linenumber)
Allocate memory for a three dimensional array in one block and set up pointers.
void * GNUNET_xmemdup_(const void *buf, size_t size, const char *filename, int linenumber)
Allocate and initialize memory.
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_assert_at(cond, f, l)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
#define GNUNET_malloc(size)
Wrapper around malloc.
static unsigned int size
Size of the "table".
Definition: peer.c:68
Header for all communications.