From e3bc22f1eff87b8f029a6ab31f1a269d69e4b053 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 14 Jun 2015 01:59:02 +0000 Subject: refactor malloc's expand_heap to share with __simple_malloc this extends the brk/stack collision protection added to full malloc in commit 276904c2f6bde3a31a24ebfa201482601d18b4f9 to also protect the __simple_malloc function used in static-linked programs that don't reference the free function. it also extends support for using mmap when brk fails, which full malloc got in commit 5446303328adf4b4e36d9fba21848e6feb55fab4, to __simple_malloc. since __simple_malloc may expand the heap by arbitrarily large increments, the stack collision detection is enhanced to detect interval overlap rather than just proximity of a single address to the stack. code size is increased a bit, but this is partly offset by the sharing of code between the two malloc implementations, which due to linking semantics, both get linked in a program that needs the full malloc with realloc/free support. --- src/malloc/lite_malloc.c | 49 +++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'src/malloc/lite_malloc.c') diff --git a/src/malloc/lite_malloc.c b/src/malloc/lite_malloc.c index 7643fc2c..008549d6 100644 --- a/src/malloc/lite_malloc.c +++ b/src/malloc/lite_malloc.c @@ -4,43 +4,46 @@ #include #include "libc.h" -uintptr_t __brk(uintptr_t); - #define ALIGN 16 +void *__expand_heap(size_t *); + void *__simple_malloc(size_t n) { - static uintptr_t cur, brk; - uintptr_t base, new; + static char *cur, *end; static volatile int lock[2]; - size_t align=1; + size_t align=1, pad; + void *p; if (!n) n++; - if (n > SIZE_MAX/2) goto toobig; - while (align SIZE_MAX - PAGE_SIZE - base) goto fail; - if (base+n > brk) { - new = base+n + PAGE_SIZE-1 & -PAGE_SIZE; - if (__brk(new) != new) goto fail; - brk = new; - } - cur = base+n; - UNLOCK(lock); - return (void *)base; + pad = -(uintptr_t)cur & align-1; + + if (n <= SIZE_MAX/2 + ALIGN) n += pad; + + if (n > end-cur) { + size_t m = n; + char *new = __expand_heap(&m); + if (!new) { + UNLOCK(lock); + return 0; + } + if (new != end) { + cur = new; + n -= pad; + pad = 0; + } + end = new + m; + } -fail: + p = cur + pad; + cur += n; UNLOCK(lock); -toobig: - errno = ENOMEM; - return 0; + return p; } weak_alias(__simple_malloc, malloc); -- cgit v1.2.1