aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-16 00:29:04 -0700
committerH. Peter Anvin (Intel) <hpa@zytor.com>2019-08-16 00:41:29 -0700
commit5bb35772b3008805ba7a212d19098cead9abf1d4 (patch)
tree719c01e8d92aa24ec2b8d2d4d5dfc838501e51a0
parent16a3e8ddb9fa6730288a586db34d768d31bd3014 (diff)
downloadnasm-5bb35772b3008805ba7a212d19098cead9abf1d4.tar.gz
nasm-5bb35772b3008805ba7a212d19098cead9abf1d4.tar.xz
nasm-5bb35772b3008805ba7a212d19098cead9abf1d4.zip
BR 3392597: the system malloc() can return NULL
malloc(0) can legitimately return NULL; it does on some systems and not others. Force the size to 1 byte if the size is 0 coming in, except for realloc() where this is legitimate and equivalent to free(). Since this is an abnormal case, and can't even happen with most C libraries, handle it on the error path, after we already got back a NULL pointer. Reported-by: Ozkan Sezer <sezeroz@gmail.com> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r--include/nasmlib.h2
-rw-r--r--nasmlib/alloc.c47
2 files changed, 42 insertions, 7 deletions
diff --git a/include/nasmlib.h b/include/nasmlib.h
index eb3a637d..2e2519f5 100644
--- a/include/nasmlib.h
+++ b/include/nasmlib.h
@@ -109,7 +109,7 @@ static inline size_t nasm_last_string_size(void)
#define nasm_assert_pointer(p) ((void)sizeof(*(p)))
#define nasm_new(p) ((p) = nasm_zalloc(sizeof(*(p))))
-#define nasm_newn(p,n) ((p) = nasm_calloc(sizeof(*(p)),(n)))
+#define nasm_newn(p,n) ((p) = nasm_calloc((n), sizeof(*(p))))
/*
* This is broken on platforms where there are pointers which don't
* match void * in their internal layout. It unfortunately also
diff --git a/nasmlib/alloc.c b/nasmlib/alloc.c
index 4e0ff9fe..b0d623a2 100644
--- a/nasmlib/alloc.c
+++ b/nasmlib/alloc.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -65,22 +65,57 @@ no_return nasm_alloc_failed(void)
void *nasm_malloc(size_t size)
{
- return validate_ptr(malloc(size));
+ void *p;
+
+again:
+ p = malloc(size);
+
+ if (unlikely(!p)) {
+ if (!size) {
+ size = 1;
+ goto again;
+ }
+ nasm_alloc_failed();
+ }
+ return p;
}
-void *nasm_calloc(size_t size, size_t nelem)
+void *nasm_calloc(size_t nelem, size_t size)
{
- return validate_ptr(calloc(size, nelem));
+ void *p;
+
+again:
+ p = calloc(nelem, size);
+
+ if (unlikely(!p)) {
+ if (!nelem || !size) {
+ nelem = size = 1;
+ goto again;
+ }
+ nasm_alloc_failed();
+ }
+
+ return p;
}
void *nasm_zalloc(size_t size)
{
- return validate_ptr(calloc(1, size));
+ return nasm_calloc(size, 1);
}
+/*
+ * Unlike the system realloc, we do *not* allow size == 0 to be
+ * the equivalent to free(); we guarantee returning a non-NULL pointer.
+ *
+ * The check for calling malloc() is theoretically redundant, but be
+ * paranoid about the system library...
+ */
void *nasm_realloc(void *q, size_t size)
{
- return validate_ptr(q ? realloc(q, size) : malloc(size));
+ if (unlikely(!size))
+ size = 1;
+ q = q ? realloc(q, size) : malloc(size);
+ return validate_ptr(q);
}
void nasm_free(void *q)