-adding ecc dlog support
[oweals/gnunet.git] / src / util / common_allocation.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
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,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
36
37 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", 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
51 /**
52  * Allocate memory. Checks the return value, aborts if no more
53  * memory is available.
54  *
55  * @param size how many bytes of memory to allocate, do NOT use
56  *  this function (or GNUNET_malloc()) to allocate more than several MB
57  *  of memory, if you are possibly needing a very large chunk use
58  *  #GNUNET_xmalloc_unchecked_() instead.
59  * @param filename where in the code was the call to GNUNET_malloc()
60  * @param linenumber where in the code was the call to GNUNET_malloc()
61  * @return pointer to size bytes of memory
62  */
63 void *
64 GNUNET_xmalloc_ (size_t size,
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 */
72   GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED,
73                     filename,
74                     linenumber);
75   ret = GNUNET_xmalloc_unchecked_ (size,
76                                    filename,
77                                    linenumber);
78   if (NULL == ret)
79   {
80     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
81                   "malloc");
82     GNUNET_assert (0);
83   }
84   return ret;
85 }
86
87
88 /**
89  * Allocate and initialize memory. Checks the return value, aborts if no more
90  * memory is available.  Don't use #GNUNET_xmemdup_() directly. Use the
91  * GNUNET_memdup() macro.
92  *
93  * @param buf buffer to initialize from (must contain size bytes)
94  * @param size number of bytes to allocate
95  * @param filename where is this call being made (for debugging)
96  * @param linenumber line where this call is being made (for debugging)
97  * @return allocated memory, never NULL
98  */
99 void *
100 GNUNET_xmemdup_ (const void *buf,
101                  size_t size,
102                  const char *filename,
103                  int linenumber)
104 {
105   void *ret;
106
107   /* As a security precaution, we generally do not allow very large
108    * allocations here */
109   GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber);
110 #ifdef W32_MEM_LIMIT
111   size += sizeof (size_t);
112   if (mem_used + size > W32_MEM_LIMIT)
113     return NULL;
114 #endif
115   GNUNET_assert_at (size < INT_MAX, filename, linenumber);
116   ret = malloc (size);
117   if (ret == NULL)
118   {
119     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc");
120     GNUNET_assert (0);
121   }
122 #ifdef W32_MEM_LIMIT
123   *((size_t *) ret) = size;
124   ret = &((size_t *) ret)[1];
125   mem_used += size;
126 #endif
127   memcpy (ret, buf, size);
128   return ret;
129 }
130
131
132 /**
133  * Wrapper around malloc(). Allocates size bytes of memory.
134  * The memory will be zero'ed out.
135  *
136  * @param size the number of bytes to allocate
137  * @param filename where in the code was the call to GNUNET_malloc_unchecked()
138  * @param linenumber where in the code was the call to GNUNET_malloc_unchecked()
139  * @return pointer to size bytes of memory, NULL if we do not have enough memory
140  */
141 void *
142 GNUNET_xmalloc_unchecked_ (size_t size,
143                            const char *filename,
144                            int linenumber)
145 {
146   void *result;
147
148 #ifdef W32_MEM_LIMIT
149   size += sizeof (size_t);
150   if (mem_used + size > W32_MEM_LIMIT)
151     return NULL;
152 #endif
153
154   result = malloc (size);
155   if (NULL == result)
156     return NULL;
157   memset (result, 0, size);
158
159 #ifdef W32_MEM_LIMIT
160   *((size_t *) result) = size;
161   result = &((size_t *) result)[1];
162   mem_used += size;
163 #endif
164
165   return result;
166 }
167
168
169 /**
170  * Reallocate memory. Checks the return value, aborts if no more
171  * memory is available.
172  *
173  * @param ptr the pointer to reallocate
174  * @param n how many bytes of memory to allocate
175  * @param filename where in the code was the call to GNUNET_realloc()
176  * @param linenumber where in the code was the call to GNUNET_realloc()
177  * @return pointer to size bytes of memory
178  */
179 void *
180 GNUNET_xrealloc_ (void *ptr,
181                   size_t n,
182                   const char *filename,
183                   int linenumber)
184 {
185 #ifdef W32_MEM_LIMIT
186   n += sizeof (size_t);
187   ptr = &((size_t *) ptr)[-1];
188   mem_used = mem_used - *((size_t *) ptr) + n;
189 #endif
190   ptr = realloc (ptr, n);
191   if ((NULL == ptr) && (n > 0))
192   {
193     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "realloc");
194     GNUNET_assert (0);
195   }
196 #ifdef W32_MEM_LIMIT
197   ptr = &((size_t *) ptr)[1];
198 #endif
199   return ptr;
200 }
201
202
203 # if __BYTE_ORDER == __LITTLE_ENDIAN
204 #define BAADFOOD_STR "\x0D\xF0\xAD\xBA"
205 #endif
206 # if __BYTE_ORDER == __BIG_ENDIAN
207 #define BAADFOOD_STR "\xBA\xAD\xF0\x0D"
208 #endif
209
210 #if WINDOWS
211 #define M_SIZE(p) _msize (p)
212 #endif
213 #if HAVE_MALLOC_NP_H
214 #include <malloc_np.h>
215 #endif
216 #if HAVE_MALLOC_USABLE_SIZE
217 #define M_SIZE(p) malloc_usable_size (p)
218 #elif HAVE_MALLOC_SIZE
219 #define M_SIZE(p) malloc_size (p)
220 #endif
221
222 /**
223  * Free memory. Merely a wrapper for the case that we
224  * want to keep track of allocations.
225  *
226  * @param ptr the pointer to free
227  * @param filename where in the code was the call to GNUNET_array_grow
228  * @param linenumber where in the code was the call to GNUNET_array_grow
229  */
230 void
231 GNUNET_xfree_ (void *ptr,
232                const char *filename,
233                int linenumber)
234 {
235   GNUNET_assert_at (NULL != ptr,
236                     filename,
237                     linenumber);
238 #ifdef W32_MEM_LIMIT
239   ptr = &((size_t *) ptr)[-1];
240   mem_used -= *((size_t *) ptr);
241 #endif
242 #if defined(M_SIZE)
243 #if ENABLE_POISONING
244   {
245     const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
246     uint64_t *base = ptr;
247     size_t s = M_SIZE (ptr);
248     size_t i;
249
250     for (i=0;i<s/8;i++)
251       base[i] = baadfood;
252     memcpy (&base[s/8], &baadfood, s % 8);
253   }
254 #endif
255 #endif
256   free (ptr);
257 }
258
259
260 /**
261  * Dup a string (same semantics as strdup).
262  *
263  * @param str the string to dup
264  * @param filename where in the code was the call to GNUNET_strdup()
265  * @param linenumber where in the code was the call to GNUNET_strdup()
266  * @return `strdup(@a str)`
267  */
268 char *
269 GNUNET_xstrdup_ (const char *str,
270                  const char *filename,
271                  int linenumber)
272 {
273   char *res;
274   size_t slen;
275
276   GNUNET_assert_at (str != NULL,
277                     filename,
278                     linenumber);
279   slen = strlen (str) + 1;
280   res = GNUNET_xmalloc_ (slen,
281                          filename,
282                          linenumber);
283   memcpy (res,
284           str,
285           slen);
286   return res;
287 }
288
289
290 #if ! HAVE_STRNLEN
291 static size_t
292 strnlen (const char *s,
293          size_t n)
294 {
295   const char *e;
296
297   e = memchr (s, '\0', n);
298   if (NULL == e)
299     return n;
300   return e - s;
301 }
302 #endif
303
304
305 /**
306  * Dup partially a string (same semantics as strndup).
307  *
308  * @param str the string to dup
309  * @param len the length of the string to dup
310  * @param filename where in the code was the call to GNUNET_strndup()
311  * @param linenumber where in the code was the call to GNUNET_strndup()
312  * @return `strndup(@a str,@a len)`
313  */
314 char *
315 GNUNET_xstrndup_ (const char *str,
316                   size_t len,
317                   const char *filename,
318                   int linenumber)
319 {
320   char *res;
321
322   if (0 == len)
323     return GNUNET_strdup ("");
324   GNUNET_assert_at (NULL != str,
325                     filename,
326                     linenumber);
327   len = strnlen (str,
328                  len);
329   res = GNUNET_xmalloc_ (len + 1,
330                          filename,
331                          linenumber);
332   memcpy (res, str, len);
333   /* res[len] = '\0'; 'malloc' zeros out anyway */
334   return res;
335 }
336
337
338 /**
339  * Grow an array.  Grows old by (*oldCount-newCount)*elementSize bytes
340  * and sets *oldCount to newCount.
341  *
342  * @param old address of the pointer to the array
343  *        *old may be NULL
344  * @param elementSize the size of the elements of the array
345  * @param oldCount address of the number of elements in the *old array
346  * @param newCount number of elements in the new array, may be 0
347  * @param filename where in the code was the call to GNUNET_array_grow()
348  * @param linenumber where in the code was the call to GNUNET_array_grow()
349  */
350 void
351 GNUNET_xgrow_ (void **old,
352                size_t elementSize,
353                unsigned int *oldCount,
354                unsigned int newCount,
355                const char *filename,
356                int linenumber)
357 {
358   void *tmp;
359   size_t size;
360
361   GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
362   size = newCount * elementSize;
363   if (size == 0)
364   {
365     tmp = NULL;
366   }
367   else
368   {
369     tmp = GNUNET_xmalloc_ (size, filename, linenumber);
370     memset (tmp, 0, size);      /* client code should not rely on this, though... */
371     if (*oldCount > newCount)
372       *oldCount = newCount;     /* shrink is also allowed! */
373     memcpy (tmp, *old, elementSize * (*oldCount));
374   }
375
376   if (*old != NULL)
377   {
378     GNUNET_xfree_ (*old, filename, linenumber);
379   }
380   *old = tmp;
381   *oldCount = newCount;
382 }
383
384
385 /**
386  * Like asprintf(), just portable.
387  *
388  * @param buf set to a buffer of sufficient size (allocated, caller must free)
389  * @param format format string (see printf(), fprintf(), etc.)
390  * @param ... data for format string
391  * @return number of bytes in `*@a buf`, excluding 0-termination
392  */
393 int
394 GNUNET_asprintf (char **buf,
395                  const char *format,
396                  ...)
397 {
398   int ret;
399   va_list args;
400
401   va_start (args, format);
402   ret = VSNPRINTF (NULL, 0, format, args);
403   va_end (args);
404   *buf = GNUNET_malloc (ret + 1);
405   va_start (args, format);
406   ret = VSPRINTF (*buf, format, args);
407   va_end (args);
408   return ret;
409 }
410
411
412 /**
413  * Like snprintf(), just aborts if the buffer is of insufficient size.
414  *
415  * @param buf pointer to buffer that is written to
416  * @param size number of bytes in buf
417  * @param format format strings
418  * @param ... data for format string
419  * @return number of bytes written to buf or negative value on error
420  */
421 int
422 GNUNET_snprintf (char *buf,
423                  size_t size,
424                  const char *format, ...)
425 {
426   int ret;
427   va_list args;
428
429   va_start (args, format);
430   ret = VSNPRINTF (buf, size, format, args);
431   va_end (args);
432   GNUNET_assert (ret < size);
433   return ret;
434 }
435
436
437 /**
438  * Create a copy of the given message.
439  *
440  * @param msg message to copy
441  * @return duplicate of the message
442  */
443 struct GNUNET_MessageHeader *
444 GNUNET_copy_message (const struct GNUNET_MessageHeader *msg)
445 {
446   struct GNUNET_MessageHeader *ret;
447   uint16_t msize;
448
449   msize = ntohs (msg->size);
450   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
451   ret = GNUNET_malloc (msize);
452   memcpy (ret, msg, msize);
453   return ret;
454 }
455
456
457 /* end of common_allocation.c */