summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYann Sionneau <yann@sionneau.net>2020-12-20 19:15:14 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2020-12-23 13:39:37 +0100
commit015d5b8c1a75b551f7f0215543fac01d55abfc0f (patch)
tree3e05dba60292a9fd46c9eacdec99a7c7d8a2442f
parent6993d9378224489b49325bd1fb962f0e8bb935f1 (diff)
stdlib: fix potential UB and integer overflow with huge allocations using malloc-simple allocator
Two things are fixed by this commit: 1/ It is wrong to allocate an object of size > PTRDIFF_MAX. It is explained in this thread: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63303 2/ There was a possible integer overflow in both malloc() and memalign() implementations of stdlib/malloc-simple. The malloc() integer overflow issue is fixed by the side effect of fixing the PTRDIFF_MAX issue. The memalign() one is fixed by adding a comparison. Signed-off-by: Yann Sionneau <yann@sionneau.net>
-rw-r--r--libc/stdlib/malloc-simple/alloc.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c
index 3baf75fdd..757a05ecf 100644
--- a/libc/stdlib/malloc-simple/alloc.c
+++ b/libc/stdlib/malloc-simple/alloc.c
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include <malloc.h>
@@ -28,6 +29,15 @@ void *malloc(size_t size)
size++;
}
+ /* prevent Undefined Behaviour for pointer arithmetic (substract) of too big pointers
+ * see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63303
+ * No need to check for size + sizeof(size_t) integer overflow since we already check for PTRDIFF_MAX
+ */
+ if (unlikely(size > PTRDIFF_MAX)) {
+ __set_errno(ENOMEM);
+ return 0;
+ }
+
#ifdef __ARCH_USE_MMU__
# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS
#else
@@ -148,6 +158,16 @@ void * memalign (size_t alignment, size_t size)
void * result;
unsigned long int adj;
+ if (unlikely(size > PTRDIFF_MAX)) {
+ __set_errno(ENOMEM);
+ return NULL;
+ }
+
+ if (unlikely((size + alignment - 1 < size) && (alignment != 0))) {
+ __set_errno(ENOMEM);
+ return NULL;
+ }
+
result = malloc (size + alignment - 1);
if (result == NULL)
return NULL;