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