diff options
author | otto <> | 2016-10-20 11:29:34 +0000 |
---|---|---|
committer | otto <> | 2016-10-20 11:29:34 +0000 |
commit | be49b9f329d0953deecf9a4850eb01932940ec94 (patch) | |
tree | 648d20eb6112d47f4de088162b9888f5c912f0ed /src | |
parent | 2beb49e605c928d344eea1d603b030942cc35d21 (diff) | |
download | openbsd-be49b9f329d0953deecf9a4850eb01932940ec94.tar.gz openbsd-be49b9f329d0953deecf9a4850eb01932940ec94.tar.bz2 openbsd-be49b9f329d0953deecf9a4850eb01932940ec94.zip |
backout for now; flag combination GC is not ok
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 213 |
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 { | |||
200 | char *malloc_options; /* compile-time options */ | 199 | char *malloc_options; /* compile-time options */ |
201 | 200 | ||
202 | static u_char getrbyte(struct dir_info *d); | 201 | static u_char getrbyte(struct dir_info *d); |
203 | static __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 |
207 | void malloc_dump(int, struct dir_info *); | 204 | void malloc_dump(int, struct dir_info *); |
@@ -264,26 +261,40 @@ struct dir_info *getpool(void) | |||
264 | } | 261 | } |
265 | 262 | ||
266 | static __dead void | 263 | static __dead void |
267 | wrterror(struct dir_info *d, char *msg, ...) | 264 | wrterror(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 | ||
390 | static void | 401 | static 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 | ||
1037 | static void | ||
1038 | validate_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 | |||
1056 | static uint32_t | 1048 | static uint32_t |
1057 | find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check) | 1049 | find_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 | 1389 | done: | |
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 | } |