121 lines · cpp
1// Test to demonstrate compile-time disabling of container-overflow checks2// in order to handle uninstrumented libraries3// UNSUPPORTED: target={{.*windows-.*}}4 5// Mimic a closed-source library compiled without ASan6// RUN: %clangxx_asan -fno-sanitize=address -DSHARED_LIB %s %fPIC -shared -o %t-so.so7 8// Mimic multiple files being linked into a single executable,9// %t-object.o and %t-main compiled seperately and then linked together10// RUN: %clangxx_asan -DMULTI_SOURCE %s -c -o %t-object.o11// RUN: %clangxx_asan %s -c -o %t-main.o12// RUN: %clangxx_asan -o %t %t-main.o %t-object.o %libdl13// RUN: not %run %t 2>&1 | FileCheck %s14 15// Disable container overflow checks at runtime using ASAN_OPTIONS=detect_container_overflow=016// RUN: %env_asan_opts=detect_container_overflow=0 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s17 18// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -DMULTI_SOURCE %s -c -o %t-object.o19// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ %s -c -o %t-main.o20// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -o %t %t-main.o %t-object.o %libdl21// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s22//23// UNSUPPORTED: true24 25#include <assert.h>26#include <sanitizer/common_interface_defs.h>27#include <stdio.h>28 29template <typename T> class Stack {30private:31 T data[5];32 size_t size;33 34public:35 Stack() : size(0) {36#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__37 // Mark entire storage as unaddressable initially38 __sanitizer_annotate_contiguous_container(data, data + 5, data + 5, data);39#endif40 }41 42 ~Stack() {43#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__44 __sanitizer_annotate_contiguous_container(data, data + 5, data + size,45 data + 5);46#endif47 }48 49 void push(const T &value) {50 assert(size < 5 && "Stack overflow");51#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__52 __sanitizer_annotate_contiguous_container(data, data + 5, data + size,53 data + size + 1);54#endif55 data[size++] = value;56 }57 58 T pop() {59 assert(size > 0 && "Cannot pop from empty stack");60 T result = data[--size];61#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__62 __sanitizer_annotate_contiguous_container(data, data + 5, data + size + 1,63 data + size);64#endif65 return result;66 }67};68 69#ifdef SHARED_LIB70// Mimics a closed-source library compiled without ASan71 72extern "C" void push_value_to_stack(Stack<int> &stack) { stack.push(42); }73#else // SHARED_LIB74 75# include <dlfcn.h>76# include <string>77 78typedef void (*push_func_t)(Stack<int> &);79 80# if defined(MULTI_SOURCE)81extern push_func_t push_value;82 83extern "C" void do_push_value_to_stack(Stack<int> &stack) {84 assert(push_value);85 push_value(stack);86}87 88# else89push_func_t push_value = nullptr;90 91extern "C" void do_push_value_to_stack(Stack<int> &stack);92 93int main(int argc, char *argv[]) {94 std::string path = std::string(argv[0]) + "-so.so";95 printf("Loading library: %s\n", path.c_str());96 97 void *lib = dlopen(path.c_str(), RTLD_NOW);98 assert(lib);99 100 push_value = (push_func_t)dlsym(lib, "push_value_to_stack");101 assert(push_value);102 103 Stack<int> stack;104 do_push_value_to_stack(stack);105 106 // BOOM! uninstrumented library didn't update container bounds107 int value = stack.pop();108 // CHECK: AddressSanitizer: container-overflow109 printf("Popped value: %d\n", value);110 assert(value == 42 && "Expected value 42");111 112 dlclose(lib);113 printf("SUCCESS\n");114 // CHECK-NO-CONTAINER-OVERFLOW: SUCCESS115 return 0;116}117 118# endif // MULTI_SOURCE119 120#endif // SHARED_LIB121