diff --git a/compiler-rt/test/asan/TestCases/disable_container_overflow_checks.cpp b/compiler-rt/test/asan/TestCases/disable_container_overflow_checks.c similarity index 92% rename from compiler-rt/test/asan/TestCases/disable_container_overflow_checks.cpp rename to compiler-rt/test/asan/TestCases/disable_container_overflow_checks.c index 585be8bab687..470131291e91 100644 --- a/compiler-rt/test/asan/TestCases/disable_container_overflow_checks.cpp +++ b/compiler-rt/test/asan/TestCases/disable_container_overflow_checks.c @@ -1,6 +1,6 @@ // Test crash gives guidance on -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ and // ASAN_OPTIONS=detect_container_overflow=0 -// RUN: %clangxx_asan -O %s -o %t +// RUN: %clang_asan -O %s -o %t // RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s // // Test overflow checks can be disabled at runtime with @@ -9,7 +9,7 @@ // // Illustrate use of -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ flag to suppress // overflow checks at compile time. -// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -O %s -o %t-no-overflow +// RUN: %clang_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -O %s -o %t-no-overflow // RUN: %run %t-no-overflow 2>&1 | FileCheck --check-prefix=CHECK-NOCRASH %s #include diff --git a/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.c b/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.c new file mode 100644 index 000000000000..ccb6f12228ac --- /dev/null +++ b/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.c @@ -0,0 +1,126 @@ +// Test to demonstrate compile-time disabling of container-overflow checks +// in order to handle uninstrumented libraries +// UNSUPPORTED: target={{.*windows-.*}} + +// Mimic a closed-source library compiled without ASan +// RUN: %clang_asan -fno-sanitize=address -DSHARED_LIB %s %fPIC -shared -o %t-so.so + +// Mimic multiple files being linked into a single executable, +// %t-object.o and %t-main compiled seperately and then linked together +// RUN: %clang_asan -DMULTI_SOURCE %s -c -o %t-object.o +// RUN: %clang_asan %s -c -o %t-main.o +// RUN: %clang_asan -o %t %t-main.o %t-object.o %libdl +// RUN: not %run %t 2>&1 | FileCheck %s + +// Disable container overflow checks at runtime using ASAN_OPTIONS=detect_container_overflow=0 +// RUN: %env_asan_opts=detect_container_overflow=0 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s + +// RUN: %clang_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -DMULTI_SOURCE %s -c -o %t-object.o +// RUN: %clang_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ %s -c -o %t-main.o +// RUN: %clang_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -o %t %t-main.o %t-object.o %libdl +// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s + +#include +#include +#include +#include +#include + +struct Stack { + int data[5]; + size_t size; +}; + +static void init(struct Stack *s) { + s->size = 0; +#if __has_feature(address_sanitizer) && \ + !defined(__SANITIZER_DISABLE_CONTAINER_OVERFLOW__) + // Mark entire storage as unaddressable initially + __sanitizer_annotate_contiguous_container(s->data, s->data + 5, s->data + 5, + s->data); +#endif +} + +static void destroy(struct Stack *s) { +#if __has_feature(address_sanitizer) && \ + !defined(__SANITIZER_DISABLE_CONTAINER_OVERFLOW__) + __sanitizer_annotate_contiguous_container(s->data, s->data + 5, + s->data + s->size, s->data + 5); +#endif +} + +static void push(struct Stack *s, int value) { + assert(s->size < 5 && "Stack overflow"); +#if __has_feature(address_sanitizer) && \ + !defined(__SANITIZER_DISABLE_CONTAINER_OVERFLOW__) + __sanitizer_annotate_contiguous_container( + s->data, s->data + 5, s->data + s->size, s->data + s->size + 1); +#endif + s->data[s->size++] = value; +} + +static int pop(struct Stack *s) { + assert(s->size > 0 && "Cannot pop from empty stack"); + int result = s->data[--s->size]; +#if __has_feature(address_sanitizer) && \ + !defined(__SANITIZER_DISABLE_CONTAINER_OVERFLOW__) + __sanitizer_annotate_contiguous_container( + s->data, s->data + 5, s->data + s->size + 1, s->data + s->size); +#endif + return result; +} + +#ifdef SHARED_LIB +// Mimics a closed-source library compiled without ASan + +void push_value_to_stack(struct Stack *stack) { push(stack, 42); } +#else // SHARED_LIB + +# include + +typedef void (*push_func_t)(struct Stack *); + +# if defined(MULTI_SOURCE) +extern push_func_t push_value; + +void do_push_value_to_stack(struct Stack *stack) { + assert(push_value); + push_value(stack); +} + +# else +push_func_t push_value = NULL; + +void do_push_value_to_stack(struct Stack *stack); + +int main(int argc, char *argv[]) { + char path[4096]; + snprintf(path, sizeof(path), "%s-so.so", argv[0]); + printf("Loading library: %s\n", path); + + void *lib = dlopen(path, RTLD_NOW); + assert(lib); + + push_value = (push_func_t)dlsym(lib, "push_value_to_stack"); + assert(push_value); + + struct Stack stack; + init(&stack); + do_push_value_to_stack(&stack); + + // BOOM! uninstrumented library didn't update container bounds + int value = pop(&stack); + // CHECK: AddressSanitizer: container-overflow + printf("Popped value: %d\n", value); + assert(value == 42 && "Expected value 42"); + + dlclose(lib); + destroy(&stack); + printf("SUCCESS\n"); + // CHECK-NO-CONTAINER-OVERFLOW: SUCCESS + return 0; +} + +# endif // MULTI_SOURCE + +#endif // SHARED_LIB diff --git a/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.cpp b/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.cpp deleted file mode 100644 index cb771f5c9563..000000000000 --- a/compiler-rt/test/asan/TestCases/stack_container_dynamic_lib.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Test to demonstrate compile-time disabling of container-overflow checks -// in order to handle uninstrumented libraries -// UNSUPPORTED: target={{.*windows-.*}} - -// Mimic a closed-source library compiled without ASan -// RUN: %clangxx_asan -fno-sanitize=address -DSHARED_LIB %s %fPIC -shared -o %t-so.so - -// Mimic multiple files being linked into a single executable, -// %t-object.o and %t-main compiled seperately and then linked together -// RUN: %clangxx_asan -DMULTI_SOURCE %s -c -o %t-object.o -// RUN: %clangxx_asan %s -c -o %t-main.o -// RUN: %clangxx_asan -o %t %t-main.o %t-object.o %libdl -// RUN: not %run %t 2>&1 | FileCheck %s - -// Disable container overflow checks at runtime using ASAN_OPTIONS=detect_container_overflow=0 -// RUN: %env_asan_opts=detect_container_overflow=0 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s - -// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -DMULTI_SOURCE %s -c -o %t-object.o -// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ %s -c -o %t-main.o -// RUN: %clangxx_asan -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -o %t %t-main.o %t-object.o %libdl -// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-NO-CONTAINER-OVERFLOW %s - -#include -#include -#include - -template class Stack { -private: - T data[5]; - size_t size; - -public: - Stack() : size(0) { -#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__ - // Mark entire storage as unaddressable initially - __sanitizer_annotate_contiguous_container(data, data + 5, data + 5, data); -#endif - } - - ~Stack() { -#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__ - __sanitizer_annotate_contiguous_container(data, data + 5, data + size, - data + 5); -#endif - } - - void push(const T &value) { - assert(size < 5 && "Stack overflow"); -#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__ - __sanitizer_annotate_contiguous_container(data, data + 5, data + size, - data + size + 1); -#endif - data[size++] = value; - } - - T pop() { - assert(size > 0 && "Cannot pop from empty stack"); - T result = data[--size]; -#if __has_feature(address_sanitizer) && !__ASAN_DISABLE_CONTAINER_OVERFLOW__ - __sanitizer_annotate_contiguous_container(data, data + 5, data + size + 1, - data + size); -#endif - return result; - } -}; - -#ifdef SHARED_LIB -// Mimics a closed-source library compiled without ASan - -extern "C" void push_value_to_stack(Stack &stack) { stack.push(42); } -#else // SHARED_LIB - -# include -# include - -typedef void (*push_func_t)(Stack &); - -# if defined(MULTI_SOURCE) -extern push_func_t push_value; - -extern "C" void do_push_value_to_stack(Stack &stack) { - assert(push_value); - push_value(stack); -} - -# else -push_func_t push_value = nullptr; - -extern "C" void do_push_value_to_stack(Stack &stack); - -int main(int argc, char *argv[]) { - std::string path = std::string(argv[0]) + "-so.so"; - printf("Loading library: %s\n", path.c_str()); - - void *lib = dlopen(path.c_str(), RTLD_NOW); - assert(lib); - - push_value = (push_func_t)dlsym(lib, "push_value_to_stack"); - assert(push_value); - - Stack stack; - do_push_value_to_stack(stack); - - // BOOM! uninstrumented library didn't update container bounds - int value = stack.pop(); - // CHECK: AddressSanitizer: container-overflow - printf("Popped value: %d\n", value); - assert(value == 42 && "Expected value 42"); - - dlclose(lib); - printf("SUCCESS\n"); - // CHECK-NO-CONTAINER-OVERFLOW: SUCCESS - return 0; -} - -# endif // MULTI_SOURCE - -#endif // SHARED_LIB