summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/malloc.c213
1 files changed, 103 insertions, 110 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 2a05d806d2..24610db9c5 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc.c,v 1.203 2016/10/20 05:38:41 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.204 2016/10/20 11:29:34 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -31,7 +31,6 @@
31#include <sys/mman.h> 31#include <sys/mman.h>
32#include <sys/uio.h> 32#include <sys/uio.h>
33#include <errno.h> 33#include <errno.h>
34#include <stdarg.h>
35#include <stdint.h> 34#include <stdint.h>
36#include <stdlib.h> 35#include <stdlib.h>
37#include <string.h> 36#include <string.h>
@@ -200,8 +199,6 @@ static union {
200char *malloc_options; /* compile-time options */ 199char *malloc_options; /* compile-time options */
201 200
202static u_char getrbyte(struct dir_info *d); 201static u_char getrbyte(struct dir_info *d);
203static __dead void wrterror(struct dir_info *d, char *msg, ...)
204 __attribute__((__format__ (printf, 2, 3)));
205 202
206#ifdef MALLOC_STATS 203#ifdef MALLOC_STATS
207void malloc_dump(int, struct dir_info *); 204void malloc_dump(int, struct dir_info *);
@@ -264,26 +261,40 @@ struct dir_info *getpool(void)
264} 261}
265 262
266static __dead void 263static __dead void
267wrterror(struct dir_info *d, char *msg, ...) 264wrterror(struct dir_info *d, char *msg, void *p)
268{ 265{
269 struct iovec iov[3]; 266 char *q = " error: ";
270 char pidbuf[80]; 267 struct iovec iov[7];
271 char buf[80]; 268 char pidbuf[20];
272 int saved_errno = errno, ret; 269 char buf[20];
273 va_list ap; 270 int saved_errno = errno, i;
274 271
275 iov[0].iov_base = pidbuf; 272 iov[0].iov_base = __progname;
276 ret = snprintf(pidbuf, sizeof(pidbuf), "%.50s(%d) in %s(): ", 273 iov[0].iov_len = strlen(__progname);
277 __progname, getpid(), d->func ? d->func : "unknown"); 274 iov[1].iov_base = pidbuf;
278 iov[0].iov_len = ret > 0 ? strlen(pidbuf) : 0; 275 snprintf(pidbuf, sizeof(pidbuf), "(%d) in ", getpid());
279 iov[1].iov_base = buf; 276 iov[1].iov_len = strlen(pidbuf);
280 va_start(ap, msg); 277 if (d != NULL) {
281 ret = vsnprintf(buf, sizeof(buf), msg, ap); 278 iov[2].iov_base = d->func;
282 va_end(ap); 279 iov[2].iov_len = strlen(d->func);
283 iov[1].iov_len = ret > 0 ? strlen(buf) : 0; 280 } else {
284 iov[2].iov_base = "\n"; 281 iov[2].iov_base = "unknown";
285 iov[2].iov_len = 1; 282 iov[2].iov_len = 7;
286 writev(STDERR_FILENO, iov, 3); 283 }
284 iov[3].iov_base = q;
285 iov[3].iov_len = strlen(q);
286 iov[4].iov_base = msg;
287 iov[4].iov_len = strlen(msg);
288 iov[5].iov_base = buf;
289 if (p == NULL)
290 iov[5].iov_len = 0;
291 else {
292 snprintf(buf, sizeof(buf), " %010p", p);
293 iov[5].iov_len = strlen(buf);
294 }
295 iov[6].iov_base = "\n";
296 iov[6].iov_len = 1;
297 writev(STDERR_FILENO, iov, 7);
287 298
288#ifdef MALLOC_STATS 299#ifdef MALLOC_STATS
289 if (mopts.malloc_stats) 300 if (mopts.malloc_stats)
@@ -331,12 +342,12 @@ unmap(struct dir_info *d, void *p, size_t sz)
331 u_int i, offset; 342 u_int i, offset;
332 343
333 if (sz != PAGEROUND(sz)) 344 if (sz != PAGEROUND(sz))
334 wrterror(d, "munmap round"); 345 wrterror(d, "munmap round", NULL);
335 346
336 if (psz > mopts.malloc_cache) { 347 if (psz > mopts.malloc_cache) {
337 i = munmap(p, sz); 348 i = munmap(p, sz);
338 if (i) 349 if (i)
339 wrterror(d, "munmap %p", p); 350 wrterror(d, "munmap", p);
340 STATS_SUB(d->malloc_used, sz); 351 STATS_SUB(d->malloc_used, sz);
341 return; 352 return;
342 } 353 }
@@ -350,7 +361,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
350 if (r->p != NULL) { 361 if (r->p != NULL) {
351 rsz = r->size << MALLOC_PAGESHIFT; 362 rsz = r->size << MALLOC_PAGESHIFT;
352 if (munmap(r->p, rsz)) 363 if (munmap(r->p, rsz))
353 wrterror(d, "munmap %p", r->p); 364 wrterror(d, "munmap", r->p);
354 r->p = NULL; 365 r->p = NULL;
355 if (tounmap > r->size) 366 if (tounmap > r->size)
356 tounmap -= r->size; 367 tounmap -= r->size;
@@ -362,7 +373,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
362 } 373 }
363 } 374 }
364 if (tounmap > 0) 375 if (tounmap > 0)
365 wrterror(d, "malloc cache underflow"); 376 wrterror(d, "malloc cache underflow", NULL);
366 for (i = 0; i < mopts.malloc_cache; i++) { 377 for (i = 0; i < mopts.malloc_cache; i++) {
367 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)]; 378 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
368 if (r->p == NULL) { 379 if (r->p == NULL) {
@@ -382,9 +393,9 @@ unmap(struct dir_info *d, void *p, size_t sz)
382 } 393 }
383 } 394 }
384 if (i == mopts.malloc_cache) 395 if (i == mopts.malloc_cache)
385 wrterror(d, "malloc free slot lost"); 396 wrterror(d, "malloc free slot lost", NULL);
386 if (d->free_regions_size > mopts.malloc_cache) 397 if (d->free_regions_size > mopts.malloc_cache)
387 wrterror(d, "malloc cache overflow"); 398 wrterror(d, "malloc cache overflow", NULL);
388} 399}
389 400
390static void 401static void
@@ -399,7 +410,7 @@ zapcacheregion(struct dir_info *d, void *p, size_t len)
399 if (r->p >= p && r->p <= (void *)((char *)p + len)) { 410 if (r->p >= p && r->p <= (void *)((char *)p + len)) {
400 rsz = r->size << MALLOC_PAGESHIFT; 411 rsz = r->size << MALLOC_PAGESHIFT;
401 if (munmap(r->p, rsz)) 412 if (munmap(r->p, rsz))
402 wrterror(d, "munmap %p", r->p); 413 wrterror(d, "munmap", r->p);
403 r->p = NULL; 414 r->p = NULL;
404 d->free_regions_size -= r->size; 415 d->free_regions_size -= r->size;
405 r->size = 0; 416 r->size = 0;
@@ -418,9 +429,9 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill)
418 429
419 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || 430 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
420 d->canary1 != ~d->canary2) 431 d->canary1 != ~d->canary2)
421 wrterror(d, "internal struct corrupt"); 432 wrterror(d, "internal struct corrupt", NULL);
422 if (sz != PAGEROUND(sz)) 433 if (sz != PAGEROUND(sz))
423 wrterror(d, "map round"); 434 wrterror(d, "map round", NULL);
424 435
425 if (!hint && psz > d->free_regions_size) { 436 if (!hint && psz > d->free_regions_size) {
426 _MALLOC_LEAVE(d); 437 _MALLOC_LEAVE(d);
@@ -475,7 +486,7 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill)
475 if (hint) 486 if (hint)
476 return MAP_FAILED; 487 return MAP_FAILED;
477 if (d->free_regions_size > mopts.malloc_cache) 488 if (d->free_regions_size > mopts.malloc_cache)
478 wrterror(d, "malloc cache"); 489 wrterror(d, "malloc cache", NULL);
479 _MALLOC_LEAVE(d); 490 _MALLOC_LEAVE(d);
480 p = MMAP(sz); 491 p = MMAP(sz);
481 _MALLOC_ENTER(d); 492 _MALLOC_ENTER(d);
@@ -662,7 +673,7 @@ omalloc_poolinit(struct dir_info **dp)
662 * lies (subject to alignment by 1 << MALLOC_MINSHIFT) 673 * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
663 */ 674 */
664 if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) 675 if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
665 wrterror(NULL, "malloc init mmap failed"); 676 wrterror(NULL, "malloc init mmap failed", NULL);
666 mprotect(p, MALLOC_PAGESIZE, PROT_NONE); 677 mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
667 mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ, 678 mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
668 MALLOC_PAGESIZE, PROT_NONE); 679 MALLOC_PAGESIZE, PROT_NONE);
@@ -676,7 +687,7 @@ omalloc_poolinit(struct dir_info **dp)
676 d->r = MMAP(regioninfo_size); 687 d->r = MMAP(regioninfo_size);
677 if (d->r == MAP_FAILED) { 688 if (d->r == MAP_FAILED) {
678 d->regions_total = 0; 689 d->regions_total = 0;
679 wrterror(NULL, "malloc init mmap failed"); 690 wrterror(NULL, "malloc init mmap failed", NULL);
680 } 691 }
681 for (i = 0; i <= MALLOC_MAXSHIFT; i++) { 692 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
682 LIST_INIT(&d->chunk_info_list[i]); 693 LIST_INIT(&d->chunk_info_list[i]);
@@ -727,7 +738,7 @@ omalloc_grow(struct dir_info *d)
727 } 738 }
728 /* avoid pages containing meta info to end up in cache */ 739 /* avoid pages containing meta info to end up in cache */
729 if (munmap(d->r, d->regions_total * sizeof(struct region_info))) 740 if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
730 wrterror(d, "munmap %p", d->r); 741 wrterror(d, "munmap", d->r);
731 else 742 else
732 STATS_SUB(d->malloc_used, 743 STATS_SUB(d->malloc_used,
733 d->regions_total * sizeof(struct region_info)); 744 d->regions_total * sizeof(struct region_info));
@@ -817,7 +828,7 @@ find(struct dir_info *d, void *p)
817 828
818 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || 829 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
819 d->canary1 != ~d->canary2) 830 d->canary1 != ~d->canary2)
820 wrterror(d, "internal struct corrupt"); 831 wrterror(d, "internal struct corrupt", NULL);
821 p = MASK_POINTER(p); 832 p = MASK_POINTER(p);
822 index = hash(p) & mask; 833 index = hash(p) & mask;
823 r = d->r[index].p; 834 r = d->r[index].p;
@@ -840,7 +851,7 @@ delete(struct dir_info *d, struct region_info *ri)
840 size_t i, j, r; 851 size_t i, j, r;
841 852
842 if (d->regions_total & (d->regions_total - 1)) 853 if (d->regions_total & (d->regions_total - 1))
843 wrterror(d, "regions_total not 2^x"); 854 wrterror(d, "regions_total not 2^x", NULL);
844 d->regions_free++; 855 d->regions_free++;
845 STATS_INC(d->deletes); 856 STATS_INC(d->deletes);
846 857
@@ -925,7 +936,7 @@ omalloc_make_chunks(struct dir_info *d, int bits, int listnum)
925 936
926 bits++; 937 bits++;
927 if ((uintptr_t)pp & bits) 938 if ((uintptr_t)pp & bits)
928 wrterror(d, "pp & bits %p", pp); 939 wrterror(d, "pp & bits", pp);
929 940
930 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL); 941 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
931 return bp; 942 return bp;
@@ -945,7 +956,7 @@ malloc_bytes(struct dir_info *d, size_t argsize, void *f)
945 956
946 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || 957 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
947 d->canary1 != ~d->canary2) 958 d->canary1 != ~d->canary2)
948 wrterror(d, "internal struct corrupt"); 959 wrterror(d, "internal struct corrupt", NULL);
949 960
950 size = argsize; 961 size = argsize;
951 962
@@ -973,7 +984,7 @@ malloc_bytes(struct dir_info *d, size_t argsize, void *f)
973 } 984 }
974 985
975 if (bp->canary != d->canary1) 986 if (bp->canary != d->canary1)
976 wrterror(d, "chunk info corrupted"); 987 wrterror(d, "chunk info corrupted", NULL);
977 988
978 i = d->chunk_start; 989 i = d->chunk_start;
979 if (bp->free > 1) 990 if (bp->free > 1)
@@ -1034,25 +1045,6 @@ malloc_bytes(struct dir_info *d, size_t argsize, void *f)
1034 return ((char *)bp->page + k); 1045 return ((char *)bp->page + k);
1035} 1046}
1036 1047
1037static void
1038validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
1039{
1040 size_t check_sz = allocated - sz;
1041 u_char *p, *q;
1042
1043 if (check_sz > CHUNK_CHECK_LENGTH)
1044 check_sz = CHUNK_CHECK_LENGTH;
1045 p = (u_char *)ptr + sz;
1046 q = p + check_sz;
1047
1048 while (p < q) {
1049 if (*p++ != SOME_JUNK) {
1050 wrterror(d, "chunk canary corrupted %p %#tx@%#zx",
1051 ptr, p - ptr - 1, sz);
1052 }
1053 }
1054}
1055
1056static uint32_t 1048static uint32_t
1057find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check) 1049find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check)
1058{ 1050{
@@ -1061,20 +1053,32 @@ find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check)
1061 1053
1062 info = (struct chunk_info *)r->size; 1054 info = (struct chunk_info *)r->size;
1063 if (info->canary != d->canary1) 1055 if (info->canary != d->canary1)
1064 wrterror(d, "chunk info corrupted"); 1056 wrterror(d, "chunk info corrupted", NULL);
1065 1057
1066 /* Find the chunk number on the page */ 1058 /* Find the chunk number on the page */
1067 chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; 1059 chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
1068 if (check && mopts.chunk_canaries && info->size > 0) { 1060 if (check && mopts.chunk_canaries && info->size > 0) {
1069 validate_canary(d, ptr, info->bits[info->offset + chunknum], 1061 size_t sz = info->bits[info->offset + chunknum];
1070 info->size); 1062 size_t check_sz = info->size - sz;
1063 u_char *p, *q;
1064
1065 if (check_sz > CHUNK_CHECK_LENGTH)
1066 check_sz = CHUNK_CHECK_LENGTH;
1067 p = (u_char *)ptr + sz;
1068 q = p + check_sz;
1069
1070 while (p < q)
1071 if (*p++ != SOME_JUNK) {
1072 q = (void *)(sz << 16 | p - (u_char *)ptr - 1);
1073 wrterror(d, "chunk canary corrupted: ", q);
1074 }
1071 } 1075 }
1072 1076
1073 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) 1077 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1))
1074 wrterror(d, "modified chunk-pointer %p", ptr); 1078 wrterror(d, "modified chunk-pointer", ptr);
1075 if (info->bits[chunknum / MALLOC_BITS] & 1079 if (info->bits[chunknum / MALLOC_BITS] &
1076 (1U << (chunknum % MALLOC_BITS))) 1080 (1U << (chunknum % MALLOC_BITS)))
1077 wrterror(d, "chunk is already free %p", ptr); 1081 wrterror(d, "chunk is already free", ptr);
1078 return chunknum; 1082 return chunknum;
1079} 1083}
1080 1084
@@ -1152,7 +1156,7 @@ omalloc(struct dir_info *pool, size_t sz, int zero_fill, void *f)
1152 if (mopts.malloc_guard) { 1156 if (mopts.malloc_guard) {
1153 if (mprotect((char *)p + psz - mopts.malloc_guard, 1157 if (mprotect((char *)p + psz - mopts.malloc_guard,
1154 mopts.malloc_guard, PROT_NONE)) 1158 mopts.malloc_guard, PROT_NONE))
1155 wrterror(pool, "mprotect"); 1159 wrterror(pool, "mprotect", NULL);
1156 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard); 1160 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
1157 } 1161 }
1158 1162
@@ -1176,12 +1180,6 @@ omalloc(struct dir_info *pool, size_t sz, int zero_fill, void *f)
1176 else 1180 else
1177 memset(p, SOME_JUNK, 1181 memset(p, SOME_JUNK,
1178 psz - mopts.malloc_guard); 1182 psz - mopts.malloc_guard);
1179 } else if (mopts.chunk_canaries) {
1180 size_t csz = psz - mopts.malloc_guard - sz;
1181
1182 if (csz > CHUNK_CHECK_LENGTH)
1183 csz = CHUNK_CHECK_LENGTH;
1184 memset(p + sz, SOME_JUNK, csz);
1185 } 1183 }
1186 } 1184 }
1187 1185
@@ -1207,7 +1205,7 @@ malloc_recurse(struct dir_info *d)
1207 1205
1208 if (noprint == 0) { 1206 if (noprint == 0) {
1209 noprint = 1; 1207 noprint = 1;
1210 wrterror(d, "recursive call"); 1208 wrterror(d, "recursive call", NULL);
1211 } 1209 }
1212 d->active--; 1210 d->active--;
1213 _MALLOC_UNLOCK(d->mutex); 1211 _MALLOC_UNLOCK(d->mutex);
@@ -1266,7 +1264,7 @@ malloc(size_t size)
1266 d = getpool(); 1264 d = getpool();
1267 } 1265 }
1268 _MALLOC_LOCK(d->mutex); 1266 _MALLOC_LOCK(d->mutex);
1269 d->func = "malloc"; 1267 d->func = "malloc():";
1270 1268
1271 if (d->active++) { 1269 if (d->active++) {
1272 malloc_recurse(d); 1270 malloc_recurse(d);
@@ -1276,7 +1274,7 @@ malloc(size_t size)
1276 d->active--; 1274 d->active--;
1277 _MALLOC_UNLOCK(d->mutex); 1275 _MALLOC_UNLOCK(d->mutex);
1278 if (r == NULL && mopts.malloc_xmalloc) 1276 if (r == NULL && mopts.malloc_xmalloc)
1279 wrterror(d, "out of memory"); 1277 wrterror(d, "out of memory", NULL);
1280 if (r != NULL) 1278 if (r != NULL)
1281 errno = saved_errno; 1279 errno = saved_errno;
1282 return r; 1280 return r;
@@ -1293,13 +1291,13 @@ validate_junk(struct dir_info *pool, void *p)
1293 return; 1291 return;
1294 r = find(pool, p); 1292 r = find(pool, p);
1295 if (r == NULL) 1293 if (r == NULL)
1296 wrterror(pool, "bogus pointer in validate_junk %p", p); 1294 wrterror(pool, "bogus pointer in validate_junk", p);
1297 REALSIZE(sz, r); 1295 REALSIZE(sz, r);
1298 if (sz > CHUNK_CHECK_LENGTH) 1296 if (sz > CHUNK_CHECK_LENGTH)
1299 sz = CHUNK_CHECK_LENGTH; 1297 sz = CHUNK_CHECK_LENGTH;
1300 for (byte = 0; byte < sz; byte++) { 1298 for (byte = 0; byte < sz; byte++) {
1301 if (((unsigned char *)p)[byte] != SOME_FREEJUNK) 1299 if (((unsigned char *)p)[byte] != SOME_FREEJUNK)
1302 wrterror(pool, "use after free %p", p); 1300 wrterror(pool, "use after free", p);
1303 } 1301 }
1304} 1302}
1305 1303
@@ -1329,7 +1327,7 @@ ofree(struct dir_info *argpool, void *p)
1329 } 1327 }
1330 } 1328 }
1331 if (r == NULL) 1329 if (r == NULL)
1332 wrterror(pool, "bogus pointer (double free?) %p", p); 1330 wrterror(pool, "bogus pointer (double free?)", p);
1333 } 1331 }
1334 1332
1335 REALSIZE(sz, r); 1333 REALSIZE(sz, r);
@@ -1337,11 +1335,7 @@ ofree(struct dir_info *argpool, void *p)
1337 if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - 1335 if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
1338 MALLOC_LEEWAY) { 1336 MALLOC_LEEWAY) {
1339 if (r->p != p) 1337 if (r->p != p)
1340 wrterror(pool, "bogus pointer %p", p); 1338 wrterror(pool, "bogus pointer", p);
1341 if (mopts.chunk_canaries)
1342 validate_canary(pool, p,
1343 sz - mopts.malloc_guard,
1344 PAGEROUND(sz - mopts.malloc_guard));
1345 } else { 1339 } else {
1346#if notyetbecause_of_realloc 1340#if notyetbecause_of_realloc
1347 /* shifted towards the end */ 1341 /* shifted towards the end */
@@ -1354,12 +1348,12 @@ ofree(struct dir_info *argpool, void *p)
1354 } 1348 }
1355 if (mopts.malloc_guard) { 1349 if (mopts.malloc_guard) {
1356 if (sz < mopts.malloc_guard) 1350 if (sz < mopts.malloc_guard)
1357 wrterror(pool, "guard size"); 1351 wrterror(pool, "guard size", NULL);
1358 if (!mopts.malloc_freeunmap) { 1352 if (!mopts.malloc_freeunmap) {
1359 if (mprotect((char *)p + PAGEROUND(sz) - 1353 if (mprotect((char *)p + PAGEROUND(sz) -
1360 mopts.malloc_guard, mopts.malloc_guard, 1354 mopts.malloc_guard, mopts.malloc_guard,
1361 PROT_READ | PROT_WRITE)) 1355 PROT_READ | PROT_WRITE))
1362 wrterror(pool, "mprotect"); 1356 wrterror(pool, "mprotect", NULL);
1363 } 1357 }
1364 STATS_SUB(pool->malloc_guarded, mopts.malloc_guard); 1358 STATS_SUB(pool->malloc_guarded, mopts.malloc_guard);
1365 } 1359 }
@@ -1377,7 +1371,7 @@ ofree(struct dir_info *argpool, void *p)
1377 tmp = p; 1371 tmp = p;
1378 p = pool->delayed_chunks[i]; 1372 p = pool->delayed_chunks[i];
1379 if (tmp == p) 1373 if (tmp == p)
1380 wrterror(pool, "double free %p", tmp); 1374 wrterror(pool, "double free", p);
1381 if (mopts.malloc_junk) 1375 if (mopts.malloc_junk)
1382 validate_junk(pool, p); 1376 validate_junk(pool, p);
1383 pool->delayed_chunks[i] = tmp; 1377 pool->delayed_chunks[i] = tmp;
@@ -1388,12 +1382,11 @@ ofree(struct dir_info *argpool, void *p)
1388 if (p != NULL) { 1382 if (p != NULL) {
1389 r = find(pool, p); 1383 r = find(pool, p);
1390 if (r == NULL) 1384 if (r == NULL)
1391 wrterror(pool, 1385 wrterror(pool, "bogus pointer (double free?)", p);
1392 "bogus pointer (double free?) %p", p);
1393 free_bytes(pool, r, p); 1386 free_bytes(pool, r, p);
1394 } 1387 }
1395 } 1388 }
1396 1389done:
1397 if (argpool != pool) { 1390 if (argpool != pool) {
1398 pool->active--; 1391 pool->active--;
1399 _MALLOC_UNLOCK(pool->mutex); 1392 _MALLOC_UNLOCK(pool->mutex);
@@ -1414,9 +1407,9 @@ free(void *ptr)
1414 1407
1415 d = getpool(); 1408 d = getpool();
1416 if (d == NULL) 1409 if (d == NULL)
1417 wrterror(d, "free() called before allocation"); 1410 wrterror(d, "free() called before allocation", NULL);
1418 _MALLOC_LOCK(d->mutex); 1411 _MALLOC_LOCK(d->mutex);
1419 d->func = "free"; 1412 d->func = "free():";
1420 if (d->active++) { 1413 if (d->active++) {
1421 malloc_recurse(d); 1414 malloc_recurse(d);
1422 return; 1415 return;
@@ -1460,7 +1453,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
1460 } 1453 }
1461 } 1454 }
1462 if (r == NULL) 1455 if (r == NULL)
1463 wrterror(pool, "bogus pointer (double free?) %p", p); 1456 wrterror(pool, "bogus pointer (double free?)", p);
1464 } 1457 }
1465 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { 1458 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1466 errno = ENOMEM; 1459 errno = ENOMEM;
@@ -1472,7 +1465,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
1472 goldsz = oldsz; 1465 goldsz = oldsz;
1473 if (oldsz > MALLOC_MAXCHUNK) { 1466 if (oldsz > MALLOC_MAXCHUNK) {
1474 if (oldsz < mopts.malloc_guard) 1467 if (oldsz < mopts.malloc_guard)
1475 wrterror(pool, "guard size"); 1468 wrterror(pool, "guard size", NULL);
1476 oldsz -= mopts.malloc_guard; 1469 oldsz -= mopts.malloc_guard;
1477 } 1470 }
1478 1471
@@ -1481,7 +1474,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
1481 gnewsz += mopts.malloc_guard; 1474 gnewsz += mopts.malloc_guard;
1482 1475
1483 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p && 1476 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
1484 !mopts.chunk_canaries && !mopts.malloc_realloc) { 1477 !mopts.malloc_realloc) {
1485 size_t roldsz = PAGEROUND(goldsz); 1478 size_t roldsz = PAGEROUND(goldsz);
1486 size_t rnewsz = PAGEROUND(gnewsz); 1479 size_t rnewsz = PAGEROUND(gnewsz);
1487 1480
@@ -1512,7 +1505,7 @@ gotit:
1512 goto done; 1505 goto done;
1513 } else if (q != MAP_FAILED) { 1506 } else if (q != MAP_FAILED) {
1514 if (munmap(q, needed)) 1507 if (munmap(q, needed))
1515 wrterror(pool, "munmap %p", q); 1508 wrterror(pool, "munmap", q);
1516 } 1509 }
1517 } 1510 }
1518 } else if (rnewsz < roldsz) { 1511 } else if (rnewsz < roldsz) {
@@ -1520,11 +1513,11 @@ gotit:
1520 if (mprotect((char *)p + roldsz - 1513 if (mprotect((char *)p + roldsz -
1521 mopts.malloc_guard, mopts.malloc_guard, 1514 mopts.malloc_guard, mopts.malloc_guard,
1522 PROT_READ | PROT_WRITE)) 1515 PROT_READ | PROT_WRITE))
1523 wrterror(pool, "mprotect"); 1516 wrterror(pool, "mprotect", NULL);
1524 if (mprotect((char *)p + rnewsz - 1517 if (mprotect((char *)p + rnewsz -
1525 mopts.malloc_guard, mopts.malloc_guard, 1518 mopts.malloc_guard, mopts.malloc_guard,
1526 PROT_NONE)) 1519 PROT_NONE))
1527 wrterror(pool, "mprotect"); 1520 wrterror(pool, "mprotect", NULL);
1528 } 1521 }
1529 unmap(pool, (char *)p + rnewsz, roldsz - rnewsz); 1522 unmap(pool, (char *)p + rnewsz, roldsz - rnewsz);
1530 r->size = gnewsz; 1523 r->size = gnewsz;
@@ -1585,7 +1578,7 @@ realloc(void *ptr, size_t size)
1585 d = getpool(); 1578 d = getpool();
1586 } 1579 }
1587 _MALLOC_LOCK(d->mutex); 1580 _MALLOC_LOCK(d->mutex);
1588 d->func = "realloc"; 1581 d->func = "realloc():";
1589 if (d->active++) { 1582 if (d->active++) {
1590 malloc_recurse(d); 1583 malloc_recurse(d);
1591 return NULL; 1584 return NULL;
@@ -1595,7 +1588,7 @@ realloc(void *ptr, size_t size)
1595 d->active--; 1588 d->active--;
1596 _MALLOC_UNLOCK(d->mutex); 1589 _MALLOC_UNLOCK(d->mutex);
1597 if (r == NULL && mopts.malloc_xmalloc) 1590 if (r == NULL && mopts.malloc_xmalloc)
1598 wrterror(d, "out of memory"); 1591 wrterror(d, "out of memory", NULL);
1599 if (r != NULL) 1592 if (r != NULL)
1600 errno = saved_errno; 1593 errno = saved_errno;
1601 return r; 1594 return r;
@@ -1622,12 +1615,12 @@ calloc(size_t nmemb, size_t size)
1622 d = getpool(); 1615 d = getpool();
1623 } 1616 }
1624 _MALLOC_LOCK(d->mutex); 1617 _MALLOC_LOCK(d->mutex);
1625 d->func = "calloc"; 1618 d->func = "calloc():";
1626 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && 1619 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1627 nmemb > 0 && SIZE_MAX / nmemb < size) { 1620 nmemb > 0 && SIZE_MAX / nmemb < size) {
1628 _MALLOC_UNLOCK(d->mutex); 1621 _MALLOC_UNLOCK(d->mutex);
1629 if (mopts.malloc_xmalloc) 1622 if (mopts.malloc_xmalloc)
1630 wrterror(d, "out of memory"); 1623 wrterror(d, "out of memory", NULL);
1631 errno = ENOMEM; 1624 errno = ENOMEM;
1632 return NULL; 1625 return NULL;
1633 } 1626 }
@@ -1643,7 +1636,7 @@ calloc(size_t nmemb, size_t size)
1643 d->active--; 1636 d->active--;
1644 _MALLOC_UNLOCK(d->mutex); 1637 _MALLOC_UNLOCK(d->mutex);
1645 if (r == NULL && mopts.malloc_xmalloc) 1638 if (r == NULL && mopts.malloc_xmalloc)
1646 wrterror(d, "out of memory"); 1639 wrterror(d, "out of memory", NULL);
1647 if (r != NULL) 1640 if (r != NULL)
1648 errno = saved_errno; 1641 errno = saved_errno;
1649 return r; 1642 return r;
@@ -1656,9 +1649,9 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
1656 char *p, *q; 1649 char *p, *q;
1657 1650
1658 if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) 1651 if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0)
1659 wrterror(d, "mapalign bad alignment"); 1652 wrterror(d, "mapalign bad alignment", NULL);
1660 if (sz != PAGEROUND(sz)) 1653 if (sz != PAGEROUND(sz))
1661 wrterror(d, "mapalign round"); 1654 wrterror(d, "mapalign round", NULL);
1662 1655
1663 /* Allocate sz + alignment bytes of memory, which must include a 1656 /* Allocate sz + alignment bytes of memory, which must include a
1664 * subrange of size bytes that is properly aligned. Unmap the 1657 * subrange of size bytes that is properly aligned. Unmap the
@@ -1675,10 +1668,10 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
1675 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1)); 1668 q = (char *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
1676 if (q != p) { 1669 if (q != p) {
1677 if (munmap(p, q - p)) 1670 if (munmap(p, q - p))
1678 wrterror(d, "munmap %p", p); 1671 wrterror(d, "munmap", p);
1679 } 1672 }
1680 if (munmap(q + sz, alignment - (q - p))) 1673 if (munmap(q + sz, alignment - (q - p)))
1681 wrterror(d, "munmap %p", q + sz); 1674 wrterror(d, "munmap", q + sz);
1682 STATS_SUB(d->malloc_used, alignment); 1675 STATS_SUB(d->malloc_used, alignment);
1683 1676
1684 return q; 1677 return q;
@@ -1723,7 +1716,7 @@ omemalign(struct dir_info *pool, size_t alignment, size_t sz, int zero_fill, voi
1723 if (mopts.malloc_guard) { 1716 if (mopts.malloc_guard) {
1724 if (mprotect((char *)p + psz - mopts.malloc_guard, 1717 if (mprotect((char *)p + psz - mopts.malloc_guard,
1725 mopts.malloc_guard, PROT_NONE)) 1718 mopts.malloc_guard, PROT_NONE))
1726 wrterror(pool, "mprotect"); 1719 wrterror(pool, "mprotect", NULL);
1727 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard); 1720 STATS_ADD(pool->malloc_guarded, mopts.malloc_guard);
1728 } 1721 }
1729 1722
@@ -1755,7 +1748,7 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
1755 d = getpool(); 1748 d = getpool();
1756 } 1749 }
1757 _MALLOC_LOCK(d->mutex); 1750 _MALLOC_LOCK(d->mutex);
1758 d->func = "posix_memalign"; 1751 d->func = "posix_memalign():";
1759 if (d->active++) { 1752 if (d->active++) {
1760 malloc_recurse(d); 1753 malloc_recurse(d);
1761 goto err; 1754 goto err;
@@ -1765,7 +1758,7 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
1765 _MALLOC_UNLOCK(d->mutex); 1758 _MALLOC_UNLOCK(d->mutex);
1766 if (r == NULL) { 1759 if (r == NULL) {
1767 if (mopts.malloc_xmalloc) 1760 if (mopts.malloc_xmalloc)
1768 wrterror(d, "out of memory"); 1761 wrterror(d, "out of memory", NULL);
1769 goto err; 1762 goto err;
1770 } 1763 }
1771 errno = saved_errno; 1764 errno = saved_errno;
@@ -2014,7 +2007,7 @@ malloc_dump(int fd, struct dir_info *pool)
2014 continue; 2007 continue;
2015 r = find(pool, p); 2008 r = find(pool, p);
2016 if (r == NULL) 2009 if (r == NULL)
2017 wrterror(pool, "bogus pointer in malloc_dump %p", p); 2010 wrterror(pool, "bogus pointer in malloc_dump", p);
2018 free_bytes(pool, r, p); 2011 free_bytes(pool, r, p);
2019 pool->delayed_chunks[i] = NULL; 2012 pool->delayed_chunks[i] = NULL;
2020 } 2013 }