1 // RUN: %clang_hwasan -O1 %s -o %t
2 // RUN: %env_hwasan_opts=stack_history_size=1 not %run %t 2>&1 | FileCheck %s --check-prefix=D1
3 // RUN: %env_hwasan_opts=stack_history_size=2 not %run %t 2>&1 | FileCheck %s --check-prefix=D2
4 // RUN: %env_hwasan_opts=stack_history_size=3 not %run %t 2>&1 | FileCheck %s --check-prefix=D3
5 // RUN: %env_hwasan_opts=stack_history_size=5 not %run %t 2>&1 | FileCheck %s --check-prefix=D5
6 // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=DEFAULT
7
8 // Run the same tests as above, but using the __hwasan_add_frame_record libcall.
9 // The output should be the exact same.
10 // RUN: %clang_hwasan -O1 %s -o %t -mllvm -hwasan-record-stack-history=libcall
11 // RUN: %env_hwasan_opts=stack_history_size=1 not %run %t 2>&1 | FileCheck %s --check-prefix=D1
12 // RUN: %env_hwasan_opts=stack_history_size=2 not %run %t 2>&1 | FileCheck %s --check-prefix=D2
13 // RUN: %env_hwasan_opts=stack_history_size=3 not %run %t 2>&1 | FileCheck %s --check-prefix=D3
14 // RUN: %env_hwasan_opts=stack_history_size=5 not %run %t 2>&1 | FileCheck %s --check-prefix=D5
15 // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=DEFAULT
16
17 // REQUIRES: stable-runtime
18
19 // Stack histories are currently not recorded on x86.
20 // XFAIL: x86_64
21
22 #include <stdlib.h>
23 // At least -O1 is needed for this function to not have a stack frame on
24 // AArch64.
USE(void * x)25 void USE(void *x) { // pretend_to_do_something(void *x)
26 __asm__ __volatile__("" : : "r" (x) : "memory");
27 }
28
29 volatile int four = 4;
30
OOB()31 __attribute__((noinline)) void OOB() { int x[4]; x[four] = 0; USE(&x[0]); }
FUNC1()32 __attribute__((noinline)) void FUNC1() { int x; USE(&x); OOB(); }
FUNC2()33 __attribute__((noinline)) void FUNC2() { int x; USE(&x); FUNC1(); }
FUNC3()34 __attribute__((noinline)) void FUNC3() { int x; USE(&x); FUNC2(); }
FUNC4()35 __attribute__((noinline)) void FUNC4() { int x; USE(&x); FUNC3(); }
FUNC5()36 __attribute__((noinline)) void FUNC5() { int x; USE(&x); FUNC4(); }
FUNC6()37 __attribute__((noinline)) void FUNC6() { int x; USE(&x); FUNC5(); }
FUNC7()38 __attribute__((noinline)) void FUNC7() { int x; USE(&x); FUNC6(); }
FUNC8()39 __attribute__((noinline)) void FUNC8() { int x; USE(&x); FUNC7(); }
FUNC9()40 __attribute__((noinline)) void FUNC9() { int x; USE(&x); FUNC8(); }
FUNC10()41 __attribute__((noinline)) void FUNC10() { int x; USE(&x); FUNC9(); }
42
main()43 int main() { FUNC10(); }
44
45 // D1: Previously allocated frames
46 // D1: in OOB
47 // D1-NOT: in FUNC
48 // D1: Memory tags around the buggy address
49
50 // D2: Previously allocated frames
51 // D2: in OOB
52 // D2: in FUNC1
53 // D2-NOT: in FUNC
54 // D2: Memory tags around the buggy address
55
56 // D3: Previously allocated frames
57 // D3: in OOB
58 // D3: in FUNC1
59 // D3: in FUNC2
60 // D3-NOT: in FUNC
61 // D3: Memory tags around the buggy address
62
63 // D5: Previously allocated frames
64 // D5: in OOB
65 // D5: in FUNC1
66 // D5: in FUNC2
67 // D5: in FUNC3
68 // D5: in FUNC4
69 // D5-NOT: in FUNC
70 // D5: Memory tags around the buggy address
71
72 // DEFAULT: Previously allocated frames
73 // DEFAULT: in OOB
74 // DEFAULT: in FUNC1
75 // DEFAULT: in FUNC2
76 // DEFAULT: in FUNC3
77 // DEFAULT: in FUNC4
78 // DEFAULT: in FUNC5
79 // DEFAULT: in FUNC6
80 // DEFAULT: in FUNC7
81 // DEFAULT: in FUNC8
82 // DEFAULT: in FUNC9
83 // DEFAULT: in FUNC10
84 // DEFAULT-NOT: in FUNC
85 // DEFAULT: Memory tags around the buggy address
86