1 // Test for ASAN_OPTIONS=start_deactivated=1 mode. 2 // Main executable is uninstrumented, but linked to ASan runtime. The shared 3 // library is instrumented. Memory errors before dlopen are not detected. 4 5 // RUN: %clangxx_asan -O0 -DSHARED_LIB %s -std=c++11 -fPIC -shared -o %t-so.so 6 // RUN: %clangxx -O0 %s -std=c++11 -c -o %t.o 7 // RUN: %clangxx_asan -O0 %t.o %libdl -o %t 8 // RUN: %env_asan_opts=start_deactivated=1,allocator_may_return_null=0 \ 9 // RUN: ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 not %run %t 2>&1 | FileCheck %s 10 // RUN: %env_asan_opts=start_deactivated=1 \ 11 // RUN: ASAN_ACTIVATION_OPTIONS=help=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HELP 12 // RUN: %env_asan_opts=start_deactivated=1,verbosity=1 \ 13 // RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED 14 // RUN: %env_asan_opts=start_deactivated=1 \ 15 // RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED-V0 16 17 // Check that verbosity=1 in activation flags affects reporting of unrecognized activation flags. 18 // RUN: %env_asan_opts=start_deactivated=1 \ 19 // RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0,verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED 20 21 22 // END. 23 24 #if !defined(SHARED_LIB) 25 26 #include <assert.h> 27 #include <dlfcn.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 #include <string> 34 35 #include "sanitizer/asan_interface.h" 36 37 void test_malloc_shadow(char *p, size_t sz, bool expect_redzones) { 38 // Last byte of the left redzone, if present. 39 assert((char *)__asan_region_is_poisoned(p - 1, sz + 1) == 40 (expect_redzones ? p - 1 : nullptr)); 41 // The user memory. 42 assert((char *)__asan_region_is_poisoned(p, sz) == nullptr); 43 // First byte of the right redzone, if present. 44 assert((char *)__asan_region_is_poisoned(p, sz + 1) == 45 (expect_redzones ? p + sz : nullptr)); 46 } 47 48 typedef void (*Fn)(); 49 50 int main(int argc, char *argv[]) { 51 constexpr unsigned nPtrs = 200; 52 char *ptrs[nPtrs]; 53 54 // Before activation: no redzones. 55 for (size_t sz = 1; sz < nPtrs; ++sz) { 56 ptrs[sz] = (char *)malloc(sz); 57 test_malloc_shadow(ptrs[sz], sz, false); 58 } 59 60 // Create a honey pot for the future, instrumented, allocations. Since the 61 // quarantine is disabled, chunks are going to be recycled right away and 62 // reused for the new allocations. New allocations must get the proper 63 // redzones anyway, whether it's a fresh or reused allocation. 64 constexpr size_t HoneyPotBlockSize = 4096; 65 constexpr int HoneyPotSize = 200; 66 char *honeyPot[HoneyPotSize]; 67 for (int i = 1; i < HoneyPotSize; ++i) { 68 honeyPot[i] = (char *)malloc(HoneyPotBlockSize); 69 test_malloc_shadow(honeyPot[i], HoneyPotBlockSize, false); 70 } 71 for (int i = 1; i < HoneyPotSize; ++i) 72 free(honeyPot[i]); 73 74 std::string path = std::string(argv[0]) + "-so.so"; 75 void *dso = dlopen(path.c_str(), RTLD_NOW); 76 if (!dso) { 77 fprintf(stderr, "dlopen failed: %s\n", dlerror()); 78 return 1; 79 } 80 81 // After this line ASan is activated and starts detecting errors. 82 void *fn = dlsym(dso, "do_another_bad_thing"); 83 if (!fn) { 84 fprintf(stderr, "dlsym failed: %s\n", dlerror()); 85 return 1; 86 } 87 88 // After activation: redzones. 89 for (int i = 1; i < HoneyPotSize; ++i) { 90 honeyPot[i] = (char *)malloc(HoneyPotBlockSize); 91 test_malloc_shadow(honeyPot[i], HoneyPotBlockSize, true); 92 } 93 { 94 char *p = (char *)malloc(HoneyPotBlockSize); 95 test_malloc_shadow(p, HoneyPotBlockSize, true); 96 free(p); 97 } 98 for (int i = 1; i < HoneyPotSize; ++i) 99 free(honeyPot[i]); 100 101 // Pre-existing allocations got redzones, too. 102 for (size_t sz = 1; sz < nPtrs; ++sz) { 103 test_malloc_shadow(ptrs[sz], sz, true); 104 free(ptrs[sz]); 105 } 106 107 // Test that ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 has effect. 108 void *p = malloc((unsigned long)-2); 109 assert(!p); 110 // CHECK: WARNING: AddressSanitizer failed to allocate 0xfff{{.*}} bytes 111 112 ((Fn)fn)(); 113 // CHECK: AddressSanitizer: heap-buffer-overflow 114 // CHECK: READ of size 1 115 // CHECK: {{#0 .* in do_another_bad_thing}} 116 // CHECK: is located 5 bytes to the right of 100-byte region 117 // CHECK: in do_another_bad_thing 118 119 return 0; 120 } 121 122 #else // SHARED_LIB 123 124 #include <stdio.h> 125 #include <stdlib.h> 126 127 extern "C" void do_another_bad_thing() { 128 char *volatile p = (char *)malloc(100); 129 printf("%hhx\n", p[105]); 130 } 131 132 #endif // SHARED_LIB 133 134 // help=1 in activation flags lists only flags are are supported at activation 135 // CHECK-HELP: Available flags for {{.*}}Sanitizer: 136 // CHECK-HELP-NOT: handle_segv 137 // CHECK-HELP: max_redzone 138 // CHECK-HELP-NOT: handle_segv 139 140 // unsupported activation flags produce a warning ... 141 // CHECK-UNSUPPORTED: WARNING: found 1 unrecognized 142 // CHECK-UNSUPPORTED: handle_segv 143 144 // ... but not at verbosity=0 145 // CHECK-UNSUPPORTED-V0-NOT: WARNING: found {{.*}} unrecognized 146