X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=string.c;h=46b346235f17ffb696f43d22d3dcfde4c75ba4ca;hb=9055c71be97f1095dcdbd83da305b600f204f763;hp=bbc322eb52dd2c529bd0622e84b2f2eeabe290fb;hpb=26a032fffa6c6e6f092ed3d14c2b5f08e5c736d6;p=paraslash.git diff --git a/string.c b/string.c index bbc322eb..46b34623 100644 --- a/string.c +++ b/string.c @@ -15,58 +15,73 @@ #include "error.h" /** - * Paraslash's version of realloc(). + * Reallocate an array, abort on failure or bugs. * - * \param p Pointer to the memory block, may be \p NULL. - * \param size The desired new size. + * \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). It calls \p exit(\p EXIT_FAILURE) on errors, - * i.e. there is no need to check the return value in the caller. + * 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 \a p. + * any kind of variable and may be different from ptr. * * \sa realloc(3). */ -__must_check void *para_realloc(void *p, size_t size) +__must_check void *arr_realloc(void *ptr, size_t nmemb, 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; + 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; } /** - * Paraslash's version of malloc(). + * Allocate an array, abort on failure or bugs. * - * \param size The desired new size. + * \param nmemb See \ref arr_realloc(). + * \param size See \ref arr_realloc(). * - * A wrapper for malloc(3) which exits on errors. + * Like \ref arr_realloc(), this aborts on invalid arguments, integer overflow + * and allocation errors. * - * \return A pointer to the allocated memory, which is suitably aligned for any - * kind of variable. + * \return A pointer to newly allocated memory which is suitably aligned for + * any kind of variable. * - * \sa malloc(3). + * \sa See \ref arr_realloc(). */ -__must_check __malloc void *alloc(size_t size) +__must_check __malloc void *arr_alloc(size_t nmemb, 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; + 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; } /** @@ -79,12 +94,45 @@ __must_check __malloc void *alloc(size_t size) * * \sa \ref alloc(), calloc(3). */ -__must_check __malloc void *zalloc(size_t size) +__must_check void *zalloc(size_t size) { - void *ret = alloc(size); + return arr_zalloc(1, size); +} - memset(ret, 0, size); - return ret; +/** + * Paraslash's version of realloc(). + * + * \param p Pointer to the memory block, may be \p NULL. + * \param size The desired new size. + * + * A wrapper for realloc(3). It calls \p exit(\p EXIT_FAILURE) on errors, + * i.e. there is no need to check the return value in the caller. + * + * \return A pointer to newly allocated memory which is suitably aligned for + * any kind of variable and may be different from \a p. + * + * \sa realloc(3). + */ +__must_check void *para_realloc(void *p, size_t size) +{ + return arr_realloc(p, 1, size); +} + +/** + * Paraslash's version of malloc(). + * + * \param size The desired new size. + * + * A wrapper for malloc(3) which exits on errors. + * + * \return A pointer to the allocated memory, which is suitably aligned for any + * kind of variable. + * + * \sa malloc(3). + */ +__must_check __malloc void *alloc(size_t size) +{ + return arr_alloc(1, size); } /** @@ -551,37 +599,6 @@ int para_atoi32(const char *str, int32_t *value) 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, @@ -722,7 +739,7 @@ void free_argv(char **argv) 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; @@ -734,7 +751,7 @@ static int create_argv_offset(int offset, const char *buf, const char *delim, 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; @@ -789,27 +806,6 @@ int create_shifted_argv(const char *buf, const char *delim, char ***result) return create_argv_offset(1, buf, delim, result); } -/** - * Find out if the given string is contained in the arg vector. - * - * \param arg The string to look for. - * \param argv The array to search. - * - * \return The first index whose value equals \a arg, or \p -E_ARG_NOT_FOUND if - * arg was not found in \a argv. - */ -int find_arg(const char *arg, char **argv) -{ - int i; - - if (!argv) - return -E_ARG_NOT_FOUND; - for (i = 0; argv[i]; i++) - if (strcmp(arg, argv[i]) == 0) - return i; - return -E_ARG_NOT_FOUND; -} - /** * Compile a regular expression. * @@ -1010,7 +1006,7 @@ __must_check int strwidth(const char *s, size_t *result) 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); @@ -1065,7 +1061,7 @@ __must_check int sanitize_str(const char *src, size_t max_width, 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);