1 //===-- slot_reuse.cpp ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gwp_asan/tests/harness.h" 10 11 #include <set> 12 13 void singleByteGoodAllocDealloc(gwp_asan::GuardedPoolAllocator *GPA) { 14 void *Ptr = GPA->allocate(1); 15 EXPECT_NE(nullptr, Ptr); 16 EXPECT_TRUE(GPA->pointerIsMine(Ptr)); 17 EXPECT_EQ(1u, GPA->getSize(Ptr)); 18 GPA->deallocate(Ptr); 19 } 20 21 TEST_F(CustomGuardedPoolAllocator, EnsureReuseOfQuarantine1) { 22 InitNumSlots(1); 23 for (unsigned i = 0; i < 128; ++i) 24 singleByteGoodAllocDealloc(&GPA); 25 } 26 27 TEST_F(CustomGuardedPoolAllocator, EnsureReuseOfQuarantine2) { 28 InitNumSlots(2); 29 for (unsigned i = 0; i < 128; ++i) 30 singleByteGoodAllocDealloc(&GPA); 31 } 32 33 TEST_F(CustomGuardedPoolAllocator, EnsureReuseOfQuarantine127) { 34 InitNumSlots(127); 35 for (unsigned i = 0; i < 128; ++i) 36 singleByteGoodAllocDealloc(&GPA); 37 } 38 39 // This test ensures that our slots are not reused ahead of time. We increase 40 // the use-after-free detection by not reusing slots until all of them have been 41 // allocated. This is done by always using the slots from left-to-right in the 42 // pool before we used each slot once, at which point random selection takes 43 // over. 44 void runNoReuseBeforeNecessary(gwp_asan::GuardedPoolAllocator *GPA, 45 unsigned PoolSize) { 46 std::set<void *> Ptrs; 47 for (unsigned i = 0; i < PoolSize; ++i) { 48 void *Ptr = GPA->allocate(1); 49 50 EXPECT_TRUE(GPA->pointerIsMine(Ptr)); 51 EXPECT_EQ(0u, Ptrs.count(Ptr)); 52 53 Ptrs.insert(Ptr); 54 GPA->deallocate(Ptr); 55 } 56 } 57 58 TEST_F(CustomGuardedPoolAllocator, NoReuseBeforeNecessary2) { 59 constexpr unsigned kPoolSize = 2; 60 InitNumSlots(kPoolSize); 61 runNoReuseBeforeNecessary(&GPA, kPoolSize); 62 } 63 64 TEST_F(CustomGuardedPoolAllocator, NoReuseBeforeNecessary128) { 65 constexpr unsigned kPoolSize = 128; 66 InitNumSlots(kPoolSize); 67 runNoReuseBeforeNecessary(&GPA, kPoolSize); 68 } 69 70 TEST_F(CustomGuardedPoolAllocator, NoReuseBeforeNecessary129) { 71 constexpr unsigned kPoolSize = 129; 72 InitNumSlots(kPoolSize); 73 runNoReuseBeforeNecessary(&GPA, kPoolSize); 74 } 75