xref: /llvm-project/compiler-rt/test/hwasan/TestCases/try-catch.cpp (revision 5ac240bbea14d4edd0c484f5f879cd0f26be59e3)
1 // This test is broken with shared libstdc++ / libc++ on Android.
2 // RUN: %clangxx_hwasan -static-libstdc++ %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
3 // RUN: %clangxx_hwasan -static-libstdc++ -DMALLOCEDSTACK %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
4 // RUN: %clangxx_hwasan -static-libstdc++ -DNO_SANITIZE_F %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
5 // RUN: %clangxx_hwasan_oldrt -static-libstdc++ %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
6 // 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
7 
8 // C++ tests on x86_64 require instrumented libc++/libstdc++.
9 // RISC-V target doesn't support oldrt
10 // REQUIRES: aarch64-target-arch
11 
12 #include <cassert>
13 #include <cstdio>
14 #include <errno.h>
15 #include <limits.h>
16 #include <pthread.h>
17 #include <sanitizer/hwasan_interface.h>
18 #include <stdexcept>
19 #include <string.h>
20 
optimization_barrier(void * arg)21 static void optimization_barrier(void* arg) {
22   asm volatile("" : : "r"(arg) : "memory");
23 }
24 
25 __attribute__((noinline))
h()26 void h() {
27   char x[1000];
28   optimization_barrier(x);
29   throw std::runtime_error("hello");
30 }
31 
32 __attribute__((noinline))
g()33 void g() {
34   char x[1000];
35   optimization_barrier(x);
36   h();
37   optimization_barrier(x);
38 }
39 
40 __attribute__((noinline))
hwasan_read(char * p,int size)41 void hwasan_read(char *p, int size) {
42   char volatile sink;
43   for (int i = 0; i < size; ++i)
44     sink = p[i];
45 }
46 
after_catch()47 __attribute__((noinline, no_sanitize("hwaddress"))) void after_catch() {
48   char x[10000];
49   hwasan_read(&x[0], sizeof(x));
50 }
51 
52 __attribute__((noinline))
53 #ifdef NO_SANITIZE_F
54 __attribute__((no_sanitize("hwaddress")))
55 #endif
56 void *
f(void *)57 f(void *) {
58   char x[1000];
59   try {
60     // Put two tagged frames on the stack, throw an exception from the deepest one.
61     g();
62   } catch (const std::runtime_error &e) {
63     // Put an untagged frame on stack, check that it is indeed untagged.
64     // This relies on exception support zeroing out stack tags.
65     // BAD: tag-mismatch
66     after_catch();
67     // Check that an in-scope stack allocation is still tagged.
68     // This relies on exception support not zeroing too much.
69     hwasan_read(&x[0], sizeof(x));
70     // GOOD: hello
71     printf("%s\n", e.what());
72   }
73   return nullptr;
74 }
75 
main()76 int main() {
77   __hwasan_enable_allocator_tagging();
78 #ifdef MALLOCEDSTACK
79   pthread_attr_t attr;
80   void *stack = malloc(PTHREAD_STACK_MIN);
81   assert(pthread_attr_init(&attr) == 0);
82   if (pthread_attr_setstack(&attr, stack, PTHREAD_STACK_MIN) != 0) {
83     fprintf(stderr, "pthread_attr_setstack: %s", strerror(errno));
84     abort();
85   }
86   pthread_t thid;
87   if (pthread_create(&thid, &attr, f, nullptr) != 0) {
88     fprintf(stderr, "pthread_create: %s", strerror(errno));
89     abort();
90   }
91   void *ret;
92   if (pthread_join(thid, &ret) != 0) {
93     fprintf(stderr, "pthread_join: %s", strerror(errno));
94     abort();
95   }
96   assert(pthread_attr_destroy(&attr) == 0);
97   free(stack);
98 #else
99   f(nullptr);
100 #endif
101 }
102