2
0

common_allocation.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file util/common_allocation.c
  19. * @brief wrapper around malloc/free
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #if HAVE_MALLOC_H
  25. #include <malloc.h>
  26. #endif
  27. #if HAVE_MALLOC_MALLOC_H
  28. #include <malloc/malloc.h>
  29. #endif
  30. #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
  31. #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
  32. #ifndef INT_MAX
  33. #define INT_MAX 0x7FFFFFFF
  34. #endif
  35. #if 0
  36. #define W32_MEM_LIMIT 200000000
  37. #endif
  38. #ifdef W32_MEM_LIMIT
  39. static LONG mem_used = 0;
  40. #endif
  41. /**
  42. * Allocate memory. Checks the return value, aborts if no more
  43. * memory is available.
  44. *
  45. * @param size how many bytes of memory to allocate, do NOT use
  46. * this function (or GNUNET_malloc) to allocate more than several MB
  47. * of memory, if you are possibly needing a very large chunk use
  48. * GNUNET_xmalloc_unchecked_ instead.
  49. * @param filename where in the code was the call to GNUNET_malloc
  50. * @param linenumber where in the code was the call to GNUNET_malloc
  51. * @return pointer to size bytes of memory
  52. */
  53. void *
  54. GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber)
  55. {
  56. void *ret;
  57. /* As a security precaution, we generally do not allow very large
  58. * allocations using the default 'GNUNET_malloc' macro */
  59. GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber);
  60. ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber);
  61. if (ret == NULL)
  62. {
  63. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc");
  64. GNUNET_abort ();
  65. }
  66. return ret;
  67. }
  68. /**
  69. * Allocate and initialize memory. Checks the return value, aborts if no more
  70. * memory is available. Don't use GNUNET_xmemdup_ directly. Use the
  71. * GNUNET_memdup macro.
  72. *
  73. * @param buf buffer to initialize from (must contain size bytes)
  74. * @param size number of bytes to allocate
  75. * @param filename where is this call being made (for debugging)
  76. * @param linenumber line where this call is being made (for debugging)
  77. * @return allocated memory, never NULL
  78. */
  79. void *
  80. GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename,
  81. int linenumber)
  82. {
  83. void *ret;
  84. /* As a security precaution, we generally do not allow very large
  85. * allocations here */
  86. GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber);
  87. #ifdef W32_MEM_LIMIT
  88. size += sizeof (size_t);
  89. if (mem_used + size > W32_MEM_LIMIT)
  90. return NULL;
  91. #endif
  92. GNUNET_assert_at (size < INT_MAX, filename, linenumber);
  93. ret = malloc (size);
  94. if (ret == NULL)
  95. {
  96. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc");
  97. GNUNET_abort ();
  98. }
  99. #ifdef W32_MEM_LIMIT
  100. *((size_t *) ret) = size;
  101. ret = &((size_t *) ret)[1];
  102. mem_used += size;
  103. #endif
  104. memcpy (ret, buf, size);
  105. return ret;
  106. }
  107. /**
  108. * Wrapper around malloc. Allocates size bytes of memory.
  109. * The memory will be zero'ed out.
  110. *
  111. * @param size the number of bytes to allocate
  112. * @param filename where in the code was the call to GNUNET_malloc_large
  113. * @param linenumber where in the code was the call to GNUNET_malloc_large
  114. * @return pointer to size bytes of memory, NULL if we do not have enough memory
  115. */
  116. void *
  117. GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber)
  118. {
  119. void *result;
  120. #ifdef W32_MEM_LIMIT
  121. size += sizeof (size_t);
  122. if (mem_used + size > W32_MEM_LIMIT)
  123. return NULL;
  124. #endif
  125. result = malloc (size);
  126. if (result == NULL)
  127. return NULL;
  128. memset (result, 0, size);
  129. #ifdef W32_MEM_LIMIT
  130. *((size_t *) result) = size;
  131. result = &((size_t *) result)[1];
  132. mem_used += size;
  133. #endif
  134. return result;
  135. }
  136. /**
  137. * Reallocate memory. Checks the return value, aborts if no more
  138. * memory is available.
  139. *
  140. * @param ptr the pointer to reallocate
  141. * @param n how many bytes of memory to allocate
  142. * @param filename where in the code was the call to GNUNET_realloc
  143. * @param linenumber where in the code was the call to GNUNET_realloc
  144. * @return pointer to size bytes of memory
  145. */
  146. void *
  147. GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber)
  148. {
  149. #ifdef W32_MEM_LIMIT
  150. n += sizeof (size_t);
  151. ptr = &((size_t *) ptr)[-1];
  152. mem_used = mem_used - *((size_t *) ptr) + n;
  153. #endif
  154. ptr = realloc (ptr, n);
  155. if ((NULL == ptr) && (n > 0))
  156. {
  157. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "realloc");
  158. GNUNET_abort ();
  159. }
  160. #ifdef W32_MEM_LIMIT
  161. ptr = &((size_t *) ptr)[1];
  162. #endif
  163. return ptr;
  164. }
  165. # if __BYTE_ORDER == __LITTLE_ENDIAN
  166. #define BAADFOOD_STR "\x0D\xF0\xAD\xBA"
  167. #endif
  168. # if __BYTE_ORDER == __BIG_ENDIAN
  169. #define BAADFOOD_STR "\xBA\xAD\xF0\x0D"
  170. #endif
  171. #if WINDOWS
  172. #define M_SIZE(p) _msize (p)
  173. #endif
  174. #if HAVE_MALLOC_NP_H
  175. #include <malloc_np.h>
  176. #endif
  177. #if HAVE_MALLOC_USABLE_SIZE
  178. #define M_SIZE(p) malloc_usable_size (p)
  179. #elif HAVE_MALLOC_SIZE
  180. #define M_SIZE(p) malloc_size (p)
  181. #endif
  182. /**
  183. * Free memory. Merely a wrapper for the case that we
  184. * want to keep track of allocations.
  185. *
  186. * @param ptr the pointer to free
  187. * @param filename where in the code was the call to GNUNET_array_grow
  188. * @param linenumber where in the code was the call to GNUNET_array_grow
  189. */
  190. void
  191. GNUNET_xfree_ (void *ptr, const char *filename, int linenumber)
  192. {
  193. GNUNET_assert_at (ptr != NULL, filename, linenumber);
  194. #ifdef W32_MEM_LIMIT
  195. ptr = &((size_t *) ptr)[-1];
  196. mem_used -= *((size_t *) ptr);
  197. #endif
  198. #if defined(M_SIZE)
  199. #if ENABLE_POISONING
  200. {
  201. const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL);
  202. uint64_t *base = ptr;
  203. size_t s = M_SIZE (ptr);
  204. size_t i;
  205. for (i=0;i<s/8;i++)
  206. base[i] = baadfood;
  207. memcpy (&base[s/8], &baadfood, s % 8);
  208. }
  209. #endif
  210. #endif
  211. free (ptr);
  212. }
  213. /**
  214. * Dup a string (same semantics as strdup).
  215. *
  216. * @param str the string to dup
  217. * @param filename where in the code was the call to GNUNET_strdup
  218. * @param linenumber where in the code was the call to GNUNET_strdup
  219. * @return strdup(str)
  220. */
  221. char *
  222. GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber)
  223. {
  224. char *res;
  225. GNUNET_assert_at (str != NULL, filename, linenumber);
  226. res = GNUNET_xmalloc_ (strlen (str) + 1, filename, linenumber);
  227. memcpy (res, str, strlen (str) + 1);
  228. return res;
  229. }
  230. #if ! HAVE_STRNLEN
  231. static size_t
  232. strnlen (const char *s,
  233. size_t n)
  234. {
  235. const char *e;
  236. e = memchr (s, '\0', n);
  237. if (NULL == e)
  238. return n;
  239. return e - s;
  240. }
  241. #endif
  242. /**
  243. * Dup partially a string (same semantics as strndup).
  244. *
  245. * @param str the string to dup
  246. * @param len the length of the string to dup
  247. * @param filename where in the code was the call to GNUNET_strndup
  248. * @param linenumber where in the code was the call to GNUNET_strndup
  249. * @return strndup(str,len)
  250. */
  251. char *
  252. GNUNET_xstrndup_ (const char *str, size_t len, const char *filename,
  253. int linenumber)
  254. {
  255. char *res;
  256. if (0 == len)
  257. return GNUNET_strdup ("");
  258. GNUNET_assert_at (str != NULL, filename, linenumber);
  259. len = strnlen (str, len);
  260. res = GNUNET_xmalloc_ (len + 1, filename, linenumber);
  261. memcpy (res, str, len);
  262. /* res[len] = '\0'; 'malloc' zeros out anyway */
  263. return res;
  264. }
  265. /**
  266. * Grow an array. Grows old by (*oldCount-newCount)*elementSize bytes
  267. * and sets *oldCount to newCount.
  268. *
  269. * @param old address of the pointer to the array
  270. * *old may be NULL
  271. * @param elementSize the size of the elements of the array
  272. * @param oldCount address of the number of elements in the *old array
  273. * @param newCount number of elements in the new array, may be 0
  274. * @param filename where in the code was the call to GNUNET_array_grow
  275. * @param linenumber where in the code was the call to GNUNET_array_grow
  276. */
  277. void
  278. GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount,
  279. unsigned int newCount, const char *filename, int linenumber)
  280. {
  281. void *tmp;
  282. size_t size;
  283. GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber);
  284. size = newCount * elementSize;
  285. if (size == 0)
  286. {
  287. tmp = NULL;
  288. }
  289. else
  290. {
  291. tmp = GNUNET_xmalloc_ (size, filename, linenumber);
  292. memset (tmp, 0, size); /* client code should not rely on this, though... */
  293. if (*oldCount > newCount)
  294. *oldCount = newCount; /* shrink is also allowed! */
  295. memcpy (tmp, *old, elementSize * (*oldCount));
  296. }
  297. if (*old != NULL)
  298. {
  299. GNUNET_xfree_ (*old, filename, linenumber);
  300. }
  301. *old = tmp;
  302. *oldCount = newCount;
  303. }
  304. /**
  305. * Like asprintf, just portable.
  306. *
  307. * @param buf set to a buffer of sufficient size (allocated, caller must free)
  308. * @param format format string (see printf, fprintf, etc.)
  309. * @param ... data for format string
  310. * @return number of bytes in "*buf" excluding 0-termination
  311. */
  312. int
  313. GNUNET_asprintf (char **buf, const char *format, ...)
  314. {
  315. int ret;
  316. va_list args;
  317. va_start (args, format);
  318. ret = VSNPRINTF (NULL, 0, format, args);
  319. va_end (args);
  320. *buf = GNUNET_malloc (ret + 1);
  321. va_start (args, format);
  322. ret = VSPRINTF (*buf, format, args);
  323. va_end (args);
  324. return ret;
  325. }
  326. /**
  327. * Like snprintf, just aborts if the buffer is of insufficient size.
  328. *
  329. * @param buf pointer to buffer that is written to
  330. * @param size number of bytes in buf
  331. * @param format format strings
  332. * @param ... data for format string
  333. * @return number of bytes written to buf or negative value on error
  334. */
  335. int
  336. GNUNET_snprintf (char *buf, size_t size, const char *format, ...)
  337. {
  338. int ret;
  339. va_list args;
  340. va_start (args, format);
  341. ret = VSNPRINTF (buf, size, format, args);
  342. va_end (args);
  343. GNUNET_assert (ret < size);
  344. return ret;
  345. }
  346. /**
  347. * Create a copy of the given message.
  348. *
  349. * @param msg message to copy
  350. * @return duplicate of the message
  351. */
  352. struct GNUNET_MessageHeader *
  353. GNUNET_copy_message (const struct GNUNET_MessageHeader *msg)
  354. {
  355. struct GNUNET_MessageHeader *ret;
  356. uint16_t msize;
  357. msize = ntohs (msg->size);
  358. GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
  359. ret = GNUNET_malloc (msize);
  360. memcpy (ret, msg, msize);
  361. return ret;
  362. }
  363. /* end of common_allocation.c */