Don't try to memset NULL if allocation fails.

Always emit UTRACE records, even for failed allocations.
When allocating more than was requested, fill the slop with garbage.
This commit is contained in:
Dag-Erling Smørgrav 2016-02-19 12:23:17 +01:00
parent 1d0f2a4ff3
commit 4d1703c77a

View file

@ -200,21 +200,33 @@ static void *
t_malloc_mapped(size_t size) t_malloc_mapped(size_t size)
{ {
struct mapping *m; struct mapping *m;
size_t msize;
/* prepare metadata */
if ((m = malloc(sizeof *m)) == NULL) if ((m = malloc(sizeof *m)) == NULL)
return (NULL); return (NULL);
size = ((size + 8191) >> 13) << 13; msize = ((size + 8191) >> 13) << 13;
m->base = mmap(NULL, size, PROT_READ | PROT_WRITE,
/* map a sufficiently large region */
m->base = mmap(NULL, msize, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_NOSYNC | MAP_SHARED, -1, 0); MAP_ANON | MAP_NOSYNC | MAP_SHARED, -1, 0);
if (m->base == MAP_FAILED) { if (m->base == MAP_FAILED) {
free(m); free(m);
errno = ENOMEM; errno = ENOMEM;
return (NULL); return (NULL);
} }
m->top = PADD(m->base, size); m->top = PADD(m->base, msize);
/* insert into linked list */
m->next = mappings; m->next = mappings;
m->prev = NULL; m->prev = NULL;
mappings = m; mappings = m;
/* fill the slop */
if (msize > size)
memset(PADD(m->base, size), BUCKET_FILL_FREE, msize - size);
/* done! */
++nmapalloc; ++nmapalloc;
return (m->base); return (m->base);
} }
@ -229,6 +241,7 @@ t_malloc_bucket(size_t size)
{ {
unsigned int shift; unsigned int shift;
struct bucket *b; struct bucket *b;
size_t msize;
void *p; void *p;
/* select bucket */ /* select bucket */
@ -236,6 +249,7 @@ t_malloc_bucket(size_t size)
/* nothing */ ; /* nothing */ ;
assert(shift >= BUCKET_MIN_SHIFT && shift <= BUCKET_MAX_SHIFT); assert(shift >= BUCKET_MIN_SHIFT && shift <= BUCKET_MAX_SHIFT);
b = &buckets[shift]; b = &buckets[shift];
msize = 1U << shift;
/* initialize bucket if necessary */ /* initialize bucket if necessary */
if (b->base == NULL) { if (b->base == NULL) {
@ -259,13 +273,17 @@ t_malloc_bucket(size_t size)
/* update the free block pointer */ /* update the free block pointer */
if (b->free == b->unused) { if (b->free == b->unused) {
/* never been used before, increment free pointer */ /* never been used before, increment free pointer */
b->free = b->unused = b->unused + (1U << shift); b->free = b->unused = b->unused + msize;
} else { } else {
/* previously used, disconnect from free list */ /* previously used, disconnect from free list */
b->free = *(char **)p; b->free = *(char **)p;
assert(b->free >= b->base && b->free < b->top); assert(b->free >= b->base && b->free < b->top);
} }
/* fill the slop */
if (msize > size)
memset(PADD(p, size), BUCKET_FILL_FREE, msize - size);
/* done! */ /* done! */
++b->nalloc; ++b->nalloc;
return (p); return (p);
@ -305,11 +323,13 @@ malloc(size_t size)
t_malloc_fail = 1; t_malloc_fail = 1;
} }
p = t_malloc(size); p = t_malloc(size);
if (p == NULL && t_malloc_fatal)
abort();
memset(p, BUCKET_FILL_ALLOC, size);
/* XXX fill the slop with garbage */
UTRACE_MALLOC(size, p); UTRACE_MALLOC(size, p);
if (p == NULL) {
if (t_malloc_fatal)
abort();
return (NULL);
}
memset(p, BUCKET_FILL_ALLOC, size);
return (p); return (p);
} }
@ -329,11 +349,13 @@ calloc(size_t n, size_t size)
t_malloc_fail = 1; t_malloc_fail = 1;
} }
p = t_malloc(n * size); p = t_malloc(n * size);
if (p == NULL && t_malloc_fatal)
abort();
memset(p, 0, n * size);
/* XXX fill the slop with garbage */
UTRACE_MALLOC(size, p); UTRACE_MALLOC(size, p);
if (p == NULL) {
if (t_malloc_fatal)
abort();
return (NULL);
}
memset(p, 0, n * size);
return (p); return (p);
} }
@ -387,17 +409,19 @@ found:
} else if (t_malloc_fail_after > 0 && --t_malloc_fail_after == 0) { } else if (t_malloc_fail_after > 0 && --t_malloc_fail_after == 0) {
t_malloc_fail = 1; t_malloc_fail = 1;
} }
if ((p = t_malloc(size)) == NULL) { p = t_malloc(size);
UTRACE_REALLOC(o, size, p);
if (p == NULL) {
if (t_malloc_fatal) if (t_malloc_fatal)
abort(); abort();
return (NULL); return (NULL);
} }
if (size > osize) if (size > osize) {
memcpy(p, o, osize); memcpy(p, o, osize);
else memset(p + osize, BUCKET_FILL_ALLOC, size - osize);
} else {
memcpy(p, o, size); memcpy(p, o, size);
/* XXX fill the slop with garbage */ }
UTRACE_REALLOC(o, size, p);
free(o); free(o);
return (p); return (p);
} }