xref: /llvm-project/compiler-rt/test/hwasan/TestCases/deep-recursion.c (revision ddf1de20a3f7db3bca1ef6ba7e6cbb90aac5fd2d)
1090f0f95SEvgeniy Stepanov // RUN: %clang_hwasan -O1 %s -o %t
2090f0f95SEvgeniy Stepanov // RUN: %env_hwasan_opts=stack_history_size=1 not %run %t 2>&1 | FileCheck %s --check-prefix=D1
3090f0f95SEvgeniy Stepanov // RUN: %env_hwasan_opts=stack_history_size=2 not %run %t 2>&1 | FileCheck %s --check-prefix=D2
4090f0f95SEvgeniy Stepanov // RUN: %env_hwasan_opts=stack_history_size=3 not %run %t 2>&1 | FileCheck %s --check-prefix=D3
5090f0f95SEvgeniy Stepanov // RUN: %env_hwasan_opts=stack_history_size=5 not %run %t 2>&1 | FileCheck %s --check-prefix=D5
6090f0f95SEvgeniy Stepanov // RUN:                                       not %run %t 2>&1 | FileCheck %s --check-prefix=DEFAULT
7090f0f95SEvgeniy Stepanov 
821f72c05SLeonard Chan // Run the same tests as above, but using the __hwasan_add_frame_record libcall.
921f72c05SLeonard Chan // The output should be the exact same.
1021f72c05SLeonard Chan // RUN: %clang_hwasan -O1 %s -o %t -mllvm -hwasan-record-stack-history=libcall
1121f72c05SLeonard Chan // RUN: %env_hwasan_opts=stack_history_size=1 not %run %t 2>&1 | FileCheck %s --check-prefix=D1
1221f72c05SLeonard Chan // RUN: %env_hwasan_opts=stack_history_size=2 not %run %t 2>&1 | FileCheck %s --check-prefix=D2
1321f72c05SLeonard Chan // RUN: %env_hwasan_opts=stack_history_size=3 not %run %t 2>&1 | FileCheck %s --check-prefix=D3
1421f72c05SLeonard Chan // RUN: %env_hwasan_opts=stack_history_size=5 not %run %t 2>&1 | FileCheck %s --check-prefix=D5
1521f72c05SLeonard Chan // RUN:                                       not %run %t 2>&1 | FileCheck %s --check-prefix=DEFAULT
1621f72c05SLeonard Chan 
170867edfcSMatt Morehouse // Stack histories are currently not recorded on x86.
1817f804efSPaul Robinson // XFAIL: target=x86_64{{.*}}
19772851caSMatt Morehouse 
20*ddf1de20SThurston Dang #include <assert.h>
21*ddf1de20SThurston Dang #include <sanitizer/hwasan_interface.h>
22090f0f95SEvgeniy Stepanov #include <stdlib.h>
23e4836732SDavid Spickett 
24090f0f95SEvgeniy Stepanov // At least -O1 is needed for this function to not have a stack frame on
25090f0f95SEvgeniy Stepanov // AArch64.
USE(void * x)26090f0f95SEvgeniy Stepanov void USE(void *x) { // pretend_to_do_something(void *x)
27090f0f95SEvgeniy Stepanov   __asm__ __volatile__("" : : "r" (x) : "memory");
28090f0f95SEvgeniy Stepanov }
29090f0f95SEvgeniy Stepanov 
30090f0f95SEvgeniy Stepanov volatile int four = 4;
31090f0f95SEvgeniy Stepanov 
OOB()32aa4dfd37SThurston Dang __attribute__((noinline)) void OOB() {
33aa4dfd37SThurston Dang   int x[4];
34aa4dfd37SThurston Dang   int y[4];
35aa4dfd37SThurston Dang 
36aa4dfd37SThurston Dang   // Tags for stack-allocated variables can occasionally be zero, resulting in
37*ddf1de20SThurston Dang   // a false negative for this test. The tag allocation algorithm is not easy
38*ddf1de20SThurston Dang   // to fix, hence we work around it: if the tag is zero, we use the
39*ddf1de20SThurston Dang   // neighboring variable instead, which must have a different (hence non-zero)
40*ddf1de20SThurston Dang   // tag.
41*ddf1de20SThurston Dang   if (__hwasan_tag_pointer(x, 0) == x) {
42*ddf1de20SThurston Dang     assert(__hwasan_tag_pointer(y, 0) != y);
43aa4dfd37SThurston Dang     y[four] = 0;
44aa4dfd37SThurston Dang   } else {
45aa4dfd37SThurston Dang     x[four] = 0;
46aa4dfd37SThurston Dang   }
47aa4dfd37SThurston Dang   USE(&x[0]);
48aa4dfd37SThurston Dang   USE(&y[0]);
49aa4dfd37SThurston Dang }
FUNC1()50090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC1() { int x; USE(&x); OOB(); }
FUNC2()51090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC2() { int x; USE(&x); FUNC1(); }
FUNC3()52090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC3() { int x; USE(&x); FUNC2(); }
FUNC4()53090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC4() { int x; USE(&x); FUNC3(); }
FUNC5()54090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC5() { int x; USE(&x); FUNC4(); }
FUNC6()55090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC6() { int x; USE(&x); FUNC5(); }
FUNC7()56090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC7() { int x; USE(&x); FUNC6(); }
FUNC8()57090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC8() { int x; USE(&x); FUNC7(); }
FUNC9()58090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC9() { int x; USE(&x); FUNC8(); }
FUNC10()59090f0f95SEvgeniy Stepanov __attribute__((noinline)) void FUNC10() { int x; USE(&x); FUNC9(); }
60090f0f95SEvgeniy Stepanov 
main()61090f0f95SEvgeniy Stepanov int main() { FUNC10(); }
62090f0f95SEvgeniy Stepanov 
63a53bb3acSPeter Collingbourne // D1: Previously allocated frames
64090f0f95SEvgeniy Stepanov // D1: in OOB
65090f0f95SEvgeniy Stepanov // D1-NOT: in FUNC
66090f0f95SEvgeniy Stepanov // D1: Memory tags around the buggy address
67090f0f95SEvgeniy Stepanov 
68a53bb3acSPeter Collingbourne // D2: Previously allocated frames
69090f0f95SEvgeniy Stepanov // D2: in OOB
70090f0f95SEvgeniy Stepanov // D2: in FUNC1
71090f0f95SEvgeniy Stepanov // D2-NOT: in FUNC
72090f0f95SEvgeniy Stepanov // D2: Memory tags around the buggy address
73090f0f95SEvgeniy Stepanov 
74a53bb3acSPeter Collingbourne // D3: Previously allocated frames
75090f0f95SEvgeniy Stepanov // D3: in OOB
76090f0f95SEvgeniy Stepanov // D3: in FUNC1
77090f0f95SEvgeniy Stepanov // D3: in FUNC2
78090f0f95SEvgeniy Stepanov // D3-NOT: in FUNC
79090f0f95SEvgeniy Stepanov // D3: Memory tags around the buggy address
80090f0f95SEvgeniy Stepanov 
81a53bb3acSPeter Collingbourne // D5: Previously allocated frames
82090f0f95SEvgeniy Stepanov // D5: in OOB
83090f0f95SEvgeniy Stepanov // D5: in FUNC1
84090f0f95SEvgeniy Stepanov // D5: in FUNC2
85090f0f95SEvgeniy Stepanov // D5: in FUNC3
86090f0f95SEvgeniy Stepanov // D5: in FUNC4
87090f0f95SEvgeniy Stepanov // D5-NOT: in FUNC
88090f0f95SEvgeniy Stepanov // D5: Memory tags around the buggy address
89090f0f95SEvgeniy Stepanov 
90a53bb3acSPeter Collingbourne // DEFAULT: Previously allocated frames
91090f0f95SEvgeniy Stepanov // DEFAULT: in OOB
92090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC1
93090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC2
94090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC3
95090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC4
96090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC5
97090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC6
98090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC7
99090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC8
100090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC9
101090f0f95SEvgeniy Stepanov // DEFAULT: in FUNC10
102090f0f95SEvgeniy Stepanov // DEFAULT-NOT: in FUNC
103090f0f95SEvgeniy Stepanov // DEFAULT: Memory tags around the buggy address
104