summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2018-05-30 11:40:42 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2018-05-30 11:40:42 -0700
commit740ec3572bb4a587a287cdcea201f12fa5f00501 (patch)
treefb7ce904917389d2ddfd8ed7a31c28f7c2490781
parent1ce81e10effa327362e8cdd316f6ea57c8324ce0 (diff)
downloadnasm-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.m47
-rw-r--r--configure.ac1
-rw-r--r--include/compiler.h8
-rw-r--r--include/nasmlib.h4
-rw-r--r--nasmlib/malloc.c87
5 files changed, 85 insertions, 22 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index 36d36cf8..1af2dd5d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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;
+}