1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/heaps/ctmalloc_heap.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/agent/asan/unittest_util.h"
19 : #include "syzygy/agent/asan/heaps/win_heap.h"
20 :
21 : namespace agent {
22 : namespace asan {
23 : namespace heaps {
24 :
25 E : TEST(CtMallocHeapTest, GetHeapTypeIsValid) {
26 E : testing::NullMemoryNotifier n;
27 E : CtMallocHeap h(&n);
28 E : EXPECT_EQ(kCtMallocHeap, h.GetHeapType());
29 E : }
30 :
31 E : TEST(CtMallocHeapTest, FeaturesAreValid) {
32 E : testing::NullMemoryNotifier n;
33 E : CtMallocHeap h(&n);
34 : EXPECT_EQ(CtMallocHeap::kHeapReportsReservations |
35 : CtMallocHeap::kHeapSupportsIsAllocated |
36 : CtMallocHeap::kHeapSupportsGetAllocationSize |
37 : CtMallocHeap::kHeapGetAllocationSizeIsUpperBound,
38 E : h.GetHeapFeatures());
39 E : }
40 :
41 E : TEST(CtMallocHeapTest, HeapTest) {
42 E : testing::NullMemoryNotifier n;
43 E : CtMallocHeap h(&n);
44 :
45 : // Allocate and free a zero-sized allocation. This should succeed
46 : // by definition.
47 E : void* alloc = h.Allocate(0);
48 E : EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(alloc) % kShadowRatio);
49 E : EXPECT_TRUE(h.Free(alloc));
50 :
51 : // Make a bunch of different sized allocations.
52 E : std::set<void*> allocs;
53 E : for (size_t i = 1; i < 1024 * 1024; i <<= 1) {
54 E : void* alloc = h.Allocate(i);
55 E : EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(alloc) % kShadowRatio);
56 E : allocs.insert(alloc);
57 E : }
58 :
59 : // Now free them.
60 E : std::set<void*>::const_iterator it = allocs.begin();
61 E : for (; it != allocs.end(); ++it)
62 E : EXPECT_TRUE(h.Free(*it));
63 E : }
64 :
65 E : TEST(CtMallocHeapTest, ZeroSizedAllocationsHaveDistinctAddresses) {
66 E : testing::NullMemoryNotifier n;
67 E : CtMallocHeap h(&n);
68 :
69 E : void* a1 = h.Allocate(0);
70 E : EXPECT_TRUE(a1 != NULL);
71 E : void* a2 = h.Allocate(0);
72 E : EXPECT_TRUE(a2 != NULL);
73 E : EXPECT_NE(a1, a2);
74 E : h.Free(a1);
75 E : h.Free(a2);
76 E : }
77 :
78 E : TEST(CtMallocHeapTest, IsAllocated) {
79 E : testing::NullMemoryNotifier n;
80 E : CtMallocHeap h(&n);
81 :
82 E : EXPECT_FALSE(h.IsAllocated(NULL));
83 :
84 E : void* a = h.Allocate(100);
85 E : EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(a) % kShadowRatio);
86 E : EXPECT_TRUE(h.IsAllocated(a));
87 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(a) - 1));
88 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(a) + 1));
89 :
90 E : h.Free(a);
91 E : EXPECT_FALSE(h.IsAllocated(a));
92 :
93 : // An allocation made in another heap should resolve as not belonging to
94 : // this heap.
95 E : WinHeap wh;
96 E : a = wh.Allocate(100);
97 E : EXPECT_FALSE(h.IsAllocated(a));
98 E : wh.Free(a);
99 E : }
100 :
101 E : TEST(CtMallocHeapTest, IsAllocatedLargeAllocation) {
102 E : testing::NullMemoryNotifier n;
103 E : CtMallocHeap h(&n);
104 :
105 E : EXPECT_FALSE(h.IsAllocated(NULL));
106 :
107 : // Mix large and small allocations to ensure that the CTMalloc data
108 : // structures correctly keep track of both.
109 E : void* a = h.Allocate(100);
110 E : void* b = h.Allocate(64 * 1024 * 1024);
111 :
112 E : EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(a) % kShadowRatio);
113 E : EXPECT_TRUE(h.IsAllocated(a));
114 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(a) - 1));
115 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(a) + 1));
116 :
117 E : EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(b) % kShadowRatio);
118 E : EXPECT_TRUE(h.IsAllocated(b));
119 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(b) - 1));
120 E : EXPECT_FALSE(h.IsAllocated(reinterpret_cast<uint8*>(b) + 1));
121 :
122 E : h.Free(a);
123 E : EXPECT_FALSE(h.IsAllocated(a));
124 E : EXPECT_TRUE(h.IsAllocated(b));
125 :
126 E : h.Free(b);
127 E : EXPECT_FALSE(h.IsAllocated(a));
128 E : EXPECT_FALSE(h.IsAllocated(b));
129 E : }
130 :
131 E : TEST(CtMallocHeapTest, GetAllocationSize) {
132 E : testing::NullMemoryNotifier n;
133 E : CtMallocHeap h(&n);
134 :
135 E : const size_t kAllocSize = 67;
136 E : void* alloc = h.Allocate(kAllocSize);
137 E : ASSERT_TRUE(alloc != NULL);
138 E : EXPECT_LE(kAllocSize, h.GetAllocationSize(alloc));
139 :
140 : // CTMalloc cleans up any oustanding allocations on tear down.
141 E : }
142 :
143 E : TEST(CtMallocHeapTest, GetAllocationSizeLargeAllocation) {
144 E : testing::NullMemoryNotifier n;
145 E : CtMallocHeap h(&n);
146 :
147 E : const size_t kAllocSize = 64 * 1024 * 1024;
148 E : void* alloc = h.Allocate(kAllocSize);
149 E : ASSERT_TRUE(alloc != NULL);
150 E : EXPECT_LE(kAllocSize, h.GetAllocationSize(alloc));
151 :
152 : // CTMalloc cleans up any oustanding allocations on tear down.
153 E : }
154 :
155 E : TEST(CtMallocHeapTest, Lock) {
156 E : testing::NullMemoryNotifier n;
157 E : CtMallocHeap h(&n);
158 E : h.Lock();
159 E : EXPECT_TRUE(h.TryLock());
160 E : h.Unlock();
161 E : h.Unlock();
162 E : }
163 :
164 : } // namespace heaps
165 : } // namespace asan
166 : } // namespace agent
|