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 {
57 E : WindowsHeapAdapter::TearDown();
58 E : }
59 :
60 : protected:
61 E : const HeapManagerInterface::HeapId kFakeHeapId =
62 : static_cast<HeapManagerInterface::HeapId>(0XAABBCCDD);
63 :
64 : // The mock heap manager we delegate to.
65 : MockHeapManager mock_heap_manager_;
66 : };
67 :
68 : } // namespace
69 :
70 E : TEST_F(WindowsHeapAdapterTest, HeapCreate) {
71 E : EXPECT_CALL(mock_heap_manager_, CreateHeap()).WillOnce(Return(kFakeHeapId));
72 : EXPECT_EQ(reinterpret_cast<HANDLE>(kFakeHeapId),
73 E : WindowsHeapAdapter::HeapCreate(0, 0, 0));
74 E : }
75 :
76 E : TEST_F(WindowsHeapAdapterTest, HeapDestroy) {
77 : EXPECT_CALL(mock_heap_manager_,
78 E : DestroyHeap(kFakeHeapId)).WillOnce(Return(true));
79 : EXPECT_TRUE(
80 E : WindowsHeapAdapter::HeapDestroy(reinterpret_cast<HANDLE>(kFakeHeapId)));
81 E : }
82 :
83 E : TEST_F(WindowsHeapAdapterTest, HeapAlloc) {
84 E : const size_t kAllocSize = 100;
85 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
86 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
87 E : Return(kFakeAlloc));
88 : void* alloc =
89 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
90 : 0,
91 E : kAllocSize);
92 E : ASSERT_EQ(kFakeAlloc, alloc);
93 E : }
94 :
95 E : TEST_F(WindowsHeapAdapterTest, HeapAllocWithZeroMemoryFlag) {
96 E : const size_t kAllocSize = 10;
97 : uint8 kDummyBuffer[kAllocSize];
98 :
99 : // Fill the array with a non-zero value.
100 E : ::memset(kDummyBuffer, 0xFF, kAllocSize);
101 :
102 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
103 E : Return(reinterpret_cast<void*>(kDummyBuffer)));
104 : void* alloc =
105 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
106 : HEAP_ZERO_MEMORY,
107 E : kAllocSize);
108 E : EXPECT_EQ(reinterpret_cast<void*>(kDummyBuffer), alloc);
109 E : for (size_t i = 0; i < kAllocSize; ++i)
110 E : EXPECT_EQ(0, kDummyBuffer[i]);
111 E : }
112 :
113 E : TEST_F(WindowsHeapAdapterTest, HeapReAlloc) {
114 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
115 E : void* kFakeReAlloc = reinterpret_cast<void*>(0x87654321);
116 : // A successful call to WindowsHeapAdapter::HeapReAlloc should end up calling
117 : // HeapManagerInterface::Allocate, HeapManagerInterface::Size and
118 : // HeapManagerInterface::Free.
119 E : const size_t kReAllocSize = 200;
120 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
121 E : Return(kFakeReAlloc));
122 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, kFakeAlloc)).WillOnce(
123 E : Return(true));
124 : // Return a size of 0 to avoid trying to copy the old buffer into the new one.
125 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, kFakeAlloc)).WillOnce(
126 E : Return(0));
127 : EXPECT_EQ(kFakeReAlloc,
128 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
129 : 0,
130 : kFakeAlloc,
131 E : kReAllocSize));
132 E : }
133 :
134 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocWithNullSrcPointer) {
135 E : const size_t kReAllocSize = 10;
136 E : void* kFakeReAlloc = reinterpret_cast<void*>(0x87654321);
137 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
138 E : Return(kFakeReAlloc));
139 : EXPECT_EQ(kFakeReAlloc,
140 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
141 : 0,
142 : NULL,
143 E : kReAllocSize));
144 E : }
145 :
146 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocFailForInPlaceReallocations) {
147 E : const size_t kReAllocSize = 10;
148 E : EXPECT_CALL(mock_heap_manager_, Allocate(_, _)).Times(0);
149 : EXPECT_EQ(NULL,
150 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
151 : HEAP_REALLOC_IN_PLACE_ONLY,
152 : NULL,
153 E : kReAllocSize));
154 E : }
155 :
156 E : TEST_F(WindowsHeapAdapterTest, HeapReAllocFailOnOOM) {
157 E : const size_t kReAllocSize = 10;
158 : // Return NULL in the internal call that allocates the new buffer.
159 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
160 E : Return(static_cast<void*>(NULL)));
161 : EXPECT_EQ(NULL,
162 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
163 : 0,
164 : NULL,
165 E : kReAllocSize));
166 E : }
167 :
168 E : TEST_F(WindowsHeapAdapterTest, HeapReallocCopyData) {
169 E : const size_t kAllocSize = 10;
170 E : const size_t kReAllocSize = kAllocSize * 2;
171 : uint8 kDummyBuffer1[kAllocSize];
172 : uint8 kDummyBuffer2[kReAllocSize];
173 :
174 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kAllocSize)).WillOnce(
175 E : Return(reinterpret_cast<void*>(kDummyBuffer1)));
176 : void* alloc =
177 : WindowsHeapAdapter::HeapAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
178 : 0,
179 E : kAllocSize);
180 E : EXPECT_EQ(reinterpret_cast<void*>(kDummyBuffer1), alloc);
181 E : base::RandBytes(alloc, kAllocSize);
182 :
183 : EXPECT_CALL(mock_heap_manager_, Allocate(kFakeHeapId, kReAllocSize)).WillOnce(
184 E : Return(reinterpret_cast<void*>(kDummyBuffer2)));
185 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, alloc)).WillOnce(
186 E : Return(true));
187 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, alloc)).WillOnce(
188 E : Return(kAllocSize));
189 : void* re_alloc =
190 : WindowsHeapAdapter::HeapReAlloc(reinterpret_cast<HANDLE>(kFakeHeapId),
191 : 0,
192 : alloc,
193 E : kReAllocSize);
194 :
195 E : EXPECT_EQ(0, ::memcmp(alloc, re_alloc, kAllocSize));
196 E : }
197 :
198 E : TEST_F(WindowsHeapAdapterTest, HeapFree) {
199 E : void* kFakeAlloc = reinterpret_cast<void*>(0x12345678);
200 : EXPECT_CALL(mock_heap_manager_, Free(kFakeHeapId, kFakeAlloc)).WillOnce(
201 E : Return(true));
202 : ASSERT_TRUE(
203 : WindowsHeapAdapter::HeapFree(reinterpret_cast<HANDLE>(kFakeHeapId),
204 : 0,
205 E : kFakeAlloc));
206 E : }
207 :
208 E : TEST_F(WindowsHeapAdapterTest, HeapSize) {
209 E : const size_t kAllocSize = 100;
210 E : const void* kFakeAlloc = reinterpret_cast<const void*>(0x12345678);
211 : EXPECT_CALL(mock_heap_manager_, Size(kFakeHeapId, kFakeAlloc)).WillOnce(
212 E : Return(kAllocSize));
213 : EXPECT_EQ(kAllocSize,
214 : WindowsHeapAdapter::HeapSize(reinterpret_cast<HANDLE>(kFakeHeapId),
215 : 0,
216 E : kFakeAlloc));
217 E : }
218 :
219 E : TEST_F(WindowsHeapAdapterTest, HeapLock) {
220 E : EXPECT_CALL(mock_heap_manager_, Lock(kFakeHeapId)).Times(1);
221 E : WindowsHeapAdapter::HeapLock(reinterpret_cast<HANDLE>(kFakeHeapId));
222 E : }
223 :
224 E : TEST_F(WindowsHeapAdapterTest, HeapUnlock) {
225 E : EXPECT_CALL(mock_heap_manager_, Unlock(kFakeHeapId)).Times(1);
226 E : WindowsHeapAdapter::HeapUnlock(reinterpret_cast<HANDLE>(kFakeHeapId));
227 E : }
228 :
229 : } // namespace asan
230 : } // namespace agent
|