summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdlib/malloc.c')
-rw-r--r--lib/libc/stdlib/malloc.c145
1 files changed, 108 insertions, 37 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 6e5d60542ce..aedb4c8f0c0 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -8,7 +8,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: malloc.c,v 1.69 2004/08/04 19:12:53 tdeval Exp $";
+static char rcsid[] = "$OpenBSD: malloc.c,v 1.70 2004/08/05 21:55:21 tdeval Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -424,7 +424,8 @@ wrterror(char *p)
malloc_dump(stderr);
#endif /* MALLOC_STATS */
malloc_active--;
- abort();
+ if (malloc_abort)
+ abort();
}
static void
@@ -533,8 +534,11 @@ map_pages(size_t pages)
pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
}
#ifdef MALLOC_EXTRA_SANITY
- if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index)
+ if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index) {
wrterror("(ES): pages directory overflow\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (index == pidx && pi != last_dir) {
prev_dir = last_dir;
@@ -640,8 +644,11 @@ malloc_init(void)
/* Allocate one page for the page directory */
page_dir = (struct pginfo **) MMAP(malloc_pagesize);
- if (page_dir == MAP_FAILED)
+ if (page_dir == MAP_FAILED) {
wrterror("mmap(2) failed, check limits\n");
+ errno = ENOMEM;
+ return;
+ }
pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
pdi_mod = pdi_off / sizeof(struct pginfo *);
@@ -685,39 +692,55 @@ malloc_pages(size_t size)
size = pageround(size) + malloc_guard;
- if (getrlimit(RLIMIT_DATA, &rl) == -1)
- wrterror("process limits not available\n");
- if (rl.rlim_cur != RLIM_INFINITY &&
- size > ((size_t)rl.rlim_cur - malloc_used)) {
- errno = ENOMEM;
- return (NULL);
- }
-
p = NULL;
/* Look for free pages before asking for more */
for (pf = free_list.next; pf; pf = pf->next) {
#ifdef MALLOC_EXTRA_SANITY
- if (pf->size & malloc_pagemask)
+ if (pf->size & malloc_pagemask) {
wrterror("(ES): junk length entry on free_list\n");
- if (!pf->size)
+ errno = EFAULT;
+ return (NULL);
+ }
+ if (!pf->size) {
wrterror("(ES): zero length entry on free_list\n");
- if (pf->page > (pf->page + pf->size))
+ errno = EFAULT;
+ return (NULL);
+ }
+ if (pf->page > (pf->page + pf->size)) {
wrterror("(ES): sick entry on free_list\n");
- if ((pi = pf->pdir) == NULL)
+ errno = EFAULT;
+ return (NULL);
+ }
+ if ((pi = pf->pdir) == NULL) {
wrterror("(ES): invalid page directory on free-list\n");
- if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum))
+ errno = EFAULT;
+ return (NULL);
+ }
+ if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
wrterror("(ES): directory index mismatch on free-list\n");
+ errno = EFAULT;
+ return (NULL);
+ }
pd = pi->base;
- if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE)
+ if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
wrterror("(ES): non-free first page on free-list\n");
+ errno = EFAULT;
+ return (NULL);
+ }
pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1);
for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): last page not referenced in page directory\n");
+ errno = EFAULT;
+ return (NULL);
+ }
pd = pi->base;
- if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE)
+ if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE) {
wrterror("(ES): non-free last page on free-list\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pf->size < size)
@@ -738,8 +761,11 @@ malloc_pages(size_t size)
pf->size -= size;
pidx = PI_IDX(ptr2index(pf->page));
for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): hole in directories\n");
+ errno = EFAULT;
+ return (NULL);
+ }
tp = pf->pdir;
pf->pdir = pi;
pi = tp;
@@ -753,8 +779,11 @@ malloc_pages(size_t size)
pidx = PD_IDX(pi->dirnum);
pd = pi->base;
}
- if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE)
+ if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
wrterror("(ES): allocated non-free page on free-list\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (p != NULL && (malloc_guard || malloc_freeprot))
@@ -772,8 +801,11 @@ malloc_pages(size_t size)
pidx = PI_IDX(index);
pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pi != last_dir) {
prev_dir = last_dir;
@@ -786,8 +818,11 @@ malloc_pages(size_t size)
pidx++;
pi = pi->next;
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): hole in mapped pages directory\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
pd = pi->base;
}
@@ -798,8 +833,11 @@ malloc_pages(size_t size)
pidx++;
pi = pi->next;
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): hole in mapped pages directory\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
pd = pi->base;
}
@@ -913,8 +951,11 @@ malloc_make_chunks(int bits)
pidx = PI_IDX(ptr2index(pp));
pdir_lookup(ptr2index(pp), &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return (0);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pi != last_dir) {
prev_dir = last_dir;
@@ -988,8 +1029,11 @@ malloc_bytes(size_t size)
k = 0;
}
#ifdef MALLOC_EXTRA_SANITY
- if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
+ if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
wrterror("chunk overflow\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (*lp & u)
i--;
@@ -1081,8 +1125,11 @@ irealloc(void *ptr, size_t size)
pidx = PI_IDX(index);
pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return (NULL);
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pi != last_dir) {
prev_dir = last_dir;
@@ -1212,8 +1259,11 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
pidx = PI_IDX(index);
pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
spi = pi; /* Save page index for start of region. */
@@ -1247,8 +1297,11 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
malloc_used -= l;
if (malloc_guard) {
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
+ if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) {
wrterror("(ES): hole in mapped pages directory\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
pd[PI_OFF(index+i)] = MALLOC_FREE;
l += malloc_guard;
@@ -1320,6 +1373,8 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
px = NULL;
} else {
wrterror("freelist is destroyed\n");
+ errno = EFAULT;
+ return;
}
}
@@ -1360,8 +1415,11 @@ free_pages(void *ptr, u_long index, struct pginfo *info)
if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
pd[PI_OFF(i)] = MALLOC_NOT_MINE;
#ifdef MALLOC_EXTRA_SANITY
- if (!PD_OFF(pi->dirnum))
+ if (!PD_OFF(pi->dirnum)) {
wrterror("(ES): pages directory underflow\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
pi->dirnum--;
}
@@ -1452,8 +1510,11 @@ free_bytes(void *ptr, int index, struct pginfo *info)
while (*mp != info) {
mp = &((*mp)->next);
#ifdef MALLOC_EXTRA_SANITY
- if (!*mp)
- wrterror("(ES): Not on queue\n");
+ if (!*mp) {
+ wrterror("(ES): Not on queue\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
}
*mp = info->next;
@@ -1462,8 +1523,11 @@ free_bytes(void *ptr, int index, struct pginfo *info)
pidx = PI_IDX(ptr2index(info->page));
pdir_lookup(ptr2index(info->page), &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pi != last_dir) {
prev_dir = last_dir;
@@ -1522,8 +1586,11 @@ ifree(void *ptr)
pidx = PI_IDX(index);
pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
- if (pi == NULL || PD_IDX(pi->dirnum) != pidx)
+ if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
wrterror("(ES): mapped pages not found in directory\n");
+ errno = EFAULT;
+ return;
+ }
#endif /* MALLOC_EXTRA_SANITY */
if (pi != last_dir) {
prev_dir = last_dir;
@@ -1577,8 +1644,10 @@ malloc(size_t size)
UTRACE(0, size, r);
malloc_active--;
_MALLOC_UNLOCK();
- if (malloc_xmalloc && r == NULL)
+ if (malloc_xmalloc && r == NULL) {
wrterror("out of memory\n");
+ errno = ENOMEM;
+ }
return (r);
}
@@ -1617,7 +1686,9 @@ realloc(void *ptr, size_t size)
UTRACE(ptr, size, r);
malloc_active--;
_MALLOC_UNLOCK();
- if (malloc_xmalloc && r == NULL)
+ if (malloc_xmalloc && r == NULL) {
wrterror("out of memory\n");
+ errno = ENOMEM;
+ }
return (r);
}