asan_noinst_test.cc revision a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660
1//===-- asan_noinst_test.cc -----------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of AddressSanitizer, an address sanity checker. 11// 12// This test file should be compiled w/o asan instrumentation. 13//===----------------------------------------------------------------------===// 14 15#include "asan_allocator.h" 16#include "asan_internal.h" 17#include "asan_mapping.h" 18#include "asan_stack.h" 19#include "asan_test_utils.h" 20#include "sanitizer/asan_interface.h" 21 22#include <assert.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> // for memset() 26#include <algorithm> 27#include <vector> 28 29 30TEST(AddressSanitizer, InternalSimpleDeathTest) { 31 EXPECT_DEATH(exit(1), ""); 32} 33 34static void MallocStress(size_t n) { 35 u32 seed = my_rand(); 36 __asan::StackTrace stack1; 37 stack1.trace[0] = 0xa123; 38 stack1.trace[1] = 0xa456; 39 stack1.size = 2; 40 41 __asan::StackTrace stack2; 42 stack2.trace[0] = 0xb123; 43 stack2.trace[1] = 0xb456; 44 stack2.size = 2; 45 46 __asan::StackTrace stack3; 47 stack3.trace[0] = 0xc123; 48 stack3.trace[1] = 0xc456; 49 stack3.size = 2; 50 51 std::vector<void *> vec; 52 for (size_t i = 0; i < n; i++) { 53 if ((i % 3) == 0) { 54 if (vec.empty()) continue; 55 size_t idx = my_rand_r(&seed) % vec.size(); 56 void *ptr = vec[idx]; 57 vec[idx] = vec.back(); 58 vec.pop_back(); 59 __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC); 60 } else { 61 size_t size = my_rand_r(&seed) % 1000 + 1; 62 switch ((my_rand_r(&seed) % 128)) { 63 case 0: size += 1024; break; 64 case 1: size += 2048; break; 65 case 2: size += 4096; break; 66 } 67 size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); 68 char *ptr = (char*)__asan::asan_memalign(alignment, size, 69 &stack2, __asan::FROM_MALLOC); 70 vec.push_back(ptr); 71 ptr[0] = 0; 72 ptr[size-1] = 0; 73 ptr[size/2] = 0; 74 } 75 } 76 for (size_t i = 0; i < vec.size(); i++) 77 __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); 78} 79 80 81TEST(AddressSanitizer, NoInstMallocTest) { 82#ifdef __arm__ 83 MallocStress(300000); 84#else 85 MallocStress(1000000); 86#endif 87} 88 89static void PrintShadow(const char *tag, uptr ptr, size_t size) { 90 fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size); 91 uptr prev_shadow = 0; 92 for (sptr i = -32; i < (sptr)size + 32; i++) { 93 uptr shadow = __asan::MemToShadow(ptr + i); 94 if (i == 0 || i == (sptr)size) 95 fprintf(stderr, "."); 96 if (shadow != prev_shadow) { 97 prev_shadow = shadow; 98 fprintf(stderr, "%02x", (int)*(u8*)shadow); 99 } 100 } 101 fprintf(stderr, "\n"); 102} 103 104TEST(AddressSanitizer, DISABLED_InternalPrintShadow) { 105 for (size_t size = 1; size <= 513; size++) { 106 char *ptr = new char[size]; 107 PrintShadow("m", (uptr)ptr, size); 108 delete [] ptr; 109 PrintShadow("f", (uptr)ptr, size); 110 } 111} 112 113static uptr pc_array[] = { 114#if SANITIZER_WORDSIZE == 64 115 0x7effbf756068ULL, 116 0x7effbf75e5abULL, 117 0x7effc0625b7cULL, 118 0x7effc05b8997ULL, 119 0x7effbf990577ULL, 120 0x7effbf990c56ULL, 121 0x7effbf992f3cULL, 122 0x7effbf950c22ULL, 123 0x7effc036dba0ULL, 124 0x7effc03638a3ULL, 125 0x7effc035be4aULL, 126 0x7effc0539c45ULL, 127 0x7effc0539a65ULL, 128 0x7effc03db9b3ULL, 129 0x7effc03db100ULL, 130 0x7effc037c7b8ULL, 131 0x7effc037bfffULL, 132 0x7effc038b777ULL, 133 0x7effc038021cULL, 134 0x7effc037c7d1ULL, 135 0x7effc037bfffULL, 136 0x7effc038b777ULL, 137 0x7effc038021cULL, 138 0x7effc037c7d1ULL, 139 0x7effc037bfffULL, 140 0x7effc038b777ULL, 141 0x7effc038021cULL, 142 0x7effc037c7d1ULL, 143 0x7effc037bfffULL, 144 0x7effc0520d26ULL, 145 0x7effc009ddffULL, 146 0x7effbf90bb50ULL, 147 0x7effbdddfa69ULL, 148 0x7effbdde1fe2ULL, 149 0x7effbdde2424ULL, 150 0x7effbdde27b3ULL, 151 0x7effbddee53bULL, 152 0x7effbdde1988ULL, 153 0x7effbdde0904ULL, 154 0x7effc106ce0dULL, 155 0x7effbcc3fa04ULL, 156 0x7effbcc3f6a4ULL, 157 0x7effbcc3e726ULL, 158 0x7effbcc40852ULL, 159 0x7effb681ec4dULL, 160#endif // SANITIZER_WORDSIZE 161 0xB0B5E768, 162 0x7B682EC1, 163 0x367F9918, 164 0xAE34E13, 165 0xBA0C6C6, 166 0x13250F46, 167 0xA0D6A8AB, 168 0x2B07C1A8, 169 0x6C844F4A, 170 0x2321B53, 171 0x1F3D4F8F, 172 0x3FE2924B, 173 0xB7A2F568, 174 0xBD23950A, 175 0x61020930, 176 0x33E7970C, 177 0x405998A1, 178 0x59F3551D, 179 0x350E3028, 180 0xBC55A28D, 181 0x361F3AED, 182 0xBEAD0F73, 183 0xAEF28479, 184 0x757E971F, 185 0xAEBA450, 186 0x43AD22F5, 187 0x8C2C50C4, 188 0x7AD8A2E1, 189 0x69EE4EE8, 190 0xC08DFF, 191 0x4BA6538, 192 0x3708AB2, 193 0xC24B6475, 194 0x7C8890D7, 195 0x6662495F, 196 0x9B641689, 197 0xD3596B, 198 0xA1049569, 199 0x44CBC16, 200 0x4D39C39F 201}; 202 203void CompressStackTraceTest(size_t n_iter) { 204 u32 seed = my_rand(); 205 const size_t kNumPcs = ARRAY_SIZE(pc_array); 206 u32 compressed[2 * kNumPcs]; 207 208 for (size_t iter = 0; iter < n_iter; iter++) { 209 std::random_shuffle(pc_array, pc_array + kNumPcs); 210 __asan::StackTrace stack0, stack1; 211 stack0.CopyFrom(pc_array, kNumPcs); 212 stack0.size = std::max((size_t)1, (size_t)(my_rand_r(&seed) % stack0.size)); 213 size_t compress_size = 214 std::max((size_t)2, (size_t)my_rand_r(&seed) % (2 * kNumPcs)); 215 size_t n_frames = 216 __asan::StackTrace::CompressStack(&stack0, compressed, compress_size); 217 Ident(n_frames); 218 assert(n_frames <= stack0.size); 219 __asan::StackTrace::UncompressStack(&stack1, compressed, compress_size); 220 assert(stack1.size == n_frames); 221 for (size_t i = 0; i < stack1.size; i++) { 222 assert(stack0.trace[i] == stack1.trace[i]); 223 } 224 } 225} 226 227TEST(AddressSanitizer, CompressStackTraceTest) { 228 CompressStackTraceTest(10000); 229} 230 231void CompressStackTraceBenchmark(size_t n_iter) { 232 const size_t kNumPcs = ARRAY_SIZE(pc_array); 233 u32 compressed[2 * kNumPcs]; 234 std::random_shuffle(pc_array, pc_array + kNumPcs); 235 236 __asan::StackTrace stack0; 237 stack0.CopyFrom(pc_array, kNumPcs); 238 stack0.size = kNumPcs; 239 for (size_t iter = 0; iter < n_iter; iter++) { 240 size_t compress_size = kNumPcs; 241 size_t n_frames = 242 __asan::StackTrace::CompressStack(&stack0, compressed, compress_size); 243 Ident(n_frames); 244 } 245} 246 247TEST(AddressSanitizer, CompressStackTraceBenchmark) { 248 CompressStackTraceBenchmark(1 << 24); 249} 250 251TEST(AddressSanitizer, QuarantineTest) { 252 __asan::StackTrace stack; 253 stack.trace[0] = 0x890; 254 stack.size = 1; 255 256 const int size = 32; 257 void *p = __asan::asan_malloc(size, &stack); 258 __asan::asan_free(p, &stack, __asan::FROM_MALLOC); 259 size_t i; 260 size_t max_i = 1 << 30; 261 for (i = 0; i < max_i; i++) { 262 void *p1 = __asan::asan_malloc(size, &stack); 263 __asan::asan_free(p1, &stack, __asan::FROM_MALLOC); 264 if (p1 == p) break; 265 } 266 // fprintf(stderr, "i=%ld\n", i); 267 EXPECT_GE(i, 100000U); 268 EXPECT_LT(i, max_i); 269} 270 271void *ThreadedQuarantineTestWorker(void *unused) { 272 (void)unused; 273 u32 seed = my_rand(); 274 __asan::StackTrace stack; 275 stack.trace[0] = 0x890; 276 stack.size = 1; 277 278 for (size_t i = 0; i < 1000; i++) { 279 void *p = __asan::asan_malloc(1 + (my_rand_r(&seed) % 4000), &stack); 280 __asan::asan_free(p, &stack, __asan::FROM_MALLOC); 281 } 282 return NULL; 283} 284 285// Check that the thread local allocators are flushed when threads are 286// destroyed. 287TEST(AddressSanitizer, ThreadedQuarantineTest) { 288 const int n_threads = 3000; 289 size_t mmaped1 = __asan_get_heap_size(); 290 for (int i = 0; i < n_threads; i++) { 291 pthread_t t; 292 PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0); 293 PTHREAD_JOIN(t, 0); 294 size_t mmaped2 = __asan_get_heap_size(); 295 EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20)); 296 } 297} 298 299void *ThreadedOneSizeMallocStress(void *unused) { 300 (void)unused; 301 __asan::StackTrace stack; 302 stack.trace[0] = 0x890; 303 stack.size = 1; 304 const size_t kNumMallocs = 1000; 305 for (int iter = 0; iter < 1000; iter++) { 306 void *p[kNumMallocs]; 307 for (size_t i = 0; i < kNumMallocs; i++) { 308 p[i] = __asan::asan_malloc(32, &stack); 309 } 310 for (size_t i = 0; i < kNumMallocs; i++) { 311 __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC); 312 } 313 } 314 return NULL; 315} 316 317TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { 318 const int kNumThreads = 4; 319 pthread_t t[kNumThreads]; 320 for (int i = 0; i < kNumThreads; i++) { 321 PTHREAD_CREATE(&t[i], 0, ThreadedOneSizeMallocStress, 0); 322 } 323 for (int i = 0; i < kNumThreads; i++) { 324 PTHREAD_JOIN(t[i], 0); 325 } 326} 327 328TEST(AddressSanitizer, MemsetWildAddressTest) { 329 typedef void*(*memset_p)(void*, int, size_t); 330 // Prevent inlining of memset(). 331 volatile memset_p libc_memset = (memset_p)memset; 332 EXPECT_DEATH(libc_memset((void*)(kLowShadowBeg + 200), 0, 100), 333 (kLowShadowEnd == 0) ? "unknown-crash.*shadow gap" 334 : "unknown-crash.*low shadow"); 335 EXPECT_DEATH(libc_memset((void*)(kShadowGapBeg + 200), 0, 100), 336 "unknown-crash.*shadow gap"); 337 EXPECT_DEATH(libc_memset((void*)(kHighShadowBeg + 200), 0, 100), 338 "unknown-crash.*high shadow"); 339} 340 341TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) { 342#if ASAN_ALLOCATOR_VERSION == 1 343 EXPECT_EQ(1U, __asan_get_estimated_allocated_size(0)); 344#elif ASAN_ALLOCATOR_VERSION == 2 345 EXPECT_EQ(0U, __asan_get_estimated_allocated_size(0)); 346#endif 347 const size_t sizes[] = { 1, 30, 1<<30 }; 348 for (size_t i = 0; i < 3; i++) { 349 EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i])); 350 } 351} 352 353static const char* kGetAllocatedSizeErrorMsg = 354 "attempting to call __asan_get_allocated_size()"; 355 356TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) { 357 const size_t kArraySize = 100; 358 char *array = Ident((char*)malloc(kArraySize)); 359 int *int_ptr = Ident(new int); 360 361 // Allocated memory is owned by allocator. Allocated size should be 362 // equal to requested size. 363 EXPECT_EQ(true, __asan_get_ownership(array)); 364 EXPECT_EQ(kArraySize, __asan_get_allocated_size(array)); 365 EXPECT_EQ(true, __asan_get_ownership(int_ptr)); 366 EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr)); 367 368 // We cannot call GetAllocatedSize from the memory we didn't map, 369 // and from the interior pointers (not returned by previous malloc). 370 void *wild_addr = (void*)0x1; 371 EXPECT_FALSE(__asan_get_ownership(wild_addr)); 372 EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg); 373 EXPECT_FALSE(__asan_get_ownership(array + kArraySize / 2)); 374 EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2), 375 kGetAllocatedSizeErrorMsg); 376 377 // NULL is not owned, but is a valid argument for __asan_get_allocated_size(). 378 EXPECT_FALSE(__asan_get_ownership(NULL)); 379 EXPECT_EQ(0U, __asan_get_allocated_size(NULL)); 380 381 // When memory is freed, it's not owned, and call to GetAllocatedSize 382 // is forbidden. 383 free(array); 384 EXPECT_FALSE(__asan_get_ownership(array)); 385 EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg); 386 delete int_ptr; 387 388 void *zero_alloc = Ident(malloc(0)); 389 if (zero_alloc != 0) { 390 // If malloc(0) is not null, this pointer is owned and should have valid 391 // allocated size. 392 EXPECT_TRUE(__asan_get_ownership(zero_alloc)); 393 // Allocated size is 0 or 1 depending on the allocator used. 394 EXPECT_LT(__asan_get_allocated_size(zero_alloc), 2U); 395 } 396 free(zero_alloc); 397} 398 399TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) { 400 size_t before_malloc, after_malloc, after_free; 401 char *array; 402 const size_t kMallocSize = 100; 403 before_malloc = __asan_get_current_allocated_bytes(); 404 405 array = Ident((char*)malloc(kMallocSize)); 406 after_malloc = __asan_get_current_allocated_bytes(); 407 EXPECT_EQ(before_malloc + kMallocSize, after_malloc); 408 409 free(array); 410 after_free = __asan_get_current_allocated_bytes(); 411 EXPECT_EQ(before_malloc, after_free); 412} 413 414static void DoDoubleFree() { 415 int *x = Ident(new int); 416 delete Ident(x); 417 delete Ident(x); 418} 419 420#if ASAN_ALLOCATOR_VERSION == 1 421// This test is run in a separate process, so that large malloced 422// chunk won't remain in the free lists after the test. 423// Note: use ASSERT_* instead of EXPECT_* here. 424static void RunGetHeapSizeTestAndDie() { 425 size_t old_heap_size, new_heap_size, heap_growth; 426 // We unlikely have have chunk of this size in free list. 427 static const size_t kLargeMallocSize = 1 << 29; // 512M 428 old_heap_size = __asan_get_heap_size(); 429 fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize); 430 free(Ident(malloc(kLargeMallocSize))); 431 new_heap_size = __asan_get_heap_size(); 432 heap_growth = new_heap_size - old_heap_size; 433 fprintf(stderr, "heap growth after first malloc: %zu\n", heap_growth); 434 ASSERT_GE(heap_growth, kLargeMallocSize); 435 ASSERT_LE(heap_growth, 2 * kLargeMallocSize); 436 437 // Now large chunk should fall into free list, and can be 438 // allocated without increasing heap size. 439 old_heap_size = new_heap_size; 440 free(Ident(malloc(kLargeMallocSize))); 441 heap_growth = __asan_get_heap_size() - old_heap_size; 442 fprintf(stderr, "heap growth after second malloc: %zu\n", heap_growth); 443 ASSERT_LT(heap_growth, kLargeMallocSize); 444 445 // Test passed. Now die with expected double-free. 446 DoDoubleFree(); 447} 448 449TEST(AddressSanitizerInterface, GetHeapSizeTest) { 450 EXPECT_DEATH(RunGetHeapSizeTestAndDie(), "double-free"); 451} 452#elif ASAN_ALLOCATOR_VERSION == 2 453TEST(AddressSanitizerInterface, GetHeapSizeTest) { 454 // asan_allocator2 does not keep huge chunks in free list, but unmaps them. 455 // The chunk should be greater than the quarantine size, 456 // otherwise it will be stuck in quarantine instead of being unmaped. 457 static const size_t kLargeMallocSize = 1 << 29; // 512M 458 uptr old_heap_size = __asan_get_heap_size(); 459 for (int i = 0; i < 3; i++) { 460 // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize); 461 free(Ident(malloc(kLargeMallocSize))); 462 EXPECT_EQ(old_heap_size, __asan_get_heap_size()); 463 } 464} 465#endif 466 467// Note: use ASSERT_* instead of EXPECT_* here. 468static void DoLargeMallocForGetFreeBytesTestAndDie() { 469#if ASAN_ALLOCATOR_VERSION == 1 470 // asan_allocator2 does not keep large chunks in free_lists, so this test 471 // will not work. 472 size_t old_free_bytes, new_free_bytes; 473 static const size_t kLargeMallocSize = 1 << 29; // 512M 474 // If we malloc and free a large memory chunk, it will not fall 475 // into quarantine and will be available for future requests. 476 old_free_bytes = __asan_get_free_bytes(); 477 fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize); 478 fprintf(stderr, "free bytes before malloc: %zu\n", old_free_bytes); 479 free(Ident(malloc(kLargeMallocSize))); 480 new_free_bytes = __asan_get_free_bytes(); 481 fprintf(stderr, "free bytes after malloc and free: %zu\n", new_free_bytes); 482 ASSERT_GE(new_free_bytes, old_free_bytes + kLargeMallocSize); 483#endif // ASAN_ALLOCATOR_VERSION 484 // Test passed. 485 DoDoubleFree(); 486} 487 488TEST(AddressSanitizerInterface, GetFreeBytesTest) { 489#if ASAN_ALLOCATOR_VERSION == 1 490 // Allocate a small chunk. Now allocator probably has a lot of these 491 // chunks to fulfill future requests. So, future requests will decrease 492 // the number of free bytes. Do this only on systems where there 493 // is enough memory for such assumptions. 494 if (SANITIZER_WORDSIZE == 64 && !ASAN_LOW_MEMORY) { 495 static const size_t kNumOfChunks = 100; 496 static const size_t kChunkSize = 100; 497 char *chunks[kNumOfChunks]; 498 size_t i; 499 size_t old_free_bytes, new_free_bytes; 500 chunks[0] = Ident((char*)malloc(kChunkSize)); 501 old_free_bytes = __asan_get_free_bytes(); 502 for (i = 1; i < kNumOfChunks; i++) { 503 chunks[i] = Ident((char*)malloc(kChunkSize)); 504 new_free_bytes = __asan_get_free_bytes(); 505 EXPECT_LT(new_free_bytes, old_free_bytes); 506 old_free_bytes = new_free_bytes; 507 } 508 for (i = 0; i < kNumOfChunks; i++) 509 free(chunks[i]); 510 } 511#endif 512 EXPECT_DEATH(DoLargeMallocForGetFreeBytesTestAndDie(), "double-free"); 513} 514 515static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357}; 516static const size_t kManyThreadsIterations = 250; 517static const size_t kManyThreadsNumThreads = 518 (SANITIZER_WORDSIZE == 32) ? 40 : 200; 519 520void *ManyThreadsWithStatsWorker(void *arg) { 521 (void)arg; 522 for (size_t iter = 0; iter < kManyThreadsIterations; iter++) { 523 for (size_t size_index = 0; size_index < 4; size_index++) { 524 free(Ident(malloc(kManyThreadsMallocSizes[size_index]))); 525 } 526 } 527 // Just one large allocation. 528 free(Ident(malloc(1 << 20))); 529 return 0; 530} 531 532TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) { 533 size_t before_test, after_test, i; 534 pthread_t threads[kManyThreadsNumThreads]; 535 before_test = __asan_get_current_allocated_bytes(); 536 for (i = 0; i < kManyThreadsNumThreads; i++) { 537 PTHREAD_CREATE(&threads[i], 0, 538 (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i); 539 } 540 for (i = 0; i < kManyThreadsNumThreads; i++) { 541 PTHREAD_JOIN(threads[i], 0); 542 } 543 after_test = __asan_get_current_allocated_bytes(); 544 // ASan stats also reflect memory usage of internal ASan RTL structs, 545 // so we can't check for equality here. 546 EXPECT_LT(after_test, before_test + (1UL<<20)); 547} 548 549TEST(AddressSanitizerInterface, ExitCode) { 550 int original_exit_code = __asan_set_error_exit_code(7); 551 EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), ""); 552 EXPECT_EQ(7, __asan_set_error_exit_code(8)); 553 EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), ""); 554 EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code)); 555 EXPECT_EXIT(DoDoubleFree(), 556 ::testing::ExitedWithCode(original_exit_code), ""); 557} 558 559static void MyDeathCallback() { 560 fprintf(stderr, "MyDeathCallback\n"); 561} 562 563TEST(AddressSanitizerInterface, DeathCallbackTest) { 564 __asan_set_death_callback(MyDeathCallback); 565 EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback"); 566 __asan_set_death_callback(NULL); 567} 568 569static const char* kUseAfterPoisonErrorMessage = "use-after-poison"; 570 571#define GOOD_ACCESS(ptr, offset) \ 572 EXPECT_FALSE(__asan::AddressIsPoisoned((uptr)(ptr + offset))) 573 574#define BAD_ACCESS(ptr, offset) \ 575 EXPECT_TRUE(__asan::AddressIsPoisoned((uptr)(ptr + offset))) 576 577TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) { 578 char *array = Ident((char*)malloc(120)); 579 // poison array[40..80) 580 __asan_poison_memory_region(array + 40, 40); 581 GOOD_ACCESS(array, 39); 582 GOOD_ACCESS(array, 80); 583 BAD_ACCESS(array, 40); 584 BAD_ACCESS(array, 60); 585 BAD_ACCESS(array, 79); 586 EXPECT_DEATH(__asan_report_error(0, 0, 0, (uptr)(array + 40), true, 1), 587 kUseAfterPoisonErrorMessage); 588 __asan_unpoison_memory_region(array + 40, 40); 589 // access previously poisoned memory. 590 GOOD_ACCESS(array, 40); 591 GOOD_ACCESS(array, 79); 592 free(array); 593} 594 595TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) { 596 char *array = Ident((char*)malloc(120)); 597 // Poison [0..40) and [80..120) 598 __asan_poison_memory_region(array, 40); 599 __asan_poison_memory_region(array + 80, 40); 600 BAD_ACCESS(array, 20); 601 GOOD_ACCESS(array, 60); 602 BAD_ACCESS(array, 100); 603 // Poison whole array - [0..120) 604 __asan_poison_memory_region(array, 120); 605 BAD_ACCESS(array, 60); 606 // Unpoison [24..96) 607 __asan_unpoison_memory_region(array + 24, 72); 608 BAD_ACCESS(array, 23); 609 GOOD_ACCESS(array, 24); 610 GOOD_ACCESS(array, 60); 611 GOOD_ACCESS(array, 95); 612 BAD_ACCESS(array, 96); 613 free(array); 614} 615 616TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) { 617 // Vector of capacity 20 618 char *vec = Ident((char*)malloc(20)); 619 __asan_poison_memory_region(vec, 20); 620 for (size_t i = 0; i < 7; i++) { 621 // Simulate push_back. 622 __asan_unpoison_memory_region(vec + i, 1); 623 GOOD_ACCESS(vec, i); 624 BAD_ACCESS(vec, i + 1); 625 } 626 for (size_t i = 7; i > 0; i--) { 627 // Simulate pop_back. 628 __asan_poison_memory_region(vec + i - 1, 1); 629 BAD_ACCESS(vec, i - 1); 630 if (i > 1) GOOD_ACCESS(vec, i - 2); 631 } 632 free(vec); 633} 634 635TEST(AddressSanitizerInterface, GlobalRedzones) { 636 GOOD_ACCESS(glob1, 1 - 1); 637 GOOD_ACCESS(glob2, 2 - 1); 638 GOOD_ACCESS(glob3, 3 - 1); 639 GOOD_ACCESS(glob4, 4 - 1); 640 GOOD_ACCESS(glob5, 5 - 1); 641 GOOD_ACCESS(glob6, 6 - 1); 642 GOOD_ACCESS(glob7, 7 - 1); 643 GOOD_ACCESS(glob8, 8 - 1); 644 GOOD_ACCESS(glob9, 9 - 1); 645 GOOD_ACCESS(glob10, 10 - 1); 646 GOOD_ACCESS(glob11, 11 - 1); 647 GOOD_ACCESS(glob12, 12 - 1); 648 GOOD_ACCESS(glob13, 13 - 1); 649 GOOD_ACCESS(glob14, 14 - 1); 650 GOOD_ACCESS(glob15, 15 - 1); 651 GOOD_ACCESS(glob16, 16 - 1); 652 GOOD_ACCESS(glob17, 17 - 1); 653 654 BAD_ACCESS(glob1, 1); 655 BAD_ACCESS(glob2, 2); 656 BAD_ACCESS(glob3, 3); 657 BAD_ACCESS(glob4, 4); 658 BAD_ACCESS(glob5, 5); 659 BAD_ACCESS(glob6, 6); 660 BAD_ACCESS(glob7, 7); 661 BAD_ACCESS(glob8, 8); 662 BAD_ACCESS(glob9, 9); 663 BAD_ACCESS(glob10, 10); 664 BAD_ACCESS(glob11, 11); 665 BAD_ACCESS(glob12, 12); 666 BAD_ACCESS(glob13, 13); 667 BAD_ACCESS(glob14, 14); 668 BAD_ACCESS(glob15, 15); 669 BAD_ACCESS(glob16, 16); 670 BAD_ACCESS(glob17, 17); 671} 672 673// Make sure that each aligned block of size "2^granularity" doesn't have 674// "true" value before "false" value. 675static void MakeShadowValid(bool *shadow, int length, int granularity) { 676 bool can_be_poisoned = true; 677 for (int i = length - 1; i >= 0; i--) { 678 if (!shadow[i]) 679 can_be_poisoned = false; 680 if (!can_be_poisoned) 681 shadow[i] = false; 682 if (i % (1 << granularity) == 0) { 683 can_be_poisoned = true; 684 } 685 } 686} 687 688TEST(AddressSanitizerInterface, PoisoningStressTest) { 689 const size_t kSize = 24; 690 bool expected[kSize]; 691 char *arr = Ident((char*)malloc(kSize)); 692 for (size_t l1 = 0; l1 < kSize; l1++) { 693 for (size_t s1 = 1; l1 + s1 <= kSize; s1++) { 694 for (size_t l2 = 0; l2 < kSize; l2++) { 695 for (size_t s2 = 1; l2 + s2 <= kSize; s2++) { 696 // Poison [l1, l1+s1), [l2, l2+s2) and check result. 697 __asan_unpoison_memory_region(arr, kSize); 698 __asan_poison_memory_region(arr + l1, s1); 699 __asan_poison_memory_region(arr + l2, s2); 700 memset(expected, false, kSize); 701 memset(expected + l1, true, s1); 702 MakeShadowValid(expected, kSize, /*granularity*/ 3); 703 memset(expected + l2, true, s2); 704 MakeShadowValid(expected, kSize, /*granularity*/ 3); 705 for (size_t i = 0; i < kSize; i++) { 706 ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); 707 } 708 // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result. 709 __asan_poison_memory_region(arr, kSize); 710 __asan_unpoison_memory_region(arr + l1, s1); 711 __asan_unpoison_memory_region(arr + l2, s2); 712 memset(expected, true, kSize); 713 memset(expected + l1, false, s1); 714 MakeShadowValid(expected, kSize, /*granularity*/ 3); 715 memset(expected + l2, false, s2); 716 MakeShadowValid(expected, kSize, /*granularity*/ 3); 717 for (size_t i = 0; i < kSize; i++) { 718 ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); 719 } 720 } 721 } 722 } 723 } 724} 725 726TEST(AddressSanitizerInterface, PoisonedRegion) { 727 size_t rz = 16; 728 for (size_t size = 1; size <= 64; size++) { 729 char *p = new char[size]; 730 uptr x = reinterpret_cast<uptr>(p); 731 for (size_t beg = 0; beg < size + rz; beg++) { 732 for (size_t end = beg; end < size + rz; end++) { 733 uptr first_poisoned = __asan_region_is_poisoned(x + beg, end - beg); 734 if (beg == end) { 735 EXPECT_FALSE(first_poisoned); 736 } else if (beg < size && end <= size) { 737 EXPECT_FALSE(first_poisoned); 738 } else if (beg >= size) { 739 EXPECT_EQ(x + beg, first_poisoned); 740 } else { 741 EXPECT_GT(end, size); 742 EXPECT_EQ(x + size, first_poisoned); 743 } 744 } 745 } 746 delete [] p; 747 } 748} 749 750// This is a performance benchmark for manual runs. 751// asan's memset interceptor calls mem_is_zero for the entire shadow region. 752// the profile should look like this: 753// 89.10% [.] __memset_sse2 754// 10.50% [.] __sanitizer::mem_is_zero 755// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles 756// than memset itself. 757TEST(AddressSanitizerInterface, DISABLED_Stress_memset) { 758 size_t size = 1 << 20; 759 char *x = new char[size]; 760 for (int i = 0; i < 100000; i++) 761 Ident(memset)(x, 0, size); 762 delete [] x; 763} 764 765static const char *kInvalidPoisonMessage = "invalid-poison-memory-range"; 766static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range"; 767 768TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) { 769 char *array = Ident((char*)malloc(120)); 770 __asan_unpoison_memory_region(array, 120); 771 // Try to unpoison not owned memory 772 EXPECT_DEATH(__asan_unpoison_memory_region(array, 121), 773 kInvalidUnpoisonMessage); 774 EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120), 775 kInvalidUnpoisonMessage); 776 777 __asan_poison_memory_region(array, 120); 778 // Try to poison not owned memory. 779 EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage); 780 EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120), 781 kInvalidPoisonMessage); 782 free(array); 783} 784 785static void ErrorReportCallbackOneToZ(const char *report) { 786 int report_len = strlen(report); 787 ASSERT_EQ(6, write(2, "ABCDEF", 6)); 788 ASSERT_EQ(report_len, write(2, report, report_len)); 789 ASSERT_EQ(6, write(2, "ABCDEF", 6)); 790 _exit(1); 791} 792 793TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) { 794 __asan_set_error_report_callback(ErrorReportCallbackOneToZ); 795 EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1), 796 ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF"); 797 __asan_set_error_report_callback(NULL); 798} 799 800TEST(AddressSanitizerInterface, GetOwnershipStressTest) { 801 std::vector<char *> pointers; 802 std::vector<size_t> sizes; 803#if ASAN_ALLOCATOR_VERSION == 1 804 const size_t kNumMallocs = 805 (SANITIZER_WORDSIZE <= 32 || ASAN_LOW_MEMORY) ? 1 << 10 : 1 << 14; 806#elif ASAN_ALLOCATOR_VERSION == 2 // too slow with asan_allocator2. :( 807 const size_t kNumMallocs = 1 << 9; 808#endif 809 for (size_t i = 0; i < kNumMallocs; i++) { 810 size_t size = i * 100 + 1; 811 pointers.push_back((char*)malloc(size)); 812 sizes.push_back(size); 813 } 814 for (size_t i = 0; i < 4000000; i++) { 815 EXPECT_FALSE(__asan_get_ownership(&pointers)); 816 EXPECT_FALSE(__asan_get_ownership((void*)0x1234)); 817 size_t idx = i % kNumMallocs; 818 EXPECT_TRUE(__asan_get_ownership(pointers[idx])); 819 EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx])); 820 } 821 for (size_t i = 0, n = pointers.size(); i < n; i++) 822 free(pointers[i]); 823} 824