// This test is broken with shared libstdc++ / libc++ on Android. // RUN: %clangxx_hwasan -static-libstdc++ %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD // RUN: %clangxx_hwasan -static-libstdc++ -DMALLOCEDSTACK %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD // RUN: %clangxx_hwasan -static-libstdc++ -DNO_SANITIZE_F %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD // RUN: %clangxx_hwasan_oldrt -static-libstdc++ %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD // RUN: %clangxx_hwasan_oldrt -static-libstdc++ %s -mllvm -hwasan-instrument-landing-pads=0 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=BAD // C++ tests on x86_64 require instrumented libc++/libstdc++. // RISC-V target doesn't support oldrt // REQUIRES: aarch64-target-arch #include #include #include #include #include #include #include #include static void optimization_barrier(void* arg) { asm volatile("" : : "r"(arg) : "memory"); } __attribute__((noinline)) void h() { char x[1000]; optimization_barrier(x); throw std::runtime_error("hello"); } __attribute__((noinline)) void g() { char x[1000]; optimization_barrier(x); h(); optimization_barrier(x); } __attribute__((noinline)) void hwasan_read(char *p, int size) { char volatile sink; for (int i = 0; i < size; ++i) sink = p[i]; } __attribute__((noinline, no_sanitize("hwaddress"))) void after_catch() { char x[10000]; hwasan_read(&x[0], sizeof(x)); } __attribute__((noinline)) #ifdef NO_SANITIZE_F __attribute__((no_sanitize("hwaddress"))) #endif void * f(void *) { char x[1000]; try { // Put two tagged frames on the stack, throw an exception from the deepest one. g(); } catch (const std::runtime_error &e) { // Put an untagged frame on stack, check that it is indeed untagged. // This relies on exception support zeroing out stack tags. // BAD: tag-mismatch after_catch(); // Check that an in-scope stack allocation is still tagged. // This relies on exception support not zeroing too much. hwasan_read(&x[0], sizeof(x)); // GOOD: hello printf("%s\n", e.what()); } return nullptr; } int main() { __hwasan_enable_allocator_tagging(); #ifdef MALLOCEDSTACK pthread_attr_t attr; void *stack = malloc(PTHREAD_STACK_MIN); assert(pthread_attr_init(&attr) == 0); if (pthread_attr_setstack(&attr, stack, PTHREAD_STACK_MIN) != 0) { fprintf(stderr, "pthread_attr_setstack: %s", strerror(errno)); abort(); } pthread_t thid; if (pthread_create(&thid, &attr, f, nullptr) != 0) { fprintf(stderr, "pthread_create: %s", strerror(errno)); abort(); } void *ret; if (pthread_join(thid, &ret) != 0) { fprintf(stderr, "pthread_join: %s", strerror(errno)); abort(); } assert(pthread_attr_destroy(&attr) == 0); free(stack); #else f(nullptr); #endif }