1 : // Copyright 2012 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 <windows.h>
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/agent/asan/heap_checker.h"
19 : #include "syzygy/agent/asan/rtl_impl.h"
20 : #include "syzygy/agent/asan/runtime.h"
21 : #include "syzygy/agent/asan/unittest_util.h"
22 :
23 : namespace agent {
24 : namespace asan {
25 :
26 : namespace {
27 :
28 : using testing::AsanBlockInfoVector;
29 : using testing::MemoryAccessorTester;
30 : using testing::ScopedAsanAlloc;
31 :
32 : // An arbitrary size for the buffer we allocate in the different unittests.
33 : const size_t kAllocSize = 13;
34 :
35 : class AsanRtlTest : public testing::TestAsanRtl {
36 : public:
37 : AsanRtlTest() : memory_src_(NULL), memory_dst_(NULL), memory_length_(0),
38 E : memory_size_(0) { }
39 :
40 E : void SetUp() override {
41 E : testing::TestAsanRtl::SetUp();
42 :
43 : // Setup the callback to detect invalid accesses.
44 E : SetCallBackFunction(&MemoryAccessorTester::AsanErrorCallback);
45 E : }
46 :
47 : protected:
48 : void AllocMemoryBuffers(int32 length, int32 element_size);
49 : void FreeMemoryBuffers();
50 :
51 : // Memory buffers used to test special instructions.
52 : void* memory_src_;
53 : void* memory_dst_;
54 : int32 memory_length_;
55 : int32 memory_size_;
56 : };
57 :
58 E : void AsanRtlTest::AllocMemoryBuffers(int32 length, int32 element_size) {
59 E : ASSERT_EQ(reinterpret_cast<void*>(NULL), memory_src_);
60 E : ASSERT_EQ(reinterpret_cast<void*>(NULL), memory_dst_);
61 E : ASSERT_EQ(0, memory_length_);
62 E : ASSERT_EQ(0, memory_size_);
63 :
64 : // Keep track of memory size.
65 E : memory_length_ = length;
66 E : memory_size_ = length * element_size;
67 :
68 : // Allocate memory space.
69 E : memory_src_ = HeapAllocFunction(heap_, 0, memory_size_);
70 E : ASSERT_TRUE(memory_src_ != NULL);
71 E : memory_dst_ = HeapAllocFunction(heap_, 0, memory_size_);
72 E : ASSERT_TRUE(memory_dst_ != NULL);
73 :
74 : // Initialize memory.
75 E : ::memset(memory_src_, 0, memory_size_);
76 E : ::memset(memory_dst_, 0, memory_size_);
77 E : }
78 :
79 E : void AsanRtlTest::FreeMemoryBuffers() {
80 E : ASSERT_NE(reinterpret_cast<void*>(NULL), memory_src_);
81 E : ASSERT_NE(reinterpret_cast<void*>(NULL), memory_dst_);
82 :
83 E : ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_src_));
84 E : ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_dst_));
85 :
86 E : memory_length_ = 0;
87 E : memory_size_ = 0;
88 E : memory_src_ = NULL;
89 E : memory_dst_ = NULL;
90 E : }
91 :
92 : } // namespace
93 :
94 E : TEST_F(AsanRtlTest, GetProcessHeap) {
95 E : agent::asan::AsanRuntime* runtime = GetActiveRuntimeFunction();
96 E : ASSERT_NE(reinterpret_cast<agent::asan::AsanRuntime*>(NULL), runtime);
97 E : HANDLE asan_heap_handle = GetProcessHeapFunction();
98 E : EXPECT_NE(static_cast<HANDLE>(NULL), asan_heap_handle);
99 : EXPECT_EQ(reinterpret_cast<HANDLE>(runtime->GetProcessHeap()),
100 E : asan_heap_handle);
101 E : }
102 :
103 E : TEST_F(AsanRtlTest, AsanCheckGoodAccess) {
104 : FARPROC check_access_fn =
105 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
106 E : ASSERT_TRUE(check_access_fn != NULL);
107 :
108 : // Run through access checking an allocation that's larger than our
109 : // block size (8), but not a multiple thereof to exercise all paths
110 : // in the access check function (save for the failure path).
111 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
112 E : ASSERT_TRUE(mem.get() != NULL);
113 :
114 E : MemoryAccessorTester tester;
115 E : for (size_t i = 0; i < kAllocSize; ++i) {
116 : ASSERT_NO_FATAL_FAILURE(
117 E : tester.CheckAccessAndCompareContexts(check_access_fn, mem.get() + i));
118 E : }
119 E : }
120 :
121 E : TEST_F(AsanRtlTest, AsanCheckHeapBufferOverflow) {
122 : FARPROC check_access_fn =
123 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
124 E : ASSERT_TRUE(check_access_fn != NULL);
125 :
126 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
127 E : ASSERT_TRUE(mem.get() != NULL);
128 :
129 E : MemoryAccessorTester tester;
130 : tester.AssertMemoryErrorIsDetected(
131 E : check_access_fn, mem.get() + kAllocSize, HEAP_BUFFER_OVERFLOW);
132 E : EXPECT_TRUE(LogContains("previously allocated here"));
133 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
134 E : }
135 :
136 E : TEST_F(AsanRtlTest, AsanCheckHeapBufferUnderflow) {
137 : FARPROC check_access_fn =
138 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
139 E : ASSERT_TRUE(check_access_fn != NULL);
140 :
141 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
142 E : ASSERT_TRUE(mem.get() != NULL);
143 :
144 E : MemoryAccessorTester tester;
145 : tester.AssertMemoryErrorIsDetected(
146 E : check_access_fn, mem.get() - 1, HEAP_BUFFER_UNDERFLOW);
147 E : EXPECT_TRUE(LogContains("previously allocated here"));
148 E : EXPECT_TRUE(LogContains(kHeapBufferUnderFlow));
149 E : }
150 :
151 E : TEST_F(AsanRtlTest, AsanCheckUseAfterFree) {
152 : FARPROC check_access_fn =
153 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
154 E : ASSERT_TRUE(check_access_fn != NULL);
155 :
156 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
157 E : ASSERT_TRUE(mem.get() != NULL);
158 :
159 E : uint8* mem_ptr = mem.get();
160 E : mem.reset(NULL);
161 :
162 E : MemoryAccessorTester tester;
163 E : tester.AssertMemoryErrorIsDetected(check_access_fn, mem_ptr, USE_AFTER_FREE);
164 E : EXPECT_TRUE(LogContains("previously allocated here"));
165 E : EXPECT_TRUE(LogContains("freed here"));
166 E : EXPECT_TRUE(LogContains(kHeapUseAfterFree));
167 E : }
168 :
169 E : TEST_F(AsanRtlTest, AsanCheckDoubleFree) {
170 : FARPROC check_access_fn =
171 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
172 E : ASSERT_TRUE(check_access_fn != NULL);
173 :
174 E : uint8* mem_ptr = NULL;
175 : {
176 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
177 E : ASSERT_TRUE(mem.get() != NULL);
178 E : mem_ptr = mem.get();
179 E : }
180 :
181 E : MemoryAccessorTester tester;
182 E : tester.set_expected_error_type(DOUBLE_FREE);
183 E : EXPECT_FALSE(HeapFreeFunction(heap_, 0, mem_ptr));
184 E : EXPECT_TRUE(tester.memory_error_detected());
185 E : EXPECT_TRUE(LogContains(kAttemptingDoubleFree));
186 E : EXPECT_TRUE(LogContains("previously allocated here"));
187 E : EXPECT_TRUE(LogContains("freed here"));
188 E : }
189 :
190 E : TEST_F(AsanRtlTest, AsanCheckWildAccess) {
191 : FARPROC check_access_fn =
192 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
193 E : ASSERT_TRUE(check_access_fn != NULL);
194 :
195 E : MemoryAccessorTester tester;
196 : tester.AssertMemoryErrorIsDetected(
197 E : check_access_fn, reinterpret_cast<void*>(0x80000000), WILD_ACCESS);
198 E : EXPECT_TRUE(LogContains(kWildAccess));
199 E : }
200 :
201 : // It is not possible to test the near-nullptr access with heap corruption
202 : // execution path since it depends on the unhandled exception filter which is
203 : // not installed in the rtl library.
204 E : TEST_F(AsanRtlTest, AsanIgnoreInvalidAccess) {
205 : FARPROC check_access_fn =
206 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
207 E : ASSERT_TRUE(check_access_fn != NULL);
208 :
209 : // A near-nullptr access should not be reported by SyzyASAN.
210 E : MemoryAccessorTester tester;
211 E : tester.CheckAccessAndCompareContexts(check_access_fn, nullptr);
212 E : EXPECT_FALSE(LogContains(kInvalidAddress));
213 E : }
214 :
215 E : TEST_F(AsanRtlTest, AsanReportInvalidAccess) {
216 : FARPROC check_access_fn =
217 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
218 E : ASSERT_NE(static_cast<FARPROC>(nullptr), check_access_fn);
219 :
220 E : MemoryAccessorTester tester;
221 E : agent::asan::AsanRuntime* runtime = GetActiveRuntimeFunction();
222 E : ASSERT_NE(reinterpret_cast<agent::asan::AsanRuntime*>(NULL), runtime);
223 E : runtime->params().report_invalid_accesses = true;
224 : tester.AssertMemoryErrorIsDetected(
225 E : check_access_fn, reinterpret_cast<void*>(0x00000000), INVALID_ADDRESS);
226 E : EXPECT_TRUE(LogContains(kInvalidAddress));
227 E : }
228 :
229 E : TEST_F(AsanRtlTest, AsanCheckCorruptBlock) {
230 E : void* mem = HeapAllocFunction(heap_, 0, kAllocSize);
231 E : reinterpret_cast<uint8*>(mem)[-1]--;
232 E : MemoryAccessorTester tester;
233 E : tester.set_expected_error_type(CORRUPT_BLOCK);
234 E : EXPECT_TRUE(HeapFreeFunction(heap_, 0, mem));
235 E : EXPECT_TRUE(tester.memory_error_detected());
236 E : EXPECT_TRUE(LogContains(kHeapCorruptBlock));
237 E : EXPECT_TRUE(LogContains("previously allocated here"));
238 E : }
239 :
240 E : TEST_F(AsanRtlTest, AsanCheckCorruptHeap) {
241 : FARPROC check_access_fn =
242 E : ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
243 E : ASSERT_TRUE(check_access_fn != NULL);
244 :
245 E : agent::asan::AsanRuntime* runtime = GetActiveRuntimeFunction();
246 E : ASSERT_NE(reinterpret_cast<agent::asan::AsanRuntime*>(NULL), runtime);
247 E : runtime->params().check_heap_on_failure = true;
248 :
249 E : ScopedAsanAlloc<uint8> mem(this, kAllocSize);
250 E : ASSERT_TRUE(mem.get() != NULL);
251 :
252 E : const size_t kMaxIterations = 10;
253 :
254 : // Retrieves the information about this block.
255 : BlockHeader* header = BlockGetHeaderFromBody(
256 E : reinterpret_cast<BlockBody*>(mem.get()));
257 E : BlockInfo block_info = {};
258 E : EXPECT_TRUE(BlockInfoFromMemory(header, &block_info));
259 :
260 : // We'll update a non essential value of the block trailer to corrupt it.
261 : uint8* mem_in_trailer = reinterpret_cast<uint8*>(
262 E : &block_info.trailer->alloc_tid);
263 :
264 : // This can fail because of a checksum collision. However, we run it a handful
265 : // of times to keep the chances as small as possible.
266 E : for (size_t i = 0; i < kMaxIterations; ++i) {
267 E : (*mem_in_trailer)++;
268 E : MemoryAccessorTester tester;
269 : tester.AssertMemoryErrorIsDetected(
270 E : check_access_fn, mem.get() + kAllocSize, HEAP_BUFFER_OVERFLOW);
271 E : EXPECT_TRUE(LogContains("previously allocated here"));
272 E : EXPECT_TRUE(LogContains(kHeapBufferOverFlow));
273 :
274 : if (!tester.last_error_info().heap_is_corrupt &&
275 E : i + 1 < kMaxIterations)
276 i : continue;
277 :
278 E : EXPECT_TRUE(tester.last_error_info().heap_is_corrupt);
279 :
280 E : EXPECT_EQ(1, tester.last_error_info().corrupt_range_count);
281 E : EXPECT_EQ(1, tester.last_corrupt_ranges().size());
282 E : AsanBlockInfoVector blocks_info = tester.last_corrupt_ranges()[0].second;
283 :
284 E : EXPECT_EQ(1, blocks_info.size());
285 E : EXPECT_EQ(kDataIsCorrupt, blocks_info[0].analysis.block_state);
286 E : EXPECT_EQ(kAllocSize, blocks_info[0].user_size);
287 E : EXPECT_EQ(block_info.header, blocks_info[0].header);
288 E : EXPECT_NE(0U, blocks_info[0].alloc_stack_size);
289 E : for (size_t j = 0; j < blocks_info[0].alloc_stack_size; ++j)
290 E : EXPECT_NE(reinterpret_cast<void*>(NULL), blocks_info[0].alloc_stack[j]);
291 E : EXPECT_EQ(0U, blocks_info[0].free_stack_size);
292 :
293 : // An error should be triggered when we free this block.
294 E : tester.set_memory_error_detected(false);
295 E : tester.set_expected_error_type(CORRUPT_BLOCK);
296 E : mem.reset(NULL);
297 E : EXPECT_TRUE(tester.memory_error_detected());
298 :
299 E : break;
300 i : }
301 E : }
302 :
303 E : TEST_F(AsanRtlTest, AsanSingleSpecial1byteInstructionCheckGoodAccess) {
304 : static const char* function_names[] = {
305 : "asan_check_1_byte_movs_access",
306 : "asan_check_1_byte_cmps_access",
307 : "asan_check_1_byte_stos_access"
308 : };
309 :
310 : // Allocate memory space.
311 E : AllocMemoryBuffers(kAllocSize, sizeof(uint8));
312 E : uint8* src = reinterpret_cast<uint8*>(memory_src_);
313 E : uint8* dst = reinterpret_cast<uint8*>(memory_dst_);
314 :
315 : // Validate memory accesses.
316 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
317 : FARPROC check_access_fn =
318 E : ::GetProcAddress(asan_rtl_, function_names[function]);
319 E : ASSERT_TRUE(check_access_fn != NULL);
320 :
321 E : for (int32 i = 0; i < memory_length_; ++i) {
322 E : MemoryAccessorTester tester;
323 : tester.ExpectSpecialMemoryErrorIsDetected(
324 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
325 : false, &dst[i], &src[i], 0xDEADDEAD,
326 E : UNKNOWN_BAD_ACCESS);
327 E : }
328 E : }
329 :
330 E : FreeMemoryBuffers();
331 E : }
332 :
333 E : TEST_F(AsanRtlTest, AsanSingleSpecial2byteInstructionCheckGoodAccess) {
334 : static const char* function_names[] = {
335 : "asan_check_2_byte_movs_access",
336 : "asan_check_2_byte_cmps_access",
337 : "asan_check_2_byte_stos_access"
338 : };
339 :
340 : // Allocate memory space.
341 E : AllocMemoryBuffers(kAllocSize, sizeof(uint16));
342 E : uint16* src = reinterpret_cast<uint16*>(memory_src_);
343 E : uint16* dst = reinterpret_cast<uint16*>(memory_dst_);
344 :
345 : // Validate memory accesses.
346 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
347 : FARPROC check_access_fn =
348 E : ::GetProcAddress(asan_rtl_, function_names[function]);
349 E : ASSERT_TRUE(check_access_fn != NULL);
350 :
351 E : for (int32 i = 0; i < memory_length_; ++i) {
352 E : MemoryAccessorTester tester;
353 : tester.ExpectSpecialMemoryErrorIsDetected(
354 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
355 E : false, &dst[i], &src[i], 0xDEADDEAD, UNKNOWN_BAD_ACCESS);
356 E : }
357 E : }
358 :
359 E : FreeMemoryBuffers();
360 E : }
361 :
362 E : TEST_F(AsanRtlTest, AsanSingleSpecial4byteInstructionCheckGoodAccess) {
363 : static const char* function_names[] = {
364 : "asan_check_4_byte_movs_access",
365 : "asan_check_4_byte_cmps_access",
366 : "asan_check_4_byte_stos_access"
367 : };
368 :
369 : // Allocate memory space.
370 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
371 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
372 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
373 :
374 : // Validate memory accesses.
375 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
376 : FARPROC check_access_fn =
377 E : ::GetProcAddress(asan_rtl_, function_names[function]);
378 E : ASSERT_TRUE(check_access_fn != NULL);
379 :
380 E : for (int32 i = 0; i < memory_length_; ++i) {
381 E : MemoryAccessorTester tester;
382 : tester.ExpectSpecialMemoryErrorIsDetected(
383 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
384 E : false, &dst[i], &src[i], 0xDEADDEAD, UNKNOWN_BAD_ACCESS);
385 E : }
386 E : }
387 :
388 E : FreeMemoryBuffers();
389 E : }
390 :
391 E : TEST_F(AsanRtlTest, AsanSingleSpecialInstructionCheckBadAccess) {
392 : static const char* function_names[] = {
393 : "asan_check_1_byte_movs_access",
394 : "asan_check_1_byte_cmps_access",
395 : "asan_check_2_byte_movs_access",
396 : "asan_check_2_byte_cmps_access",
397 : "asan_check_4_byte_movs_access",
398 : "asan_check_4_byte_cmps_access"
399 : };
400 :
401 : // Allocate memory space.
402 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
403 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
404 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
405 :
406 : // Validate memory accesses.
407 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
408 : FARPROC check_access_fn =
409 E : ::GetProcAddress(asan_rtl_, function_names[function]);
410 E : ASSERT_TRUE(check_access_fn != NULL);
411 :
412 E : MemoryAccessorTester tester;
413 : tester.ExpectSpecialMemoryErrorIsDetected(
414 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
415 E : true, &dst[0], &src[-1], 0xDEADDEAD, HEAP_BUFFER_UNDERFLOW);
416 : tester.ExpectSpecialMemoryErrorIsDetected(
417 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
418 E : true, &dst[-1], &src[0], 0xDEADDEAD, HEAP_BUFFER_UNDERFLOW);
419 :
420 : tester.ExpectSpecialMemoryErrorIsDetected(
421 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
422 E : true, &dst[0], &src[memory_length_], 0xDEADDEAD, HEAP_BUFFER_OVERFLOW);
423 : tester.ExpectSpecialMemoryErrorIsDetected(
424 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
425 E : true, &dst[memory_length_], &src[0], 0xDEADDEAD, HEAP_BUFFER_OVERFLOW);
426 E : }
427 :
428 E : FreeMemoryBuffers();
429 E : }
430 :
431 E : TEST_F(AsanRtlTest, AsanSingleStoInstructionCheckBadAccess) {
432 : static const char* function_names[] = {
433 : "asan_check_1_byte_stos_access",
434 : "asan_check_2_byte_stos_access",
435 : "asan_check_4_byte_stos_access"
436 : };
437 :
438 : // Allocate memory space.
439 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
440 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
441 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
442 :
443 : // Validate memory accesses.
444 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
445 : FARPROC check_access_fn =
446 E : ::GetProcAddress(asan_rtl_, function_names[function]);
447 E : ASSERT_TRUE(check_access_fn != NULL);
448 :
449 E : MemoryAccessorTester tester;
450 : tester.ExpectSpecialMemoryErrorIsDetected(
451 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
452 E : false, &dst[0], &src[-1], 0xDEAD, HEAP_BUFFER_UNDERFLOW);
453 : tester.ExpectSpecialMemoryErrorIsDetected(
454 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
455 E : true, &dst[-1], &src[0], 0xDEAD, HEAP_BUFFER_UNDERFLOW);
456 :
457 : tester.ExpectSpecialMemoryErrorIsDetected(
458 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
459 E : false, &dst[0], &src[memory_length_], 0xDEADDEAD, HEAP_BUFFER_OVERFLOW);
460 : tester.ExpectSpecialMemoryErrorIsDetected(
461 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
462 E : true, &dst[memory_length_], &src[0], 0xDEADDEAD, HEAP_BUFFER_OVERFLOW);
463 E : }
464 :
465 E : FreeMemoryBuffers();
466 E : }
467 :
468 E : TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckGoodAccess) {
469 : static const char* function_names[] = {
470 : "asan_check_repz_4_byte_movs_access",
471 : "asan_check_repz_4_byte_cmps_access",
472 : "asan_check_repz_4_byte_stos_access"
473 : };
474 :
475 : // Allocate memory space.
476 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
477 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
478 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
479 :
480 : // Validate memory accesses.
481 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
482 : FARPROC check_access_fn =
483 E : ::GetProcAddress(asan_rtl_, function_names[function]);
484 E : ASSERT_TRUE(check_access_fn != NULL);
485 :
486 E : MemoryAccessorTester tester;
487 : tester.ExpectSpecialMemoryErrorIsDetected(
488 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
489 E : false, &dst[0], &src[0], memory_length_, UNKNOWN_BAD_ACCESS);
490 E : }
491 :
492 E : FreeMemoryBuffers();
493 E : }
494 :
495 E : TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckBadAccess) {
496 : static const char* function_names[] = {
497 : "asan_check_repz_4_byte_movs_access",
498 : "asan_check_repz_4_byte_cmps_access",
499 : "asan_check_repz_4_byte_stos_access"
500 : };
501 :
502 : // Allocate memory space.
503 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
504 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
505 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
506 :
507 : // Validate memory accesses.
508 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
509 : FARPROC check_access_fn =
510 E : ::GetProcAddress(asan_rtl_, function_names[function]);
511 E : ASSERT_TRUE(check_access_fn != NULL);
512 :
513 E : MemoryAccessorTester tester;
514 : tester.ExpectSpecialMemoryErrorIsDetected(
515 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
516 E : true, &dst[0], &src[0], memory_length_ + 1, HEAP_BUFFER_OVERFLOW);
517 : tester.ExpectSpecialMemoryErrorIsDetected(
518 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
519 E : true, &dst[-1], &src[-1], memory_length_, HEAP_BUFFER_UNDERFLOW);
520 : tester.ExpectSpecialMemoryErrorIsDetected(
521 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
522 E : true, &dst[-1], &src[0], memory_length_, HEAP_BUFFER_UNDERFLOW);
523 E : }
524 :
525 E : FreeMemoryBuffers();
526 E : }
527 :
528 E : TEST_F(AsanRtlTest, AsanDirectionSpecialInstructionCheckGoodAccess) {
529 : static const char* function_names[] = {
530 : "asan_check_repz_4_byte_movs_access",
531 : "asan_check_repz_4_byte_cmps_access",
532 : "asan_check_repz_4_byte_stos_access"
533 : };
534 :
535 : // Allocate memory space.
536 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
537 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
538 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
539 :
540 : // Validate memory accesses.
541 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
542 : FARPROC check_access_fn =
543 E : ::GetProcAddress(asan_rtl_, function_names[function]);
544 E : ASSERT_TRUE(check_access_fn != NULL);
545 :
546 E : MemoryAccessorTester tester;
547 : tester.ExpectSpecialMemoryErrorIsDetected(
548 : check_access_fn, MemoryAccessorTester::DIRECTION_BACKWARD,
549 : false, &dst[memory_length_ - 1],
550 : &src[memory_length_ - 1], memory_length_,
551 E : UNKNOWN_BAD_ACCESS);
552 E : }
553 :
554 E : FreeMemoryBuffers();
555 E : }
556 :
557 E : TEST_F(AsanRtlTest, AsanSpecialInstructionCheckZeroAccess) {
558 : static const char* function_names[] = {
559 : "asan_check_repz_1_byte_movs_access",
560 : "asan_check_repz_1_byte_cmps_access",
561 : "asan_check_repz_1_byte_stos_access",
562 : "asan_check_repz_2_byte_movs_access",
563 : "asan_check_repz_2_byte_cmps_access",
564 : "asan_check_repz_2_byte_stos_access",
565 : "asan_check_repz_4_byte_movs_access",
566 : "asan_check_repz_4_byte_cmps_access",
567 : "asan_check_repz_4_byte_stos_access"
568 : };
569 :
570 : // Allocate memory space.
571 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
572 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
573 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
574 :
575 : // Validate memory accesses.
576 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
577 : FARPROC check_access_fn =
578 E : ::GetProcAddress(asan_rtl_, function_names[function]);
579 E : ASSERT_TRUE(check_access_fn != NULL);
580 :
581 : // A prefixed instruction with a count of zero do not have side effects.
582 E : MemoryAccessorTester tester;
583 : tester.ExpectSpecialMemoryErrorIsDetected(
584 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
585 E : false, &dst[-1], &src[-1], 0, UNKNOWN_BAD_ACCESS);
586 E : }
587 :
588 E : FreeMemoryBuffers();
589 E : }
590 :
591 E : TEST_F(AsanRtlTest, AsanSpecialInstructionCheckShortcutAccess) {
592 : static const char* function_names[] = {
593 : "asan_check_repz_1_byte_cmps_access",
594 : "asan_check_repz_2_byte_cmps_access",
595 : "asan_check_repz_4_byte_cmps_access",
596 : };
597 :
598 : // Allocate memory space.
599 E : AllocMemoryBuffers(kAllocSize, sizeof(uint32));
600 E : uint32* src = reinterpret_cast<uint32*>(memory_src_);
601 E : uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
602 :
603 E : src[1] = 0x12345667;
604 :
605 : // Validate memory accesses.
606 E : for (int32 function = 0; function < arraysize(function_names); ++function) {
607 : FARPROC check_access_fn =
608 E : ::GetProcAddress(asan_rtl_, function_names[function]);
609 E : ASSERT_TRUE(check_access_fn != NULL);
610 :
611 : // Compare instruction stop their execution when values differ.
612 E : MemoryAccessorTester tester;
613 : tester.ExpectSpecialMemoryErrorIsDetected(
614 : check_access_fn, MemoryAccessorTester::DIRECTION_FORWARD,
615 E : false, &dst[0], &src[0], memory_length_ + 1, UNKNOWN_BAD_ACCESS);
616 E : }
617 :
618 E : FreeMemoryBuffers();
619 E : }
620 :
621 E : TEST_F(AsanRtlTest, AllocationFilterFlag) {
622 E : agent::asan::AsanRuntime* runtime = GetActiveRuntimeFunction();
623 E : SetAllocationFilterFlagFunction();
624 E : EXPECT_TRUE(runtime->allocation_filter_flag());
625 E : ClearAllocationFilterFlagFunction();
626 E : EXPECT_FALSE(runtime->allocation_filter_flag());
627 E : SetAllocationFilterFlagFunction();
628 E : EXPECT_TRUE(runtime->allocation_filter_flag());
629 E : }
630 :
631 : } // namespace asan
632 : } // namespace agent
|