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/windows_heap_adapter.h"
16 :
17 : #include "base/compiler_specific.h"
18 : #include "base/rand_util.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/agent/asan/heap_manager.h"
22 :
23 : namespace agent {
24 : namespace asan {
25 :
26 : namespace {
27 :
28 : using testing::Return;
29 : using testing::_;
30 :
31 : // A mock heap manager to make sure that the calls to the Windows heap adapter
32 : // are correctly forwarded.
33 : class LenientMockHeapManager : public HeapManagerInterface {
34 : public:
35 E : MOCK_METHOD0(CreateHeap, HeapId());
36 E : MOCK_METHOD1(DestroyHeap, bool(HeapId));
37 E : MOCK_METHOD2(Size, size_t(HeapId, const void*));
38 E : MOCK_METHOD2(Allocate, void*(HeapId, size_t));
39 E : MOCK_METHOD2(Free, bool(HeapId, void*));
40 E : MOCK_METHOD1(Lock, void(HeapId));
41 E : MOCK_METHOD1(Unlock, void(HeapId));
42 i : MOCK_METHOD0(BestEffortLockAll, void());
43 i : MOCK_METHOD0(UnlockAll, void());
44 : };
45 :
46 : typedef testing::StrictMock<LenientMockHeapManager> MockHeapManager;
47 :
48 : class WindowsHeapAdapterTest : public testing::Test {
49 : public:
50 E : WindowsHeapAdapterTest() { }
51 :
52 E : virtual void SetUp() override {
53 E : WindowsHeapAdapter::SetUp(&mock_heap_manager_);
54 E : }
55 :
56 E : virtual void TearDown() override { WindowsHeapAdapter::TearDown(); }
57 :
58 : protected:
59 E : const HeapManagerInterface::HeapId kFakeHeapId =
60 : static_cast<HeapManagerInterface::HeapId>(0XAABBCCDD);
61 :
62 : // The mock heap manager we delegate to.
63 : MockHeapManager mock_heap_manager_;
64 : };
65 :
66 : } // namespace
67 :
68 E : TEST_F(WindowsHeapAdapterTest, HeapCreate) {
69 E : EXPECT_CALL(mock_heap_manager_, CreateHeap()).WillOnce(Return(kFakeHeapId));
70 : EXPECT_EQ(reinterpret_cast<HANDLE>(kFakeHeapId),
71 E : WindowsHeapAdapter::HeapCreate(0, 0, 0));
72 E : }
73 :
74 E : TEST_F(WindowsHeapAdapterTest, HeapDestroy) {
75 : EXPECT_CALL(mock_heap_manager_,
76 E : DestroyHeap(kFakeHeapId)).WillOnce(Return(true));
77 : EXPECT_TRUE(
78 E : WindowsHeapAdapter::HeapDestroy(reinterpret_cast<HANDLE>(kFakeHeapId)));
79 E : }
80 :
81 E : TEST_F(WindowsHeapAdapterTest, HeapAlloc) {
82 E : const size_t kAllocSize = 100;
83 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
84 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
85 E : Return(kFakeAlloc));
86 : void* alloc =
87 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
88 : 0,
89 E : kAllocSize);
90 E : ASSERT_EQ(kFakeAlloc, alloc);
91 E : }
92 :
93 E : TEST_F(WindowsHeapAdapterTest, HeapAllocWithZeroMemoryFlag) {
94 E : const size_t kAllocSize = 10;
95 : uint8 kDummyBuffer[kAllocSize];
96 :
97 : // Fill the array with a non-zero value.
98 E : ::memset(kDummyBuffer, 0xFF, kAllocSize);
99 :
100 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
101 E : Return(reinterpret_cast<void*>(kDummyBuffer)));
102 : void* alloc =
103 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
104 : HEAP_ZERO_MEMORY,
105 E : kAllocSize);
106 E : EXPECT_EQ(reinterpret_cast<void*>(kDummyBuffer), alloc);
107 E : for (size_t i = 0; i < kAllocSize; ++i)
108 E : EXPECT_EQ(0, kDummyBuffer[i]);
109 E : }
110 :
111 E : TEST_F(WindowsHeapAdapterTest, HeapReAlloc) {
112 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
113 E : void* kFakeReAlloc = reinterpret_cast<void*>(0x87654321);
114 : // A successful call to WindowsHeapAdapter::HeapReAlloc should end up calling
115 : // HeapManagerInterface::Allocate, HeapManagerInterface::Size and
116 : // HeapManagerInterface::Free.
117 E : const size_t kReAllocSize = 200;
118 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
119 E : Return(kFakeReAlloc));
120 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, kFakeAlloc)).WillOnce(
121 E : Return(true));
122 : // Return a size of 0 to avoid trying to copy the old buffer into the new one.
123 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, kFakeAlloc)).WillOnce(
124 E : Return(0));
125 : EXPECT_EQ(kFakeReAlloc,
126 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
127 : 0,
128 : kFakeAlloc,
129 E : kReAllocSize));
130 E : }
131 :
132 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocWithNullSrcPointer) {
133 E : const size_t kReAllocSize = 10;
134 E : void* kFakeReAlloc = reinterpret_cast<void*>(0x87654321);
135 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
136 E : Return(kFakeReAlloc));
137 : EXPECT_EQ(kFakeReAlloc,
138 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
139 : 0,
140 : NULL,
141 E : kReAllocSize));
142 E : }
143 :
144 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocFailForInPlaceReallocations) {
145 E : const size_t kReAllocSize = 10;
146 E : EXPECT_CALL(mock_heap_manager_, Allocate(_, _)).Times(0);
147 : EXPECT_EQ(NULL,
148 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
149 : HEAP_REALLOC_IN_PLACE_ONLY,
150 : NULL,
151 E : kReAllocSize));
152 E : }
153 :
154 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocFailOnOOM) {
155 E : const size_t kReAllocSize = 10;
156 : // Return NULL in the internal call that allocates the new buffer.
157 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
158 E : Return(static_cast<void*>(NULL)));
159 : EXPECT_EQ(NULL,
160 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
161 : 0,
162 : NULL,
163 E : kReAllocSize));
164 E : }
165 :
166 E : TEST_F(WindowsHeapAdapterTest, HeapReallocCopyData) {
167 E : const size_t kAllocSize = 10;
168 E : const size_t kReAllocSize = kAllocSize * 2;
169 : uint8 kDummyBuffer1[kAllocSize];
170 : uint8 kDummyBuffer2[kReAllocSize];
171 :
172 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
173 E : Return(reinterpret_cast<void*>(kDummyBuffer1)));
174 : void* alloc =
175 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
176 : 0,
177 E : kAllocSize);
178 E : EXPECT_EQ(reinterpret_cast<void*>(kDummyBuffer1), alloc);
179 E : base::RandBytes(alloc, kAllocSize);
180 :
181 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
182 E : Return(reinterpret_cast<void*>(kDummyBuffer2)));
183 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, alloc)).WillOnce(
184 E : Return(true));
185 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, alloc)).WillOnce(
186 E : Return(kAllocSize));
187 : void* re_alloc =
188 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
189 : 0,
190 : alloc,
191 E : kReAllocSize);
192 :
193 E : EXPECT_EQ(0, ::memcmp(alloc, re_alloc, kAllocSize));
194 E : }
195 :
196 E : TEST_F(WindowsHeapAdapterTest, HeapFree) {
197 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
198 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, kFakeAlloc)).WillOnce(
199 E : Return(true));
200 : ASSERT_TRUE(
201 : WindowsHeapAdapter::HeapFree(reinterpret_cast<HANDLE>(kFakeHeapId),
202 : 0,
203 E : kFakeAlloc));
204 E : }
205 :
206 E : TEST_F(WindowsHeapAdapterTest, HeapSize) {
207 E : const size_t kAllocSize = 100;
208 E : const void* kFakeAlloc = reinterpret_cast<const void*>(0x12345678);
209 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, kFakeAlloc)).WillOnce(
210 E : Return(kAllocSize));
211 : EXPECT_EQ(kAllocSize,
212 : WindowsHeapAdapter::HeapSize(reinterpret_cast<HANDLE>(kFakeHeapId),
213 : 0,
214 E : kFakeAlloc));
215 E : }
216 :
217 E : TEST_F(WindowsHeapAdapterTest, HeapLock) {
218 E : EXPECT_CALL(mock_heap_manager_, Lock(kFakeHeapId)).Times(1);
219 E : WindowsHeapAdapter::HeapLock(reinterpret_cast<HANDLE>(kFakeHeapId));
220 E : }
221 :
222 E : TEST_F(WindowsHeapAdapterTest, HeapUnlock) {
223 E : EXPECT_CALL(mock_heap_manager_, Unlock(kFakeHeapId)).Times(1);
224 E : WindowsHeapAdapter::HeapUnlock(reinterpret_cast<HANDLE>(kFakeHeapId));
225 E : }
226 :
227 : } // namespace asan
228 : } // namespace agent
|