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 Stepanovvoid 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 Stepanovint 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