diff options
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 83 |
1 files changed, 22 insertions, 61 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index b4c0010f35..9aedc772db 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.192 2016/07/06 20:32:02 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.193 2016/08/17 05:33:54 otto Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> |
| 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> | 4 | * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> |
| @@ -249,7 +249,7 @@ hash(void *p) | |||
| 249 | return sum; | 249 | return sum; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | static void | 252 | __dead static void |
| 253 | wrterror(struct dir_info *d, char *msg, void *p) | 253 | wrterror(struct dir_info *d, char *msg, void *p) |
| 254 | { | 254 | { |
| 255 | char *q = " error: "; | 255 | char *q = " error: "; |
| @@ -329,10 +329,8 @@ unmap(struct dir_info *d, void *p, size_t sz) | |||
| 329 | struct region_info *r; | 329 | struct region_info *r; |
| 330 | u_int i, offset; | 330 | u_int i, offset; |
| 331 | 331 | ||
| 332 | if (sz != PAGEROUND(sz)) { | 332 | if (sz != PAGEROUND(sz)) |
| 333 | wrterror(d, "munmap round", NULL); | 333 | wrterror(d, "munmap round", NULL); |
| 334 | return; | ||
| 335 | } | ||
| 336 | 334 | ||
| 337 | if (psz > mopts.malloc_cache) { | 335 | if (psz > mopts.malloc_cache) { |
| 338 | i = munmap(p, sz); | 336 | i = munmap(p, sz); |
| @@ -415,10 +413,8 @@ map(struct dir_info *d, void *hint, size_t sz, int zero_fill) | |||
| 415 | if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || | 413 | if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) || |
| 416 | d->canary1 != ~d->canary2) | 414 | d->canary1 != ~d->canary2) |
| 417 | wrterror(d, "internal struct corrupt", NULL); | 415 | wrterror(d, "internal struct corrupt", NULL); |
| 418 | if (sz != PAGEROUND(sz)) { | 416 | if (sz != PAGEROUND(sz)) |
| 419 | wrterror(d, "map round", NULL); | 417 | wrterror(d, "map round", NULL); |
| 420 | return MAP_FAILED; | ||
| 421 | } | ||
| 422 | if (!hint && psz > d->free_regions_size) { | 418 | if (!hint && psz > d->free_regions_size) { |
| 423 | _MALLOC_LEAVE(d); | 419 | _MALLOC_LEAVE(d); |
| 424 | p = MMAP(sz); | 420 | p = MMAP(sz); |
| @@ -667,11 +663,9 @@ omalloc_init(struct dir_info **dp) | |||
| 667 | d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS; | 663 | d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS; |
| 668 | regioninfo_size = d->regions_total * sizeof(struct region_info); | 664 | regioninfo_size = d->regions_total * sizeof(struct region_info); |
| 669 | d->r = MMAP(regioninfo_size); | 665 | d->r = MMAP(regioninfo_size); |
| 670 | if (d->r == MAP_FAILED) { | 666 | if (d->r == MAP_FAILED) |
| 671 | wrterror(NULL, "malloc init mmap failed", NULL); | 667 | wrterror(NULL, "malloc init mmap failed", NULL); |
| 672 | d->regions_total = 0; | 668 | |
| 673 | return 1; | ||
| 674 | } | ||
| 675 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { | 669 | for (i = 0; i <= MALLOC_MAXSHIFT; i++) { |
| 676 | LIST_INIT(&d->chunk_info_list[i]); | 670 | LIST_INIT(&d->chunk_info_list[i]); |
| 677 | for (j = 0; j < MALLOC_CHUNK_LISTS; j++) | 671 | for (j = 0; j < MALLOC_CHUNK_LISTS; j++) |
| @@ -1045,15 +1039,11 @@ find_chunknum(struct dir_info *d, struct region_info *r, void *ptr) | |||
| 1045 | /* Find the chunk number on the page */ | 1039 | /* Find the chunk number on the page */ |
| 1046 | chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; | 1040 | chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; |
| 1047 | 1041 | ||
| 1048 | if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) { | 1042 | if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) |
| 1049 | wrterror(d, "modified chunk-pointer", ptr); | 1043 | wrterror(d, "modified chunk-pointer", ptr); |
| 1050 | return -1; | ||
| 1051 | } | ||
| 1052 | if (info->bits[chunknum / MALLOC_BITS] & | 1044 | if (info->bits[chunknum / MALLOC_BITS] & |
| 1053 | (1U << (chunknum % MALLOC_BITS))) { | 1045 | (1U << (chunknum % MALLOC_BITS))) |
| 1054 | wrterror(d, "chunk is already free", ptr); | 1046 | wrterror(d, "chunk is already free", ptr); |
| 1055 | return -1; | ||
| 1056 | } | ||
| 1057 | return chunknum; | 1047 | return chunknum; |
| 1058 | } | 1048 | } |
| 1059 | 1049 | ||
| @@ -1226,10 +1216,8 @@ malloc(size_t size) | |||
| 1226 | r = omalloc(d, size, 0, CALLER); | 1216 | r = omalloc(d, size, 0, CALLER); |
| 1227 | d->active--; | 1217 | d->active--; |
| 1228 | _MALLOC_UNLOCK(); | 1218 | _MALLOC_UNLOCK(); |
| 1229 | if (r == NULL && mopts.malloc_xmalloc) { | 1219 | if (r == NULL && mopts.malloc_xmalloc) |
| 1230 | wrterror(d, "out of memory", NULL); | 1220 | wrterror(d, "out of memory", NULL); |
| 1231 | errno = ENOMEM; | ||
| 1232 | } | ||
| 1233 | if (r != NULL) | 1221 | if (r != NULL) |
| 1234 | errno = saved_errno; | 1222 | errno = saved_errno; |
| 1235 | return r; | 1223 | return r; |
| @@ -1244,20 +1232,16 @@ validate_junk(struct dir_info *pool, void *p) { | |||
| 1244 | if (p == NULL) | 1232 | if (p == NULL) |
| 1245 | return; | 1233 | return; |
| 1246 | r = find(pool, p); | 1234 | r = find(pool, p); |
| 1247 | if (r == NULL) { | 1235 | if (r == NULL) |
| 1248 | wrterror(pool, "bogus pointer in validate_junk", p); | 1236 | wrterror(pool, "bogus pointer in validate_junk", p); |
| 1249 | return; | ||
| 1250 | } | ||
| 1251 | REALSIZE(sz, r); | 1237 | REALSIZE(sz, r); |
| 1252 | if (sz > 0 && sz <= MALLOC_MAXCHUNK) | 1238 | if (sz > 0 && sz <= MALLOC_MAXCHUNK) |
| 1253 | sz -= mopts.malloc_canaries; | 1239 | sz -= mopts.malloc_canaries; |
| 1254 | if (sz > 32) | 1240 | if (sz > 32) |
| 1255 | sz = 32; | 1241 | sz = 32; |
| 1256 | for (byte = 0; byte < sz; byte++) { | 1242 | for (byte = 0; byte < sz; byte++) { |
| 1257 | if (((unsigned char *)p)[byte] != SOME_FREEJUNK) { | 1243 | if (((unsigned char *)p)[byte] != SOME_FREEJUNK) |
| 1258 | wrterror(pool, "use after free", p); | 1244 | wrterror(pool, "use after free", p); |
| 1259 | return; | ||
| 1260 | } | ||
| 1261 | } | 1245 | } |
| 1262 | } | 1246 | } |
| 1263 | 1247 | ||
| @@ -1268,18 +1252,14 @@ ofree(struct dir_info *pool, void *p) | |||
| 1268 | size_t sz; | 1252 | size_t sz; |
| 1269 | 1253 | ||
| 1270 | r = find(pool, p); | 1254 | r = find(pool, p); |
| 1271 | if (r == NULL) { | 1255 | if (r == NULL) |
| 1272 | wrterror(pool, "bogus pointer (double free?)", p); | 1256 | wrterror(pool, "bogus pointer (double free?)", p); |
| 1273 | return; | ||
| 1274 | } | ||
| 1275 | REALSIZE(sz, r); | 1257 | REALSIZE(sz, r); |
| 1276 | if (sz > MALLOC_MAXCHUNK) { | 1258 | if (sz > MALLOC_MAXCHUNK) { |
| 1277 | if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - | 1259 | if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE - |
| 1278 | MALLOC_LEEWAY) { | 1260 | MALLOC_LEEWAY) { |
| 1279 | if (r->p != p) { | 1261 | if (r->p != p) |
| 1280 | wrterror(pool, "bogus pointer", p); | 1262 | wrterror(pool, "bogus pointer", p); |
| 1281 | return; | ||
| 1282 | } | ||
| 1283 | } else { | 1263 | } else { |
| 1284 | #if notyetbecause_of_realloc | 1264 | #if notyetbecause_of_realloc |
| 1285 | /* shifted towards the end */ | 1265 | /* shifted towards the end */ |
| @@ -1320,20 +1300,16 @@ ofree(struct dir_info *pool, void *p) | |||
| 1320 | i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK; | 1300 | i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK; |
| 1321 | tmp = p; | 1301 | tmp = p; |
| 1322 | p = pool->delayed_chunks[i]; | 1302 | p = pool->delayed_chunks[i]; |
| 1323 | if (tmp == p) { | 1303 | if (tmp == p) |
| 1324 | wrterror(pool, "double free", p); | 1304 | wrterror(pool, "double free", p); |
| 1325 | return; | ||
| 1326 | } | ||
| 1327 | if (mopts.malloc_junk) | 1305 | if (mopts.malloc_junk) |
| 1328 | validate_junk(pool, p); | 1306 | validate_junk(pool, p); |
| 1329 | pool->delayed_chunks[i] = tmp; | 1307 | pool->delayed_chunks[i] = tmp; |
| 1330 | } | 1308 | } |
| 1331 | if (p != NULL) { | 1309 | if (p != NULL) { |
| 1332 | r = find(pool, p); | 1310 | r = find(pool, p); |
| 1333 | if (r == NULL) { | 1311 | if (r == NULL) |
| 1334 | wrterror(pool, "bogus pointer (double free?)", p); | 1312 | wrterror(pool, "bogus pointer (double free?)", p); |
| 1335 | return; | ||
| 1336 | } | ||
| 1337 | free_bytes(pool, r, p); | 1313 | free_bytes(pool, r, p); |
| 1338 | } | 1314 | } |
| 1339 | } | 1315 | } |
| @@ -1354,7 +1330,6 @@ free(void *ptr) | |||
| 1354 | if (d == NULL) { | 1330 | if (d == NULL) { |
| 1355 | _MALLOC_UNLOCK(); | 1331 | _MALLOC_UNLOCK(); |
| 1356 | wrterror(d, "free() called before allocation", NULL); | 1332 | wrterror(d, "free() called before allocation", NULL); |
| 1357 | return; | ||
| 1358 | } | 1333 | } |
| 1359 | d->func = "free():"; | 1334 | d->func = "free():"; |
| 1360 | if (d->active++) { | 1335 | if (d->active++) { |
| @@ -1380,10 +1355,8 @@ orealloc(struct dir_info *pool, void *p, size_t newsz, void *f) | |||
| 1380 | return omalloc(pool, newsz, 0, f); | 1355 | return omalloc(pool, newsz, 0, f); |
| 1381 | 1356 | ||
| 1382 | r = find(pool, p); | 1357 | r = find(pool, p); |
| 1383 | if (r == NULL) { | 1358 | if (r == NULL) |
| 1384 | wrterror(pool, "bogus pointer (double free?)", p); | 1359 | wrterror(pool, "bogus pointer (double free?)", p); |
| 1385 | return NULL; | ||
| 1386 | } | ||
| 1387 | if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { | 1360 | if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { |
| 1388 | errno = ENOMEM; | 1361 | errno = ENOMEM; |
| 1389 | return NULL; | 1362 | return NULL; |
| @@ -1512,10 +1485,8 @@ realloc(void *ptr, size_t size) | |||
| 1512 | 1485 | ||
| 1513 | d->active--; | 1486 | d->active--; |
| 1514 | _MALLOC_UNLOCK(); | 1487 | _MALLOC_UNLOCK(); |
| 1515 | if (r == NULL && mopts.malloc_xmalloc) { | 1488 | if (r == NULL && mopts.malloc_xmalloc) |
| 1516 | wrterror(d, "out of memory", NULL); | 1489 | wrterror(d, "out of memory", NULL); |
| 1517 | errno = ENOMEM; | ||
| 1518 | } | ||
| 1519 | if (r != NULL) | 1490 | if (r != NULL) |
| 1520 | errno = saved_errno; | 1491 | errno = saved_errno; |
| 1521 | return r; | 1492 | return r; |
| @@ -1565,10 +1536,8 @@ calloc(size_t nmemb, size_t size) | |||
| 1565 | 1536 | ||
| 1566 | d->active--; | 1537 | d->active--; |
| 1567 | _MALLOC_UNLOCK(); | 1538 | _MALLOC_UNLOCK(); |
| 1568 | if (r == NULL && mopts.malloc_xmalloc) { | 1539 | if (r == NULL && mopts.malloc_xmalloc) |
| 1569 | wrterror(d, "out of memory", NULL); | 1540 | wrterror(d, "out of memory", NULL); |
| 1570 | errno = ENOMEM; | ||
| 1571 | } | ||
| 1572 | if (r != NULL) | 1541 | if (r != NULL) |
| 1573 | errno = saved_errno; | 1542 | errno = saved_errno; |
| 1574 | return r; | 1543 | return r; |
| @@ -1580,14 +1549,10 @@ mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill) | |||
| 1580 | { | 1549 | { |
| 1581 | char *p, *q; | 1550 | char *p, *q; |
| 1582 | 1551 | ||
| 1583 | if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) { | 1552 | if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) |
| 1584 | wrterror(d, "mapalign bad alignment", NULL); | 1553 | wrterror(d, "mapalign bad alignment", NULL); |
| 1585 | return MAP_FAILED; | 1554 | if (sz != PAGEROUND(sz)) |
| 1586 | } | ||
| 1587 | if (sz != PAGEROUND(sz)) { | ||
| 1588 | wrterror(d, "mapalign round", NULL); | 1555 | wrterror(d, "mapalign round", NULL); |
| 1589 | return MAP_FAILED; | ||
| 1590 | } | ||
| 1591 | 1556 | ||
| 1592 | /* Allocate sz + alignment bytes of memory, which must include a | 1557 | /* Allocate sz + alignment bytes of memory, which must include a |
| 1593 | * subrange of size bytes that is properly aligned. Unmap the | 1558 | * subrange of size bytes that is properly aligned. Unmap the |
| @@ -1696,10 +1661,8 @@ posix_memalign(void **memptr, size_t alignment, size_t size) | |||
| 1696 | d->active--; | 1661 | d->active--; |
| 1697 | _MALLOC_UNLOCK(); | 1662 | _MALLOC_UNLOCK(); |
| 1698 | if (r == NULL) { | 1663 | if (r == NULL) { |
| 1699 | if (mopts.malloc_xmalloc) { | 1664 | if (mopts.malloc_xmalloc) |
| 1700 | wrterror(d, "out of memory", NULL); | 1665 | wrterror(d, "out of memory", NULL); |
| 1701 | errno = ENOMEM; | ||
| 1702 | } | ||
| 1703 | goto err; | 1666 | goto err; |
| 1704 | } | 1667 | } |
| 1705 | errno = saved_errno; | 1668 | errno = saved_errno; |
| @@ -1948,10 +1911,8 @@ malloc_dump(int fd) | |||
| 1948 | if (p == NULL) | 1911 | if (p == NULL) |
| 1949 | continue; | 1912 | continue; |
| 1950 | r = find(pool, p); | 1913 | r = find(pool, p); |
| 1951 | if (r == NULL) { | 1914 | if (r == NULL) |
| 1952 | wrterror(pool, "bogus pointer in malloc_dump", p); | 1915 | wrterror(pool, "bogus pointer in malloc_dump", p); |
| 1953 | continue; | ||
| 1954 | } | ||
| 1955 | free_bytes(pool, r, p); | 1916 | free_bytes(pool, r, p); |
| 1956 | pool->delayed_chunks[i] = NULL; | 1917 | pool->delayed_chunks[i] = NULL; |
| 1957 | } | 1918 | } |
