diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2018-05-30 11:40:42 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2018-05-30 11:40:42 -0700 |
commit | 740ec3572bb4a587a287cdcea201f12fa5f00501 (patch) | |
tree | fb7ce904917389d2ddfd8ed7a31c28f7c2490781 | |
parent | 1ce81e10effa327362e8cdd316f6ea57c8324ce0 (diff) | |
download | nasm-740ec3572bb4a587a287cdcea201f12fa5f00501.tar.gz |
malloc: simplify nasm_malloc code, add nasm_strcatn()
Simplify the nasm_malloc() code by moving the pointer check into a
common subroutine.
We can now issue a filename error even for failures like malloc().
Add support for the gcc sentinel attribute (verify that a list ends
with NULL).
Add a handful of safe_alloc attributes.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | aclocal.m4 | 7 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | include/compiler.h | 8 | ||||
-rw-r--r-- | include/nasmlib.h | 4 | ||||
-rw-r--r-- | nasmlib/malloc.c | 87 |
5 files changed, 85 insertions, 22 deletions
@@ -106,10 +106,11 @@ AC_DEFUN(PA_FUNC_ATTRIBUTE, AC_INCLUDES_DEFAULT extern ifelse([$3],[],[void *],[$3]) __attribute__(($1$2)) bar(ifelse([$4],[],[int],[$4])); -void *foo(void); -void *foo(void) +ifelse([$3],[],[void *],[$3]) foo(void); +ifelse([$3],[],[void *],[$3]) foo(void) { - return bar(ifelse([$5],[],[1],[$5])); + ifelse([$3],[void],[],[return]) + bar(ifelse([$5],[],[1],[$5])); } ])], [AC_MSG_RESULT([yes]) diff --git a/configure.ac b/configure.ac index 44c9e179..40a6f62c 100644 --- a/configure.ac +++ b/configure.ac @@ -220,6 +220,7 @@ PA_FUNC_ATTRIBUTE(noreturn) PA_FUNC_ATTRIBUTE(returns_nonnull) PA_FUNC_ATTRIBUTE(malloc) PA_FUNC_ATTRIBUTE(alloc_size, (1)) +PA_FUNC_ATTRIBUTE(sentinel,,, [const char *, ...], ["a","b",NULL]) PA_FUNC_ATTRIBUTE(format, [(printf,1,2)], int, [const char *, ...], ["%d",1]) PA_FUNC_ATTRIBUTE(const) PA_FUNC_ATTRIBUTE(pure) diff --git a/include/compiler.h b/include/compiler.h index fb146af4..4178c98e 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -264,7 +264,7 @@ size_t strnlen(const char *s, size_t maxlen); #ifdef HAVE_FUNC_ATTRIBUTE_MALLOC # define safe_alloc never_null __attribute__((malloc)) #else -# define safe_alloc +# define safe_alloc never_null #endif #ifdef HAVE_FUNC_ATTRIBUTE_ALLOC_SIZE @@ -277,6 +277,12 @@ size_t strnlen(const char *s, size_t maxlen); # define safe_realloc(s) never_null #endif +#ifdef HAVE_FUNC_ATTRIBUTE_SENTINEL +# define end_with_null __attribute__((sentinel)) +#else +# define end_with_null +#endif + /* * How to tell the compiler that a function doesn't return */ diff --git a/include/nasmlib.h b/include/nasmlib.h index bb1becdf..a4f6bf95 100644 --- a/include/nasmlib.h +++ b/include/nasmlib.h @@ -79,6 +79,8 @@ void * safe_realloc(2) nasm_realloc(void *, size_t); void nasm_free(void *); char * safe_alloc nasm_strdup(const char *); char * safe_alloc nasm_strndup(const char *, size_t); +char * safe_alloc nasm_strcat(const char *one, const char *two); +char * safe_alloc end_with_null nasm_strcatn(const char *one, ...); /* Assert the argument is a pointer without evaluating it */ #define nasm_assert_pointer(p) ((void)sizeof(*(p))) @@ -282,8 +284,6 @@ void src_set(int32_t line, const char *filename); */ int32_t src_get(int32_t *xline, const char **xname); -char *nasm_strcat(const char *one, const char *two); - char *nasm_skip_spaces(const char *p); char *nasm_skip_word(const char *p); char *nasm_zap_spaces_fwd(char *p); diff --git a/nasmlib/malloc.c b/nasmlib/malloc.c index 160d0ffb..ccbc0c75 100644 --- a/nasmlib/malloc.c +++ b/nasmlib/malloc.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * - * - * Copyright 1996-2016 The NASM Authors - All Rights Reserved + * + * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -14,7 +14,7 @@ * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -42,33 +42,36 @@ #include "nasmlib.h" #include "error.h" -void *nasm_malloc(size_t size) +static no_return nasm_alloc_failed(void) +{ + nasm_fatal(0, "out of memory"); +} + +static inline void *validate_ptr(void *p) { - void *p = malloc(size); - if (!p) - nasm_fatal(ERR_NOFILE, "out of memory"); + if (unlikely(!p)) + nasm_alloc_failed(); return p; } +void *nasm_malloc(size_t size) +{ + return validate_ptr(malloc(size)); +} + void *nasm_calloc(size_t size, size_t nelem) { - void *p = calloc(size, nelem); - if (!p) - nasm_fatal(ERR_NOFILE, "out of memory"); - return p; + return validate_ptr(calloc(size, nelem)); } void *nasm_zalloc(size_t size) { - return nasm_calloc(size, 1); + return validate_ptr(calloc(1, size)); } void *nasm_realloc(void *q, size_t size) { - void *p = q ? realloc(q, size) : malloc(size); - if (!p) - nasm_fatal(ERR_NOFILE, "out of memory"); - return p; + return validate_ptr(q ? realloc(q, size) : malloc(size)); } void nasm_free(void *q) @@ -106,3 +109,55 @@ char *nasm_strcat(const char *one, const char *two) memcpy(rslt + l1, two, l2+1); return rslt; } + +char *nasm_strcatn(const char *str1, ...) +{ + va_list ap; + char *rslt; /* Output buffer */ + size_t s; /* Total buffer size */ + size_t n; /* Number of arguments */ + size_t *ltbl; /* Table of lengths */ + size_t l, *lp; /* Length for current argument */ + const char *p; /* Currently examined argument */ + char *q; /* Output pointer */ + + n = 0; /* No strings encountered yet */ + p = str1; + va_start(ap, str1); + while (p) { + n++; + p = va_arg(ap, const char *); + } + va_end(ap); + + ltbl = nasm_malloc(n * sizeof(size_t)); + + s = 1; /* Space for final NULL */ + p = str1; + lp = ltbl; + va_start(ap, str1); + while (p) { + *lp++ = l = strlen(p); + s += l; + p = va_arg(ap, const char *); + } + va_end(ap); + + q = rslt = nasm_malloc(s); + + p = str1; + lp = ltbl; + va_start(ap, str1); + while (p) { + l = *lp++; + memcpy(q, p, l); + q += l; + p = va_arg(ap, const char *); + } + va_end(ap); + *q = '\0'; + + nasm_free(ltbl); + + return rslt; +} |