[sanitizer] fix an allocator bug where the allocated memory may overlap with the free array (kudos to Kostya Korcthinsky). Also make sure that the allocator does not mmap more than requested. Test both.
llvm-svn: 281103
This commit is contained in:
parent
b1153848ff
commit
58560a05ad
|
@ -401,12 +401,12 @@ class SizeClassAllocator64 {
|
|||
uptr beg_idx = region->allocated_user;
|
||||
uptr end_idx = beg_idx + requested_count * size;
|
||||
uptr region_beg = GetRegionBeginBySizeClass(class_id);
|
||||
if (end_idx + size > region->mapped_user) {
|
||||
if (end_idx > region->mapped_user) {
|
||||
if (!kUsingConstantSpaceBeg && region->mapped_user == 0)
|
||||
region->rand_state = static_cast<u32>(region_beg >> 12); // From ASLR.
|
||||
// Do the mmap for the user memory.
|
||||
uptr map_size = kUserMapSize;
|
||||
while (end_idx + size > region->mapped_user + map_size)
|
||||
while (end_idx > region->mapped_user + map_size)
|
||||
map_size += kUserMapSize;
|
||||
CHECK_GE(region->mapped_user + map_size, end_idx);
|
||||
MapWithCallback(region_beg + region->mapped_user, map_size);
|
||||
|
@ -441,7 +441,8 @@ class SizeClassAllocator64 {
|
|||
region->mapped_meta += map_size;
|
||||
}
|
||||
CHECK_LE(region->allocated_meta, region->mapped_meta);
|
||||
if (region->mapped_user + region->mapped_meta > kRegionSize) {
|
||||
if (region->mapped_user + region->mapped_meta >
|
||||
kRegionSize - kFreeArraySize) {
|
||||
Printf("%s: Out of memory. Dying. ", SanitizerToolName);
|
||||
Printf("The process has exhausted %zuMB for size class %zu.\n",
|
||||
kRegionSize / 1024 / 1024, size);
|
||||
|
|
|
@ -931,16 +931,33 @@ TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) {
|
|||
|
||||
// ...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);
|
||||
const uptr kAllocationSize = SpecialSizeClassMap::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");
|
||||
|
||||
const uptr Class2 = 100;
|
||||
const uptr Size2 = SpecialSizeClassMap::Size(Class2);
|
||||
ASSERT_EQ(Size2 * 8, kRegionSize);
|
||||
char *p[7];
|
||||
for (int i = 0; i < 7; i++) {
|
||||
p[i] = (char*)cache.Allocate(a, Class2);
|
||||
fprintf(stderr, "p[%d] %p s = %lx\n", i, (void*)p[i], Size2);
|
||||
p[i][Size2 - 1] = 42;
|
||||
if (i) ASSERT_LT(p[i - 1], p[i]);
|
||||
}
|
||||
EXPECT_DEATH(cache.Allocate(a, Class2), "The process has exhausted");
|
||||
cache.Deallocate(a, Class2, p[0]);
|
||||
cache.Drain(a);
|
||||
ASSERT_EQ(p[6][Size2 - 1], 42);
|
||||
a->TestOnlyUnmap();
|
||||
delete a;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(SanitizerCommon, TwoLevelByteMap) {
|
||||
|
|
Loading…
Reference in New Issue