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