GNUnet  0.20.0
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 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 
59 void *
60 GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber)
61 {
62  void *ret;
63 
64  /* As a security precaution, we generally do not allow very large
65  * allocations using the default 'GNUNET_malloc()' macro */
67  ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber);
68  if (NULL == ret)
69  {
71  GNUNET_assert (0);
72  }
73  return ret;
74 }
75 
76 
91 void **
93  size_t m,
94  size_t elementSize,
95  const char *filename,
96  int linenumber)
97 {
98  /* use char pointer internally to avoid void pointer arithmetic warnings */
99  char **ret = GNUNET_xmalloc_ (n * sizeof(void *) /* 1. dim header */
100  + n * m * elementSize, /* element data */
101  filename,
102  linenumber);
103 
104  for (size_t i = 0; i < n; i++)
105  ret[i] = (char *) ret /* base address */
106  + n * sizeof(void *) /* skip 1. dim header */
107  + i * m * elementSize; /* skip to 2. dim row header */
108  return (void **) ret;
109 }
110 
111 
127 void ***
129  size_t m,
130  size_t o,
131  size_t elementSize,
132  const char *filename,
133  int linenumber)
134 {
135  /* use char pointer internally to avoid void pointer arithmetic warnings */
136  char ***ret = GNUNET_xmalloc_ (n * sizeof(void **) /* 1. dim header */
137  + n * m * sizeof(void *) /* 2. dim header */
138  + n * m * o * elementSize, /* element data */
139  filename,
140  linenumber);
141 
142  for (size_t i = 0; i < n; i++)
143  {
144  /* need to cast to (char *) temporarily for byte level accuracy */
145  ret[i] = (char **) ((char *) ret /* base address */
146  + n * sizeof(void **) /* skip 1. dim header */
147  + i * m * sizeof(void *)); /* skip to 2. dim header */
148  for (size_t j = 0; j < m; j++)
149  ret[i][j] = (char *) ret /* base address */
150  + n * sizeof(void **) /* skip 1. dim header */
151  + n * m * sizeof(void *) /* skip 2. dim header */
152  + i * m * o * elementSize /* skip to 2. dim part */
153  + j * o * elementSize; /* skip to 3. dim row data */
154  }
155  return (void ***) ret;
156 }
157 
158 
159 void *
160 GNUNET_xmemdup_ (const void *buf,
161  size_t size,
162  const char *filename,
163  int linenumber)
164 {
165  void *ret;
166 
167  /* As a security precaution, we generally do not allow very large
168  * allocations here */
170  GNUNET_assert_at (size < INT_MAX, filename, linenumber);
171  ret = malloc (size);
172  if (ret == NULL)
173  {
175  GNUNET_assert (0);
176  }
178  return ret;
179 }
180 
181 
191 void *
192 GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber)
193 {
194  void *result;
195 
196  (void) filename;
197  (void) linenumber;
198 
199  result = malloc (size);
200  if (NULL == result)
201  return NULL;
202  memset (result, 0, size);
203 
204  return result;
205 }
206 
207 
219 void *
220 GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber)
221 {
222  (void) filename;
223  (void) linenumber;
224 
225 #if defined(M_SIZE)
226 #if ENABLE_POISONING
227  {
228  uint64_t *base = ptr;
229  size_t s = M_SIZE (ptr);
230 
231  if (s > n)
232  {
233  const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
234  char *cbase = ptr;
235 
236  GNUNET_memcpy (&cbase[n],
237  &baadfood,
238  GNUNET_MIN (8 - (n % 8),
239  s - n));
240  for (size_t i = 1 + (n + 7) / 8; i < s / 8; i++)
241  base[i] = baadfood;
242  GNUNET_memcpy (&base[s / 8],
243  &baadfood,
244  s % 8);
245  }
246  }
247 #endif
248 #endif
249  ptr = realloc (ptr, n);
250  if ((NULL == ptr) && (n > 0))
251  {
253  GNUNET_assert (0);
254  }
255  return ptr;
256 }
257 
258 
259 #if __BYTE_ORDER == __LITTLE_ENDIAN
260 #define BAADFOOD_STR "\x0D\xF0\xAD\xBA"
261 #endif
262 #if __BYTE_ORDER == __BIG_ENDIAN
263 #define BAADFOOD_STR "\xBA\xAD\xF0\x0D"
264 #endif
265 
266 #if HAVE_MALLOC_NP_H
267 #include <malloc_np.h>
268 #endif
269 #if HAVE_MALLOC_USABLE_SIZE
270 #define M_SIZE(p) malloc_usable_size (p)
271 #elif HAVE_MALLOC_SIZE
272 #define M_SIZE(p) malloc_size (p)
273 #endif
274 
283 void
284 GNUNET_xfree_ (void *ptr,
285  const char *filename,
286  int linenumber)
287 {
288  if (NULL == ptr)
289  return;
290 #if defined(M_SIZE)
291 #if ENABLE_POISONING
292  {
293  const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
294  uint64_t *base = ptr;
295  size_t s = M_SIZE (ptr);
296 
297  for (size_t i = 0; i < s / 8; i++)
298  base[i] = baadfood;
299  GNUNET_memcpy (&base[s / 8], &baadfood, s % 8);
300  }
301 #endif
302 #endif
303  free (ptr);
304 }
305 
306 
315 char *
316 GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber)
317 {
318  char *res;
319  size_t slen;
320 
321  GNUNET_assert_at (str != NULL, filename, linenumber);
322  slen = strlen (str) + 1;
323  res = GNUNET_xmalloc_ (slen, filename, linenumber);
324  GNUNET_memcpy (res, str, slen);
325  return res;
326 }
327 
328 
329 #if ! HAVE_STRNLEN
330 static size_t
331 strnlen (const char *s, size_t n)
332 {
333  const char *e;
334 
335  e = memchr (s, '\0', n);
336  if (NULL == e)
337  return n;
338  return e - s;
339 }
340 
341 
342 #endif
343 
344 
354 char *
355 GNUNET_xstrndup_ (const char *str,
356  size_t len,
357  const char *filename,
358  int linenumber)
359 {
360  char *res;
361 
362  if (0 == len)
363  return GNUNET_strdup ("");
364  GNUNET_assert_at (NULL != str, filename, linenumber);
365  len = strnlen (str, len);
366  res = GNUNET_xmalloc_ (len + 1, filename, linenumber);
367  GNUNET_memcpy (res, str, len);
368  /* res[len] = '\0'; 'malloc' zeros out anyway */
369  return res;
370 }
371 
372 
385 void
386 GNUNET_xgrow_ (void **old,
387  size_t elementSize,
388  unsigned int *oldCount,
389  unsigned int newCount,
390  const char *filename,
391  int linenumber)
392 {
393  void *tmp;
394  size_t size;
395 
396  GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
397  size = newCount * elementSize;
398  if (0 == size)
399  {
400  tmp = NULL;
401  }
402  else
403  {
404  tmp = GNUNET_xmalloc_ (size, filename, linenumber);
405  if (NULL != *old)
406  {
407  GNUNET_memcpy (tmp, *old, elementSize * GNUNET_MIN (*oldCount, newCount));
408  }
409  }
410 
411  if (NULL != *old)
412  {
413  GNUNET_xfree_ (*old, filename, linenumber);
414  }
415  *old = tmp;
416  *oldCount = newCount;
417 }
418 
419 
428 int
429 GNUNET_asprintf (char **buf, const char *format, ...)
430 {
431  int ret;
432  va_list args;
433 
434  va_start (args, format);
435  ret = vsnprintf (NULL, 0, format, args);
436  va_end (args);
437  GNUNET_assert (ret >= 0);
438  *buf = GNUNET_malloc (ret + 1);
439  va_start (args, format);
440  ret = vsprintf (*buf, format, args);
441  va_end (args);
442  return ret;
443 }
444 
445 
455 int
456 GNUNET_snprintf (char *buf, size_t size, const char *format, ...)
457 {
458  int ret;
459  va_list args;
460 
461  va_start (args, format);
462  ret = vsnprintf (buf, size, format, args);
463  va_end (args);
464  GNUNET_assert ((ret >= 0) && (((size_t) ret) < size));
465  return ret;
466 }
467 
468 
469 struct GNUNET_MessageHeader *
471 {
472  struct GNUNET_MessageHeader *ret;
473  uint16_t msize;
474 
475  msize = ntohs (msg->size);
476  GNUNET_assert (msize >= sizeof(struct GNUNET_MessageHeader));
477  ret = GNUNET_malloc (msize);
478  GNUNET_memcpy (ret, msg, msize);
479  return ret;
480 }
481 
482 
492 GNUNET_is_zero_ (const void *a,
493  size_t n)
494 {
495  const char *b = a;
496 
497  for (size_t i = 0; i < n; i++)
498  if (b[i])
499  return GNUNET_NO;
500  return GNUNET_YES;
501 }
502 
503 
504 /* 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,...)
Like snprintf(), just aborts if the buffer is of insufficient size.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf(), just portable.
#define LOG_STRERROR(kind, syscall)
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static struct Experiment * e
static int res
static char * filename
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static int result
Global testing status.
static char buf[2048]
enum GNUNET_GenericReturnValue GNUNET_is_zero_(const void *a, size_t n)
Check that memory in a is all zeros.
char * GNUNET_xstrdup_(const char *str, const char *filename, int linenumber)
Dup a string (same semantics as strdup).
void * GNUNET_xrealloc_(void *ptr, size_t n, const char *filename, int linenumber)
Reallocate memory.
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.
void GNUNET_xgrow_(void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber)
Grow an array.
void * GNUNET_xmalloc_(size_t size, const char *filename, int linenumber)
Allocate memory.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
void GNUNET_xfree_(void *ptr, const char *filename, int linenumber)
Free memory.
void * GNUNET_xmemdup_(const void *buf, size_t size, const char *filename, int linenumber)
Allocate and initialize memory.
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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
char * GNUNET_xstrndup_(const char *str, size_t len, const char *filename, int linenumber)
Dup partially a string (same semantics as strndup).
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_MIN(a, b)
void * GNUNET_xmalloc_unchecked_(size_t size, const char *filename, int linenumber)
Wrapper around malloc().
@ GNUNET_YES
@ GNUNET_NO
#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.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
static unsigned int size
Size of the "table".
Definition: peer.c:68
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.