summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_allocator.h2
-rw-r--r--lib/sanitizer_common/tests/sanitizer_allocator_test.cc29
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