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(Size: 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(Size: 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 | |