/** * Allocate and initialize memory. Checks the return value, aborts if no more * memory is available. Don't use GNUNET_xmemdup_ directly. Use the * GNUNET_memdup macro. * * @param buf buffer to initialize from (must contain size bytes) * @param size number of bytes to allocate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return allocated memory, never NULL */ void * GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename, int linenumber) { void *ret; /* As a security precaution, we generally do not allow very large * allocations here */ GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); #ifdef W32_MEM_LIMIT size += sizeof (size_t); if (mem_used + size > W32_MEM_LIMIT) return NULL; #endif GNUNET_assert_at (size < INT_MAX, filename, linenumber); ret = malloc (size); if (ret == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_abort (); } #ifdef W32_MEM_LIMIT *((size_t *) ret) = size; ret = &((size_t *) ret)[1]; mem_used += size; #endif memcpy (ret, buf, size); return ret; }
/** * Grow an array. Grows old by (*oldCount-newCount)*elementSize bytes * and sets *oldCount to newCount. * * @param old address of the pointer to the array * *old may be NULL * @param elementSize the size of the elements of the array * @param oldCount address of the number of elements in the *old array * @param newCount number of elements in the new array, may be 0 * @param filename where in the code was the call to GNUNET_array_grow * @param linenumber where in the code was the call to GNUNET_array_grow */ void GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber) { void *tmp; size_t size; GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber); size = newCount * elementSize; if (size == 0) { tmp = NULL; } else { tmp = GNUNET_xmalloc_ (size, filename, linenumber); memset (tmp, 0, size); /* client code should not rely on this, though... */ if (*oldCount > newCount) *oldCount = newCount; /* shrink is also allowed! */ memcpy (tmp, *old, elementSize * (*oldCount)); } if (*old != NULL) { GNUNET_xfree_ (*old, filename, linenumber); } *old = tmp; *oldCount = newCount; }
/** * Grow an array. Grows old by (*oldCount-newCount)*elementSize bytes * and sets *oldCount to newCount. * * @param old address of the pointer to the array * *old may be NULL * @param elementSize the size of the elements of the array * @param oldCount address of the number of elements in the *old array * @param newCount number of elements in the new array, may be 0 * @param filename where in the code was the call to GNUNET_array_grow() * @param linenumber where in the code was the call to GNUNET_array_grow() */ void GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber) { void *tmp; size_t size; GNUNET_assert_at (INT_MAX / elementSize > newCount, filename, linenumber); size = newCount * elementSize; if (0 == size) { tmp = NULL; } else { tmp = GNUNET_xmalloc_ (size, filename, linenumber); if (NULL != *old) { GNUNET_memcpy (tmp, *old, elementSize * GNUNET_MIN(*oldCount, newCount)); } } if (NULL != *old) { GNUNET_xfree_ (*old, filename, linenumber); } *old = tmp; *oldCount = newCount; }
/** * Free memory. Merely a wrapper for the case that we * want to keep track of allocations. * * @param ptr the pointer to free * @param filename where in the code was the call to GNUNET_free * @param linenumber where in the code was the call to GNUNET_free */ void GNUNET_xfree_ (void *ptr, const char *filename, int linenumber) { GNUNET_assert_at (NULL != ptr, filename, linenumber); #ifdef W32_MEM_LIMIT ptr = &((size_t *) ptr)[-1]; mem_used -= *((size_t *) ptr); #endif #if defined(M_SIZE) #if ENABLE_POISONING { const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); uint64_t *base = ptr; size_t s = M_SIZE (ptr); size_t i; for (i=0;i<s/8;i++) base[i] = baadfood; GNUNET_memcpy (&base[s/8], &baadfood, s % 8); } #endif #endif free (ptr); }
/** * Dup a string (same semantics as strdup). * * @param str the string to dup * @param filename where in the code was the call to GNUNET_strdup * @param linenumber where in the code was the call to GNUNET_strdup * @return strdup(str) */ char * GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber) { char *res; GNUNET_assert_at (str != NULL, filename, linenumber); res = GNUNET_xmalloc_ (strlen (str) + 1, filename, linenumber); memcpy (res, str, strlen (str) + 1); return res; }
/** * Dup partially a string (same semantics as strndup). * * @param str the string to dup * @param len the length of the string to dup * @param filename where in the code was the call to GNUNET_strndup * @param linenumber where in the code was the call to GNUNET_strndup * @return strndup(str,len) */ char * GNUNET_xstrndup_ (const char *str, size_t len, const char *filename, int linenumber) { char *res; GNUNET_assert_at (str != NULL, filename, linenumber); len = strnlen (str, len); res = GNUNET_xmalloc_ (len + 1, filename, linenumber); memcpy (res, str, len); /* res[len] = '\0'; 'malloc' zeros out anyway */ return res; }
/** * Allocate memory. Checks the return value, aborts if no more * memory is available. * * @param size how many bytes of memory to allocate, do NOT use * this function (or GNUNET_malloc) to allocate more than several MB * of memory, if you are possibly needing a very large chunk use * GNUNET_xmalloc_unchecked_ instead. * @param filename where in the code was the call to GNUNET_malloc * @param linenumber where in the code was the call to GNUNET_malloc * @return pointer to size bytes of memory */ void * GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber) { void *ret; /* As a security precaution, we generally do not allow very large * allocations using the default 'GNUNET_malloc' macro */ GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber); if (ret == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_abort (); } return ret; }
/** * Dup a string (same semantics as strdup). * * @param str the string to dup * @param filename where in the code was the call to GNUNET_strdup() * @param linenumber where in the code was the call to GNUNET_strdup() * @return `strdup(@a str)` */ char * GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber) { char *res; size_t slen; GNUNET_assert_at (str != NULL, filename, linenumber); slen = strlen (str) + 1; res = GNUNET_xmalloc_ (slen, filename, linenumber); GNUNET_memcpy (res, str, slen); return res; }