//===-- asan_noinst_test.cc -----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // This test file should be compiled w/o asan instrumentation. //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_test_utils.h" #include #include #include #include // for memset() #include #include #include #if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1 // Manually set correct ASan mapping scale and offset, as they won't be // exported from instrumented sources (there are none). # define FLEXIBLE_SHADOW_SCALE kDefaultShadowScale # if SANITIZER_ANDROID # define FLEXIBLE_SHADOW_OFFSET (0) # else # if SANITIZER_WORDSIZE == 32 # if defined(__mips__) # define FLEXIBLE_SHADOW_OFFSET kMIPS32_ShadowOffset32 # else # define FLEXIBLE_SHADOW_OFFSET kDefaultShadowOffset32 # endif # else # if defined(__powerpc64__) # define FLEXIBLE_SHADOW_OFFSET kPPC64_ShadowOffset64 # elif SANITIZER_MAC # define FLEXIBLE_SHADOW_OFFSET kDefaultShadowOffset64 # else # define FLEXIBLE_SHADOW_OFFSET kDefaultShort64bitShadowOffset # endif # endif # endif SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale = FLEXIBLE_SHADOW_SCALE; SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset = FLEXIBLE_SHADOW_OFFSET; #endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET extern "C" { // Set specific ASan options for uninstrumented unittest. const char* __asan_default_options() { return "allow_reexec=0"; } } // extern "C" // Make sure __asan_init is called before any test case is run. struct AsanInitCaller { AsanInitCaller() { __asan_init(); } }; static AsanInitCaller asan_init_caller; TEST(AddressSanitizer, InternalSimpleDeathTest) { EXPECT_DEATH(exit(1), ""); } static void MallocStress(size_t n) { u32 seed = my_rand(); StackTrace stack1; stack1.trace[0] = 0xa123; stack1.trace[1] = 0xa456; stack1.size = 2; StackTrace stack2; stack2.trace[0] = 0xb123; stack2.trace[1] = 0xb456; stack2.size = 2; StackTrace stack3; stack3.trace[0] = 0xc123; stack3.trace[1] = 0xc456; stack3.size = 2; std::vector vec; for (size_t i = 0; i < n; i++) { if ((i % 3) == 0) { if (vec.empty()) continue; size_t idx = my_rand_r(&seed) % vec.size(); void *ptr = vec[idx]; vec[idx] = vec.back(); vec.pop_back(); __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC); } else { size_t size = my_rand_r(&seed) % 1000 + 1; switch ((my_rand_r(&seed) % 128)) { case 0: size += 1024; break; case 1: size += 2048; break; case 2: size += 4096; break; } size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2, __asan::FROM_MALLOC); EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0)); vec.push_back(ptr); ptr[0] = 0; ptr[size-1] = 0; ptr[size/2] = 0; } } for (size_t i = 0; i < vec.size(); i++) __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); } TEST(AddressSanitizer, NoInstMallocTest) { MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000); } TEST(AddressSanitizer, ThreadedMallocStressTest) { const int kNumThreads = 4; const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; pthread_t t[kNumThreads]; for (int i = 0; i < kNumThreads; i++) { PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress, (void*)kNumIterations); } for (int i = 0; i < kNumThreads; i++) { PTHREAD_JOIN(t[i], 0); } } static void PrintShadow(const char *tag, uptr ptr, size_t size) { fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size); uptr prev_shadow = 0; for (sptr i = -32; i < (sptr)size + 32; i++) { uptr shadow = __asan::MemToShadow(ptr + i); if (i == 0 || i == (sptr)size) fprintf(stderr, "."); if (shadow != prev_shadow) { prev_shadow = shadow; fprintf(stderr, "%02x", (int)*(u8*)shadow); } } fprintf(stderr, "\n"); } TEST(AddressSanitizer, DISABLED_InternalPrintShadow) { for (size_t size = 1; size <= 513; size++) { char *ptr = new char[size]; PrintShadow("m", (uptr)ptr, size); delete [] ptr; PrintShadow("f", (uptr)ptr, size); } } TEST(AddressSanitizer, QuarantineTest) { StackTrace stack; stack.trace[0] = 0x890; stack.size = 1; const int size = 1024; void *p = __asan::asan_malloc(size, &stack); __asan::asan_free(p, &stack, __asan::FROM_MALLOC); size_t i; size_t max_i = 1 << 30; for (i = 0; i < max_i; i++) { void *p1 = __asan::asan_malloc(size, &stack); __asan::asan_free(p1, &stack, __asan::FROM_MALLOC); if (p1 == p) break; } EXPECT_GE(i, 10000U); EXPECT_LT(i, max_i); } void *ThreadedQuarantineTestWorker(void *unused) { (void)unused; u32 seed = my_rand(); StackTrace stack; stack.trace[0] = 0x890; stack.size = 1; for (size_t i = 0; i < 1000; i++) { void *p = __asan::asan_malloc(1 + (my_rand_r(&seed) % 4000), &stack); __asan::asan_free(p, &stack, __asan::FROM_MALLOC); } return NULL; } // Check that the thread local allocators are flushed when threads are // destroyed. TEST(AddressSanitizer, ThreadedQuarantineTest) { const int n_threads = 3000; size_t mmaped1 = __asan_get_heap_size(); for (int i = 0; i < n_threads; i++) { pthread_t t; PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0); PTHREAD_JOIN(t, 0); size_t mmaped2 = __asan_get_heap_size(); EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20)); } } void *ThreadedOneSizeMallocStress(void *unused) { (void)unused; StackTrace stack; stack.trace[0] = 0x890; stack.size = 1; const size_t kNumMallocs = 1000; for (int iter = 0; iter < 1000; iter++) { void *p[kNumMallocs]; for (size_t i = 0; i < kNumMallocs; i++) { p[i] = __asan::asan_malloc(32, &stack); } for (size_t i = 0; i < kNumMallocs; i++) { __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC); } } return NULL; } TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { const int kNumThreads = 4; pthread_t t[kNumThreads]; for (int i = 0; i < kNumThreads; i++) { PTHREAD_CREATE(&t[i], 0, ThreadedOneSizeMallocStress, 0); } for (int i = 0; i < kNumThreads; i++) { PTHREAD_JOIN(t[i], 0); } } TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) { using __asan::kHighMemEnd; // Check that __asan_region_is_poisoned works for shadow regions. uptr ptr = kLowShadowBeg + 200; EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); ptr = kShadowGapBeg + 200; EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); ptr = kHighShadowBeg + 200; EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); }