Browse Source

print the pointer value that caused the error (if available); ok

deraadt@ nicm@ (on an earlier version)
OPENBSD_4_9
otto 14 years ago
parent
commit
5228178676
1 changed files with 54 additions and 47 deletions
  1. +54
    -47
      src/lib/libc/stdlib/malloc.c

+ 54
- 47
src/lib/libc/stdlib/malloc.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: malloc.c,v 1.125 2010/05/18 22:24:55 tedu Exp $ */
/* $OpenBSD: malloc.c,v 1.126 2010/10/21 08:09:35 otto Exp $ */
/* /*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
* *
@ -352,12 +352,12 @@ malloc_exit(void)
#endif /* MALLOC_STATS */ #endif /* MALLOC_STATS */
static void static void
wrterror(char *p)
wrterror(char *msg, void *p)
{ {
char *q = " error: "; char *q = " error: ";
struct iovec iov[5];
struct iovec iov[6];
char buf[20];
iov[0].iov_base = __progname; iov[0].iov_base = __progname;
iov[0].iov_len = strlen(__progname); iov[0].iov_len = strlen(__progname);
@ -365,11 +365,18 @@ wrterror(char *p)
iov[1].iov_len = strlen(malloc_func); iov[1].iov_len = strlen(malloc_func);
iov[2].iov_base = q; iov[2].iov_base = q;
iov[2].iov_len = strlen(q); iov[2].iov_len = strlen(q);
iov[3].iov_base = p;
iov[3].iov_len = strlen(p);
iov[4].iov_base = "\n";
iov[4].iov_len = 1;
writev(STDERR_FILENO, iov, 5);
iov[3].iov_base = msg;
iov[3].iov_len = strlen(msg);
iov[4].iov_base = buf;
if (p == NULL)
iov[4].iov_len = 0;
else {
snprintf(buf, sizeof(buf), " %p", p);
iov[4].iov_len = strlen(buf);
}
iov[5].iov_base = "\n";
iov[5].iov_len = 1;
writev(STDERR_FILENO, iov, 6);
#ifdef MALLOC_STATS #ifdef MALLOC_STATS
if (mopts.malloc_stats) if (mopts.malloc_stats)
@ -414,13 +421,13 @@ unmap(struct dir_info *d, void *p, size_t sz)
u_int i, offset; u_int i, offset;
if (sz != PAGEROUND(sz)) { if (sz != PAGEROUND(sz)) {
wrterror("munmap round");
wrterror("munmap round", NULL);
return; return;
} }
if (psz > mopts.malloc_cache) { if (psz > mopts.malloc_cache) {
if (munmap(p, sz)) if (munmap(p, sz))
wrterror("munmap");
wrterror("munmap", p);
malloc_used -= sz; malloc_used -= sz;
return; return;
} }
@ -434,7 +441,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
if (r->p != NULL) { if (r->p != NULL) {
rsz = r->size << MALLOC_PAGESHIFT; rsz = r->size << MALLOC_PAGESHIFT;
if (munmap(r->p, rsz)) if (munmap(r->p, rsz))
wrterror("munmap");
wrterror("munmap", r->p);
r->p = NULL; r->p = NULL;
if (tounmap > r->size) if (tounmap > r->size)
tounmap -= r->size; tounmap -= r->size;
@ -446,7 +453,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
} }
} }
if (tounmap > 0) if (tounmap > 0)
wrterror("malloc cache underflow");
wrterror("malloc cache underflow", NULL);
for (i = 0; i < mopts.malloc_cache; i++) { for (i = 0; i < mopts.malloc_cache; i++) {
r = &d->free_regions[i]; r = &d->free_regions[i];
if (r->p == NULL) { if (r->p == NULL) {
@ -461,9 +468,9 @@ unmap(struct dir_info *d, void *p, size_t sz)
} }
} }
if (i == mopts.malloc_cache) if (i == mopts.malloc_cache)
wrterror("malloc free slot lost");
wrterror("malloc free slot lost", NULL);
if (d->free_regions_size > mopts.malloc_cache) if (d->free_regions_size > mopts.malloc_cache)
wrterror("malloc cache overflow");
wrterror("malloc cache overflow", NULL);
} }
static void static void
@ -478,7 +485,7 @@ zapcacheregion(struct dir_info *d, void *p)
if (r->p == p) { if (r->p == p) {
rsz = r->size << MALLOC_PAGESHIFT; rsz = r->size << MALLOC_PAGESHIFT;
if (munmap(r->p, rsz)) if (munmap(r->p, rsz))
wrterror("munmap");
wrterror("munmap", r->p);
r->p = NULL; r->p = NULL;
d->free_regions_size -= r->size; d->free_regions_size -= r->size;
r->size = 0; r->size = 0;
@ -497,9 +504,9 @@ map(struct dir_info *d, size_t sz, int zero_fill)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt");
wrterror("internal struct corrupt", NULL);
if (sz != PAGEROUND(sz)) { if (sz != PAGEROUND(sz)) {
wrterror("map round");
wrterror("map round", NULL);
return NULL; return NULL;
} }
if (psz > d->free_regions_size) { if (psz > d->free_regions_size) {
@ -551,7 +558,7 @@ map(struct dir_info *d, size_t sz, int zero_fill)
if (p != MAP_FAILED) if (p != MAP_FAILED)
malloc_used += sz; malloc_used += sz;
if (d->free_regions_size > mopts.malloc_cache) if (d->free_regions_size > mopts.malloc_cache)
wrterror("malloc cache");
wrterror("malloc cache", NULL);
/* zero fill not needed */ /* zero fill not needed */
return p; return p;
} }
@ -724,7 +731,7 @@ omalloc_init(struct dir_info **dp)
regioninfo_size = d->regions_total * sizeof(struct region_info); regioninfo_size = d->regions_total * sizeof(struct region_info);
d->r = MMAP(regioninfo_size); d->r = MMAP(regioninfo_size);
if (d->r == MAP_FAILED) { if (d->r == MAP_FAILED) {
wrterror("malloc init mmap failed");
wrterror("malloc init mmap failed", NULL);
d->regions_total = 0; d->regions_total = 0;
return 1; return 1;
} }
@ -787,7 +794,7 @@ omalloc_grow(struct dir_info *d)
} }
/* avoid pages containing meta info to end up in cache */ /* avoid pages containing meta info to end up in cache */
if (munmap(d->r, d->regions_total * sizeof(struct region_info))) if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
wrterror("munmap");
wrterror("munmap", d->r);
else else
malloc_used -= d->regions_total * sizeof(struct region_info); malloc_used -= d->regions_total * sizeof(struct region_info);
d->regions_free = d->regions_free + d->regions_total; d->regions_free = d->regions_free + d->regions_total;
@ -853,7 +860,7 @@ find(struct dir_info *d, void *p)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt");
wrterror("internal struct corrupt", NULL);
p = MASK_POINTER(p); p = MASK_POINTER(p);
index = hash(p) & mask; index = hash(p) & mask;
r = d->r[index].p; r = d->r[index].p;
@ -876,7 +883,7 @@ delete(struct dir_info *d, struct region_info *ri)
size_t i, j, r; size_t i, j, r;
if (d->regions_total & (d->regions_total - 1)) if (d->regions_total & (d->regions_total - 1))
wrterror("regions_total not 2^x");
wrterror("regions_total not 2^x", NULL);
d->regions_free++; d->regions_free++;
STATS_INC(g_pool->deletes); STATS_INC(g_pool->deletes);
@ -960,7 +967,7 @@ omalloc_make_chunks(struct dir_info *d, int bits)
bits++; bits++;
if ((uintptr_t)pp & bits) if ((uintptr_t)pp & bits)
wrterror("pp & bits");
wrterror("pp & bits", pp);
insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp); insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp);
return bp; return bp;
@ -980,7 +987,7 @@ malloc_bytes(struct dir_info *d, size_t size)
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2) d->canary1 != ~d->canary2)
wrterror("internal struct corrupt");
wrterror("internal struct corrupt", NULL);
/* Don't bother with anything less than this */ /* Don't bother with anything less than this */
/* unless we have a malloc(0) requests */ /* unless we have a malloc(0) requests */
if (size != 0 && size < MALLOC_MINSIZE) if (size != 0 && size < MALLOC_MINSIZE)
@ -1005,7 +1012,7 @@ malloc_bytes(struct dir_info *d, size_t size)
bp = LIST_FIRST(&d->chunk_dir[j]); bp = LIST_FIRST(&d->chunk_dir[j]);
if (bp->canary != d->canary1) if (bp->canary != d->canary1)
wrterror("chunk info corrupted");
wrterror("chunk info corrupted", NULL);
/* Find first word of bitmap which isn't empty */ /* Find first word of bitmap which isn't empty */
for (lp = bp->bits; !*lp; lp++) for (lp = bp->bits; !*lp; lp++)
/* EMPTY */; /* EMPTY */;
@ -1029,7 +1036,7 @@ malloc_bytes(struct dir_info *d, size_t size)
k = 0; k = 0;
} }
if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) { if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
wrterror("chunk overflow");
wrterror("chunk overflow", NULL);
errno = EFAULT; errno = EFAULT;
return (NULL); return (NULL);
} }
@ -1065,17 +1072,17 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
info = (struct chunk_info *)r->size; info = (struct chunk_info *)r->size;
if (info->canary != d->canary1) if (info->canary != d->canary1)
wrterror("chunk info corrupted");
wrterror("chunk info corrupted", NULL);
/* Find the chunk number on the page */ /* Find the chunk number on the page */
i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
if ((uintptr_t)ptr & ((1UL << (info->shift)) - 1)) { if ((uintptr_t)ptr & ((1UL << (info->shift)) - 1)) {
wrterror("modified chunk-pointer");
wrterror("modified chunk-pointer", ptr);
return; return;
} }
if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) { if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
wrterror("chunk is already free");
wrterror("chunk is already free", ptr);
return; return;
} }
@ -1133,7 +1140,7 @@ omalloc(size_t sz, int zero_fill)
if (mopts.malloc_guard) { if (mopts.malloc_guard) {
if (mprotect((char *)p + psz - mopts.malloc_guard, if (mprotect((char *)p + psz - mopts.malloc_guard,
mopts.malloc_guard, PROT_NONE)) mopts.malloc_guard, PROT_NONE))
wrterror("mprotect");
wrterror("mprotect", NULL);
malloc_guarded += mopts.malloc_guard; malloc_guarded += mopts.malloc_guard;
} }
@ -1182,7 +1189,7 @@ malloc_recurse(void)
if (noprint == 0) { if (noprint == 0) {
noprint = 1; noprint = 1;
wrterror("recursive call");
wrterror("recursive call", NULL);
} }
malloc_active--; malloc_active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
@ -1195,7 +1202,7 @@ malloc_init(void)
if (omalloc_init(&g_pool)) { if (omalloc_init(&g_pool)) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (mopts.malloc_xmalloc) if (mopts.malloc_xmalloc)
wrterror("out of memory");
wrterror("out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@ -1222,7 +1229,7 @@ malloc(size_t size)
malloc_active--; malloc_active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory");
wrterror("out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)
@ -1238,7 +1245,7 @@ ofree(void *p)
r = find(g_pool, p); r = find(g_pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)");
wrterror("bogus pointer (double free?)", p);
return; return;
} }
REALSIZE(sz, r); REALSIZE(sz, r);
@ -1246,7 +1253,7 @@ ofree(void *p)
if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
MALLOC_LEEWAY) { MALLOC_LEEWAY) {
if (r->p != p) { if (r->p != p) {
wrterror("bogus pointer");
wrterror("bogus pointer", p);
return; return;
} }
} else { } else {
@ -1261,12 +1268,12 @@ ofree(void *p)
} }
if (mopts.malloc_guard) { if (mopts.malloc_guard) {
if (sz < mopts.malloc_guard) if (sz < mopts.malloc_guard)
wrterror("guard size");
wrterror("guard size", NULL);
if (!mopts.malloc_freeprot) { if (!mopts.malloc_freeprot) {
if (mprotect((char *)p + PAGEROUND(sz) - if (mprotect((char *)p + PAGEROUND(sz) -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_READ | PROT_WRITE)) PROT_READ | PROT_WRITE))
wrterror("mprotect");
wrterror("mprotect", NULL);
} }
malloc_guarded -= mopts.malloc_guard; malloc_guarded -= mopts.malloc_guard;
} }
@ -1290,7 +1297,7 @@ ofree(void *p)
if (p != NULL) { if (p != NULL) {
r = find(g_pool, p); r = find(g_pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)");
wrterror("bogus pointer (double free?)", p);
return; return;
} }
free_bytes(g_pool, r, p); free_bytes(g_pool, r, p);
@ -1311,7 +1318,7 @@ free(void *ptr)
malloc_func = " in free():"; malloc_func = " in free():";
if (g_pool == NULL) { if (g_pool == NULL) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
wrterror("free() called before allocation");
wrterror("free() called before allocation", NULL);
return; return;
} }
if (malloc_active++) { if (malloc_active++) {
@ -1337,7 +1344,7 @@ orealloc(void *p, size_t newsz)
r = find(g_pool, p); r = find(g_pool, p);
if (r == NULL) { if (r == NULL) {
wrterror("bogus pointer (double free?)");
wrterror("bogus pointer (double free?)", p);
return NULL; return NULL;
} }
if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
@ -1349,7 +1356,7 @@ orealloc(void *p, size_t newsz)
goldsz = oldsz; goldsz = oldsz;
if (oldsz > MALLOC_MAXCHUNK) { if (oldsz > MALLOC_MAXCHUNK) {
if (oldsz < mopts.malloc_guard) if (oldsz < mopts.malloc_guard)
wrterror("guard size");
wrterror("guard size", NULL);
oldsz -= mopts.malloc_guard; oldsz -= mopts.malloc_guard;
} }
@ -1383,11 +1390,11 @@ orealloc(void *p, size_t newsz)
if (mprotect((char *)p + roldsz - if (mprotect((char *)p + roldsz -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_READ | PROT_WRITE)) PROT_READ | PROT_WRITE))
wrterror("mprotect");
wrterror("mprotect", NULL);
if (mprotect((char *)p + rnewsz - if (mprotect((char *)p + rnewsz -
mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard, mopts.malloc_guard,
PROT_NONE)) PROT_NONE))
wrterror("mprotect");
wrterror("mprotect", NULL);
} }
unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz); unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz);
r->size = gnewsz; r->size = gnewsz;
@ -1437,7 +1444,7 @@ realloc(void *ptr, size_t size)
malloc_active--; malloc_active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory");
wrterror("out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)
@ -1464,7 +1471,7 @@ calloc(size_t nmemb, size_t size)
nmemb > 0 && SIZE_MAX / nmemb < size) { nmemb > 0 && SIZE_MAX / nmemb < size) {
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (mopts.malloc_xmalloc) if (mopts.malloc_xmalloc)
wrterror("out of memory");
wrterror("out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
@ -1480,7 +1487,7 @@ calloc(size_t nmemb, size_t size)
malloc_active--; malloc_active--;
_MALLOC_UNLOCK(); _MALLOC_UNLOCK();
if (r == NULL && mopts.malloc_xmalloc) { if (r == NULL && mopts.malloc_xmalloc) {
wrterror("out of memory");
wrterror("out of memory", NULL);
errno = ENOMEM; errno = ENOMEM;
} }
if (r != NULL) if (r != NULL)


Loading…
Cancel
Save