diff options
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator.h | 2 | ||||
-rw-r--r-- | lib/sanitizer_common/tests/sanitizer_allocator_test.cc | 29 |
2 files changed, 30 insertions, 1 deletions
diff --git a/lib/sanitizer_common/sanitizer_allocator.h b/lib/sanitizer_common/sanitizer_allocator.h index b93de9fcf..1e9de4496 100644 --- a/lib/sanitizer_common/sanitizer_allocator.h +++ b/lib/sanitizer_common/sanitizer_allocator.h @@ -535,7 +535,7 @@ class SizeClassAllocator64 { region->mapped_meta += map_size; } CHECK_LE(region->allocated_meta, region->mapped_meta); - if (region->allocated_user + region->allocated_meta > kRegionSize) { + if (region->mapped_user + region->mapped_meta > kRegionSize) { Printf("%s: Out of memory. Dying. ", SanitizerToolName); Printf("The process has exhausted %zuMB for size class %zu.\n", kRegionSize / 1024 / 1024, size); diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index 445cbeed9..d30058add 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -701,4 +701,33 @@ TEST(SanitizerCommon, LargeMmapAllocatorIteration) { } } +#if SANITIZER_WORDSIZE == 64 +// Regression test for out-of-memory condition in PopulateFreeList(). +TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) { + // In a world where regions are small and chunks are huge... + typedef SizeClassMap<63, 128, 16> SpecialSizeClassMap; + typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0, + SpecialSizeClassMap> SpecialAllocator64; + const uptr kRegionSize = + kAllocatorSize / SpecialSizeClassMap::kNumClassesRounded; + SpecialAllocator64 *a = new SpecialAllocator64; + a->Init(); + SizeClassAllocatorLocalCache<SpecialAllocator64> cache; + memset(&cache, 0, sizeof(cache)); + cache.Init(0); + + // ...one man is on a mission to overflow a region with a series of + // successive allocations. + const uptr kClassID = 107; + const uptr kAllocationSize = DefaultSizeClassMap::Size(kClassID); + ASSERT_LT(2 * kAllocationSize, kRegionSize); + ASSERT_GT(3 * kAllocationSize, kRegionSize); + cache.Allocate(a, kClassID); + EXPECT_DEATH(cache.Allocate(a, kClassID) && cache.Allocate(a, kClassID), + "The process has exhausted"); + a->TestOnlyUnmap(); + delete a; +} +#endif + #endif // #if TSAN_DEBUG==0 |