summaryrefslogtreecommitdiff
path: root/src/malloc/lite_malloc.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-06-14 01:59:02 +0000
committerRich Felker <dalias@aerifal.cx>2015-06-14 01:59:02 +0000
commite3bc22f1eff87b8f029a6ab31f1a269d69e4b053 (patch)
treed0fc5ca6b5a1a5740f739a37ff5d8c7446fbfd9a /src/malloc/lite_malloc.c
parent4ef9b828c1f39553a69e0635ac91f0fcadd6e8c6 (diff)
downloadmusl-e3bc22f1eff87b8f029a6ab31f1a269d69e4b053.tar.gz
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.
Diffstat (limited to 'src/malloc/lite_malloc.c')
-rw-r--r--src/malloc/lite_malloc.c49
1 files changed, 26 insertions, 23 deletions
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 <errno.h>
#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<n && align<ALIGN)
align += align;
- n = n + align - 1 & -align;
LOCK(lock);
- if (!cur) cur = brk = __brk(0)+16;
- base = cur + align-1 & -align;
- if (n > 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);