#include "string.h"
#include "error.h"
+/**
+ * Reallocate an array, abort on failure or bugs.
+ *
+ * \param ptr Pointer to the memory block, may be NULL.
+ * \param nmemb Number of elements.
+ * \param size The size of one element in bytes.
+ *
+ * A wrapper for realloc(3) which aborts on invalid arguments or integer
+ * overflow. The wrapper also terminates the current process on allocation
+ * errors, so the caller does not need to check for failure.
+ *
+ * \return A pointer to newly allocated memory which is suitably aligned for
+ * any kind of variable and may be different from ptr.
+ *
+ * \sa realloc(3).
+ */
+__must_check void *arr_realloc(void *ptr, size_t nmemb, size_t size)
+{
+ size_t pr;
+
+ assert(size > 0);
+ assert(nmemb > 0);
+ assert(!__builtin_mul_overflow(nmemb, size, &pr));
+ assert(pr != 0);
+ ptr = realloc(ptr, pr);
+ assert(ptr);
+ return ptr;
+}
+
+/**
+ * Allocate an array, abort on failure or bugs.
+ *
+ * \param nmemb See \ref arr_realloc().
+ * \param size See \ref arr_realloc().
+ *
+ * Like \ref arr_realloc(), this aborts on invalid arguments, integer overflow
+ * and allocation errors.
+ *
+ * \return A pointer to newly allocated memory which is suitably aligned for
+ * any kind of variable.
+ *
+ * \sa See \ref arr_realloc().
+ */
+__must_check __malloc void *arr_alloc(size_t nmemb, size_t size)
+{
+ return arr_realloc(NULL, nmemb, size);
+}
+
+/**
+ * Allocate and initialize an array, abort on failure or bugs.
+ *
+ * \param nmemb See \ref arr_realloc().
+ * \param size See \ref arr_realloc().
+ *
+ * This calls \ref arr_alloc() and zeroes-out the array.
+ *
+ * \return See \ref arr_alloc().
+ */
+__must_check __malloc void *arr_zalloc(size_t nmemb, size_t size)
+{
+ void *ptr = arr_alloc(nmemb, size);
+
+ /*
+ * This multiplication can not overflow because the above call to \ref
+ * arr_alloc() aborts on overflow.
+ */
+ memset(ptr, 0, nmemb * size);
+ return ptr;
+}
+
+/**
+ * Allocate and initialize memory.
+ *
+ * \param size The desired new size.
+ *
+ * \return A pointer to the allocated and zeroed-out memory, which is suitably
+ * aligned for any kind of variable.
+ *
+ * \sa \ref alloc(), calloc(3).
+ */
+__must_check void *zalloc(size_t size)
+{
+ return arr_zalloc(1, size);
+}
+
/**
* Paraslash's version of realloc().
*
*/
__must_check void *para_realloc(void *p, size_t size)
{
- /*
- * No need to check for NULL pointers: If p is NULL, the call
- * to realloc is equivalent to malloc(size)
- */
- assert(size);
- if (!(p = realloc(p, size))) {
- PARA_EMERG_LOG("realloc failed (size = %zu), aborting\n",
- size);
- exit(EXIT_FAILURE);
- }
- return p;
+ return arr_realloc(p, 1, size);
}
/**
*/
__must_check __malloc void *alloc(size_t size)
{
- void *p;
-
- assert(size);
- p = malloc(size);
- if (!p) {
- PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n",
- size);
- exit(EXIT_FAILURE);
- }
- return p;
-}
-
-/**
- * Paraslash's version of calloc().
- *
- * \param size The desired new size.
- *
- * A wrapper for calloc(3) which exits on errors.
- *
- * \return A pointer to the allocated and zeroed-out memory, which is suitably
- * aligned for any kind of variable.
- *
- * \sa calloc(3)
- */
-__must_check __malloc void *para_calloc(size_t size)
-{
- void *ret = alloc(size);
-
- memset(ret, 0, size);
- return ret;
+ return arr_alloc(1, size);
}
/**
return 1;
}
-static inline int loglevel_equal(const char *arg, const char * const ll)
-{
- return !strncasecmp(arg, ll, strlen(ll));
-}
-
-/**
- * Compute the loglevel number from its name.
- *
- * \param txt The name of the loglevel (debug, info, ...).
- *
- * \return The numeric representation of the loglevel name.
- */
-int get_loglevel_by_name(const char *txt)
-{
- if (loglevel_equal(txt, "debug"))
- return LL_DEBUG;
- if (loglevel_equal(txt, "info"))
- return LL_INFO;
- if (loglevel_equal(txt, "notice"))
- return LL_NOTICE;
- if (loglevel_equal(txt, "warning"))
- return LL_WARNING;
- if (loglevel_equal(txt, "error"))
- return LL_ERROR;
- if (loglevel_equal(txt, "crit"))
- return LL_CRIT;
- if (loglevel_equal(txt, "emerg"))
- return LL_EMERG;
- return -E_BAD_LL;
-}
-
static int get_next_word(const char *buf, const char *delim, char **word)
{
enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2,
static int create_argv_offset(int offset, const char *buf, const char *delim,
char ***result)
{
- char *word, **argv = alloc((offset + 1) * sizeof(char *));
+ char *word, **argv = arr_alloc(offset + 1, sizeof(char *));
const char *p;
int i, ret;
goto err;
if (!ret)
break;
- argv = para_realloc(argv, (i + 2) * sizeof(char*));
+ argv = arr_realloc(argv, i + 2, sizeof(char*));
argv[i] = word;
}
argv[i] = NULL;
return -ERRNO_TO_PARA_ERROR(errno);
if (num_wchars == 0)
return 0;
- dest = alloc((num_wchars + 1) * sizeof(*dest));
+ dest = arr_alloc(num_wchars + 1, sizeof(*dest));
src = s;
memset(&state, 0, sizeof(state));
num_wchars = mbsrtowcs(dest, &src, num_wchars, &state);
num_wchars = mbsrtowcs(NULL, &src, 0, &state);
if (num_wchars == (size_t)-1)
return -ERRNO_TO_PARA_ERROR(errno);
- wcs = alloc((num_wchars + 1) * sizeof(*wcs));
+ wcs = arr_alloc(num_wchars + 1, sizeof(*wcs));
memset(&state, 0, sizeof(state));
num_wchars = mbsrtowcs(wcs, &src, num_wchars + 1, &state);
assert(num_wchars != (size_t)-1);