diff options
author | otto <> | 2006-04-24 19:23:42 +0000 |
---|---|---|
committer | otto <> | 2006-04-24 19:23:42 +0000 |
commit | bbbd1f39932721cf9371df2b05d20ea041c2ccb0 (patch) | |
tree | 2e647b1647c082907dab29d896a11b61e5932305 /src | |
parent | 87c4f50b85185f283080c848a73bd7b9671b4335 (diff) | |
download | openbsd-bbbd1f39932721cf9371df2b05d20ea041c2ccb0.tar.gz openbsd-bbbd1f39932721cf9371df2b05d20ea041c2ccb0.tar.bz2 openbsd-bbbd1f39932721cf9371df2b05d20ea041c2ccb0.zip |
Do not leave an hole in the directory list if allocation of the
region succeeds, but allocation a required page dir failed. This
can happen if we're really close to ulimit after allocation the
region of the size requested. See malloc_ulimit1 regress test.
Tested by many; thanks.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 4a38c53bbd..b858bbb739 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.81 2006/04/18 18:26:13 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.82 2006/04/24 19:23:42 otto Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * ---------------------------------------------------------------------------- | 4 | * ---------------------------------------------------------------------------- |
@@ -487,14 +487,16 @@ map_pages(size_t pages) | |||
487 | u_long idx, pidx, lidx; | 487 | u_long idx, pidx, lidx; |
488 | caddr_t result, tail; | 488 | caddr_t result, tail; |
489 | u_long index, lindex; | 489 | u_long index, lindex; |
490 | void *pdregion = NULL; | ||
491 | size_t dirs, cnt; | ||
490 | 492 | ||
491 | pages <<= malloc_pageshift; | 493 | pages <<= malloc_pageshift; |
492 | result = MMAP(pages + malloc_guard); | 494 | result = MMAP(pages + malloc_guard); |
493 | if (result == MAP_FAILED) { | 495 | if (result == MAP_FAILED) { |
494 | errno = ENOMEM; | ||
495 | #ifdef MALLOC_EXTRA_SANITY | 496 | #ifdef MALLOC_EXTRA_SANITY |
496 | wrtwarning("(ES): map_pages fails"); | 497 | wrtwarning("(ES): map_pages fails"); |
497 | #endif /* MALLOC_EXTRA_SANITY */ | 498 | #endif /* MALLOC_EXTRA_SANITY */ |
499 | errno = ENOMEM; | ||
498 | return (NULL); | 500 | return (NULL); |
499 | } | 501 | } |
500 | index = ptr2index(result); | 502 | index = ptr2index(result); |
@@ -510,19 +512,31 @@ map_pages(size_t pages) | |||
510 | malloc_brk = tail; | 512 | malloc_brk = tail; |
511 | last_index = lindex; | 513 | last_index = lindex; |
512 | } | 514 | } |
515 | |||
516 | dirs = lidx - pidx; | ||
517 | |||
513 | /* Insert directory pages, if needed. */ | 518 | /* Insert directory pages, if needed. */ |
514 | pdir_lookup(index, &pi); | 519 | if (pdir_lookup(index, &pi) != 0) |
520 | dirs++; | ||
521 | |||
522 | if (dirs > 0) { | ||
523 | pdregion = MMAP(malloc_pagesize * dirs); | ||
524 | if (pdregion == MAP_FAILED) { | ||
525 | munmap(result, tail - result); | ||
526 | #ifdef MALLOC_EXTRA_SANITY | ||
527 | wrtwarning("(ES): map_pages fails"); | ||
528 | #endif | ||
529 | errno = ENOMEM; | ||
530 | return (NULL); | ||
531 | } | ||
532 | } | ||
515 | 533 | ||
534 | cnt = 0; | ||
516 | for (idx = pidx, spi = pi; idx <= lidx; idx++) { | 535 | for (idx = pidx, spi = pi; idx <= lidx; idx++) { |
517 | if (pi == NULL || PD_IDX(pi->dirnum) != idx) { | 536 | if (pi == NULL || PD_IDX(pi->dirnum) != idx) { |
518 | if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) { | 537 | pd = (struct pginfo **)((char *)pdregion + |
519 | errno = ENOMEM; /* XXX */ | 538 | cnt * malloc_pagesize); |
520 | munmap(result, (size_t)(tail - result)); | 539 | cnt++; |
521 | #ifdef MALLOC_EXTRA_SANITY | ||
522 | wrtwarning("(ES): map_pages fails"); | ||
523 | #endif /* MALLOC_EXTRA_SANITY */ | ||
524 | return (NULL); | ||
525 | } | ||
526 | memset(pd, 0, malloc_pagesize); | 540 | memset(pd, 0, malloc_pagesize); |
527 | pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); | 541 | pi = (struct pdinfo *) ((caddr_t) pd + pdi_off); |
528 | pi->base = pd; | 542 | pi->base = pd; |
@@ -561,6 +575,13 @@ map_pages(size_t pages) | |||
561 | spi = pi; | 575 | spi = pi; |
562 | pi = spi->next; | 576 | pi = spi->next; |
563 | } | 577 | } |
578 | #ifdef MALLOC_EXTRA_SANITY | ||
579 | if (cnt > dirs) | ||
580 | wrtwarning("(ES): cnt > dirs"); | ||
581 | #endif /* MALLOC_EXTRA_SANITY */ | ||
582 | if (cnt < dirs) | ||
583 | munmap((char *)pdregion + cnt * malloc_pagesize, | ||
584 | (dirs - cnt) * malloc_pagesize); | ||
564 | 585 | ||
565 | return (result); | 586 | return (result); |
566 | } | 587 | } |