1 | // Verify that use of longjmp() in a _FORTIFY_SOURCE'd library (without ASAN) |
2 | // is correctly intercepted such that the stack is unpoisoned. |
3 | // Note: it is essential that the external library is not built with ASAN, |
4 | // otherwise it would be able to unpoison the stack before use. |
5 | // |
6 | // RUN: %clang -DIS_LIBRARY -D_FORTIFY_SOURCE=2 -O2 %s -c -o %t.o |
7 | // RUN: %clang_asan -O2 %s %t.o -o %t |
8 | // RUN: %run %t |
9 | |
10 | #ifdef IS_LIBRARY |
11 | /* the library */ |
12 | #include <setjmp.h> |
13 | #include <assert.h> |
14 | #include <sanitizer/asan_interface.h> |
15 | |
16 | static jmp_buf jenv; |
17 | |
18 | void external_callme(void (*callback)(void)) { |
19 | if (setjmp(jenv) == 0) { |
20 | callback(); |
21 | } |
22 | } |
23 | |
24 | void external_longjmp(char *msg) { |
25 | longjmp(jenv, 1); |
26 | } |
27 | |
28 | void external_check_stack(void) { |
29 | char buf[256] = "" ; |
30 | for (int i = 0; i < 256; i++) { |
31 | assert(!__asan_address_is_poisoned(buf + i)); |
32 | } |
33 | } |
34 | #else |
35 | /* main program */ |
36 | extern void external_callme(void (*callback)(void)); |
37 | extern void external_longjmp(char *msg); |
38 | extern void external_check_stack(void); |
39 | |
40 | static void callback(void) { |
41 | char msg[16]; /* Note: this triggers addition of a redzone. */ |
42 | /* Note: msg is passed to prevent compiler optimization from removing it. */ |
43 | external_longjmp(msg); |
44 | } |
45 | |
46 | int main() { |
47 | external_callme(callback); |
48 | external_check_stack(); |
49 | return 0; |
50 | } |
51 | #endif |
52 | |