GNUnet  0.10.x
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 
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,...) GNUNET_log_from (kind, "util-common-allocation",__VA_ARGS__)
36 
37 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-common-allocation", syscall)
38 
39 #ifndef INT_MAX
40 #define INT_MAX 0x7FFFFFFF
41 #endif
42 
43 #if 0
44 #define W32_MEM_LIMIT 200000000
45 #endif
46 
47 #ifdef W32_MEM_LIMIT
48 static LONG mem_used = 0;
49 #endif
50 
63 void *
65  const char *filename,
66  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 */
73  filename,
74  linenumber);
75  ret = GNUNET_xmalloc_unchecked_ (size,
76  filename,
77  linenumber);
78  if (NULL == ret)
79  {
81  "malloc");
82  GNUNET_assert (0);
83  }
84  return ret;
85 }
86 
87 
102 void **
104  size_t m,
105  size_t elementSize,
106  const char *filename,
107  int linenumber)
108 {
109  /* use char pointer internally to avoid void pointer arithmetic warnings */
110  char **ret = GNUNET_xmalloc_ (n * sizeof (void *) + /* 1. dim header */
111  n * m * elementSize, /* element data */
112  filename, linenumber);
113 
114  for (size_t i = 0; i < n; i++)
115  ret[i] = (char *)ret + /* base address */
116  n * sizeof (void *) + /* skip 1. dim header */
117  i * m * elementSize; /* skip to 2. dim row header */
118  return (void **)ret;
119 }
120 
121 
137 void ***
138 GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize,
139  const char *filename, 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, linenumber);
146 
147  for (size_t i = 0; i < n; i++)
148  {
149  /* need to cast to (char *) temporarily for byte level acuracy */
150  ret[i] = (char **)((char *)ret + /* base address */
151  n * sizeof (void **) + /* skip 1. dim header */
152  i * m * sizeof (void *)); /* skip to 2. dim header */
153  for (size_t j = 0; j < m; j++)
154  ret[i][j] = (char *)ret + /* base address */
155  n * sizeof (void **) + /* skip 1. dim header */
156  n * m * sizeof (void *) + /* skip 2. dim header */
157  i * m * o * elementSize + /* skip to 2. dim part */
158  j * o * elementSize; /* skip to 3. dim row data */
159  }
160  return (void ***)ret;
161 }
162 
163 
175 void *
176 GNUNET_xmemdup_ (const void *buf,
177  size_t size,
178  const char *filename,
179  int linenumber)
180 {
181  void *ret;
182 
183  /* As a security precaution, we generally do not allow very large
184  * allocations here */
185  GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber);
186 #ifdef W32_MEM_LIMIT
187  size += sizeof (size_t);
188  if (mem_used + size > W32_MEM_LIMIT)
189  return NULL;
190 #endif
191  GNUNET_assert_at (size < INT_MAX, filename, linenumber);
192  ret = malloc (size);
193  if (ret == NULL)
194  {
196  GNUNET_assert (0);
197  }
198 #ifdef W32_MEM_LIMIT
199  *((size_t *) ret) = size;
200  ret = &((size_t *) ret)[1];
201  mem_used += size;
202 #endif
203  GNUNET_memcpy (ret, buf, size);
204  return ret;
205 }
206 
207 
217 void *
219  const char *filename,
220  int linenumber)
221 {
222  void *result;
223 
224  (void) filename;
225  (void) linenumber;
226 #ifdef W32_MEM_LIMIT
227  size += sizeof (size_t);
228  if (mem_used + size > W32_MEM_LIMIT)
229  return NULL;
230 #endif
231 
232  result = malloc (size);
233  if (NULL == result)
234  return NULL;
235  memset (result, 0, size);
236 
237 #ifdef W32_MEM_LIMIT
238  *((size_t *) result) = size;
239  result = &((size_t *) result)[1];
240  mem_used += size;
241 #endif
242 
243  return result;
244 }
245 
246 
258 void *
259 GNUNET_xrealloc_ (void *ptr,
260  size_t n,
261  const char *filename,
262  int linenumber)
263 {
264  (void) filename;
265  (void) linenumber;
266 
267 #ifdef W32_MEM_LIMIT
268  n += sizeof (size_t);
269  ptr = &((size_t *) ptr)[-1];
270  mem_used = mem_used - *((size_t *) ptr) + n;
271 #endif
272  ptr = realloc (ptr, n);
273  if ((NULL == ptr) && (n > 0))
274  {
276  "realloc");
277  GNUNET_assert (0);
278  }
279 #ifdef W32_MEM_LIMIT
280  ptr = &((size_t *) ptr)[1];
281 #endif
282  return ptr;
283 }
284 
285 
286 # if __BYTE_ORDER == __LITTLE_ENDIAN
287 #define BAADFOOD_STR "\x0D\xF0\xAD\xBA"
288 #endif
289 # if __BYTE_ORDER == __BIG_ENDIAN
290 #define BAADFOOD_STR "\xBA\xAD\xF0\x0D"
291 #endif
292 
293 #if WINDOWS
294 #define M_SIZE(p) _msize (p)
295 #endif
296 #if HAVE_MALLOC_NP_H
297 #include <malloc_np.h>
298 #endif
299 #if HAVE_MALLOC_USABLE_SIZE
300 #define M_SIZE(p) malloc_usable_size (p)
301 #elif HAVE_MALLOC_SIZE
302 #define M_SIZE(p) malloc_size (p)
303 #endif
304 
313 void
314 GNUNET_xfree_ (void *ptr,
315  const char *filename,
316  int linenumber)
317 {
318  GNUNET_assert_at (NULL != ptr,
319  filename,
320  linenumber);
321 #ifdef W32_MEM_LIMIT
322  ptr = &((size_t *) ptr)[-1];
323  mem_used -= *((size_t *) ptr);
324 #endif
325 #if defined(M_SIZE)
326 #if ENABLE_POISONING
327  {
328  const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
329  uint64_t *base = ptr;
330  size_t s = M_SIZE (ptr);
331  size_t i;
332 
333  for (i=0;i<s/8;i++)
334  base[i] = baadfood;
335  GNUNET_memcpy (&base[s/8], &baadfood, s % 8);
336  }
337 #endif
338 #endif
339  free (ptr);
340 }
341 
342 
351 char *
352 GNUNET_xstrdup_ (const char *str,
353  const char *filename,
354  int linenumber)
355 {
356  char *res;
357  size_t slen;
358 
359  GNUNET_assert_at (str != NULL,
360  filename,
361  linenumber);
362  slen = strlen (str) + 1;
363  res = GNUNET_xmalloc_ (slen,
364  filename,
365  linenumber);
366  GNUNET_memcpy (res,
367  str,
368  slen);
369  return res;
370 }
371 
372 
373 #if ! HAVE_STRNLEN
374 static size_t
375 strnlen (const char *s,
376  size_t n)
377 {
378  const char *e;
379 
380  e = memchr (s, '\0', n);
381  if (NULL == e)
382  return n;
383  return e - s;
384 }
385 #endif
386 
387 
397 char *
398 GNUNET_xstrndup_ (const char *str,
399  size_t len,
400  const char *filename,
401  int linenumber)
402 {
403  char *res;
404 
405  if (0 == len)
406  return GNUNET_strdup ("");
407  GNUNET_assert_at (NULL != str,
408  filename,
409  linenumber);
410  len = strnlen (str,
411  len);
412  res = GNUNET_xmalloc_ (len + 1,
413  filename,
414  linenumber);
415  GNUNET_memcpy (res, str, len);
416  /* res[len] = '\0'; 'malloc' zeros out anyway */
417  return res;
418 }
419 
420 
433 void
434 GNUNET_xgrow_ (void **old,
435  size_t elementSize,
436  unsigned int *oldCount,
437  unsigned int newCount,
438  const char *filename,
439  int linenumber)
440 {
441  void *tmp;
442  size_t size;
443 
444  GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
445  size = newCount * elementSize;
446  if (0 == size)
447  {
448  tmp = NULL;
449  }
450  else
451  {
452  tmp = GNUNET_xmalloc_ (size, filename, linenumber);
453  if (NULL != *old)
454  {
455  GNUNET_memcpy (tmp, *old, elementSize * GNUNET_MIN(*oldCount, newCount));
456  }
457  }
458 
459  if (NULL != *old)
460  {
461  GNUNET_xfree_ (*old, filename, linenumber);
462  }
463  *old = tmp;
464  *oldCount = newCount;
465 }
466 
467 
476 int
478  const char *format,
479  ...)
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 
505 int
507  size_t size,
508  const char *format, ...)
509 {
510  int ret;
511  va_list args;
512 
513  va_start (args, format);
514  ret = VSNPRINTF (buf,
515  size,
516  format,
517  args);
518  va_end (args);
519  GNUNET_assert ( (ret >= 0) &&
520  (((size_t) ret) < size) );
521  return ret;
522 }
523 
524 
531 struct GNUNET_MessageHeader *
533 {
534  struct GNUNET_MessageHeader *ret;
535  uint16_t msize;
536 
537  msize = ntohs (msg->size);
538  GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
539  ret = GNUNET_malloc (msize);
540  GNUNET_memcpy (ret,
541  msg,
542  msize);
543  return ret;
544 }
545 
546 
547 /* end of common_allocation.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf(), just aborts if the buffer is of insufficient size.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct Experiment * e
char * GNUNET_xstrndup_(const char *str, size_t len, const char *filename, int linenumber)
Dup partially a string (same semantics as strndup).
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void * GNUNET_xmalloc_(size_t size, const char *filename, int linenumber)
Allocate memory.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
#define INT_MAX
char * GNUNET_xstrdup_(const char *str, const char *filename, int linenumber)
Dup a string (same semantics as strdup).
cryptographic primitives for GNUnet
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf(), just portable.
void * GNUNET_xrealloc_(void *ptr, size_t n, const char *filename, int linenumber)
Reallocate memory.
#define GNUNET_memcpy(dst, src, n)
#define VSPRINTF(d, f, a)
Definition: plibc.h:686
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
static char buf[2048]
void GNUNET_xfree_(void *ptr, const char *filename, int linenumber)
Free memory.
static char * filename
static int result
Global testing status.
#define LOG_STRERROR(kind, syscall)
void * GNUNET_xmalloc_unchecked_(size_t size, const char *filename, int linenumber)
Wrapper around malloc().
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.
static int res
void * GNUNET_xmemdup_(const void *buf, size_t size, const char *filename, int linenumber)
Allocate and initialize memory.
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define VSNPRINTF(str, size, fmt, a)
Definition: plibc.h:687
#define GNUNET_assert_at(cond, f, l)
Use this for fatal errors that cannot be handled.
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.
Header for all communications.
static size_t strnlen(const char *s, size_t n)
#define GNUNET_malloc(size)
Wrapper around malloc.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
void GNUNET_xgrow_(void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber)
Grow an array.
struct GNUNET_MessageHeader * GNUNET_copy_message(const struct GNUNET_MessageHeader *msg)
Create a copy of the given message.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...