1// RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
2// RUN: %clangxx_asan -O1 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
3// RUN: %clangxx_asan -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
4// RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
5// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t
6// RUN: %clangxx_asan -O0 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
7// RUN: %clangxx_asan -O1 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
8// RUN: %clangxx_asan -O2 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
9// RUN: %clangxx_asan -O3 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
10// RUN: %clangxx_asan -O3 %s -pthread -o %t -fsanitize-address-use-after-return=never && %run %t
11// Regression test for a CHECK failure with small stack size and large frame.
12// RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=131072 && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
13// RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=131072 -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
14//
15// Test that we can find UAR in a thread other than main (UAR mode: runtime):
16// RUN: %clangxx_asan -DUseThread -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
17//
18// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
19// (uses the previous)
20//
21// RUN: %env_asan_opts=detect_stack_use_after_return=1:max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
22// RUN: %env_asan_opts=detect_stack_use_after_return=1:min_uar_stack_size_log=24:max_uar_stack_size_log=24:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
23//
24// Test that we can find UAR in a thread other than main (UAR mode: always):
25// RUN: %clangxx_asan -DUseThread -O2 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
26//
27// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
28// (uses the previous)
29//
30// RUN: %env_asan_opts=max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
31// RUN: %env_asan_opts=min_uar_stack_size_log=24:max_uar_stack_size_log=24:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
32
33// This test runs out of stack on AArch64.
34// UNSUPPORTED: target=aarch64{{.*}}
35// stack size log lower than expected
36// XFAIL: target={{.*(freebsd|netbsd).*}}
37
38// FIXME: Fix this test for dynamic runtime on arm linux.
39// UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime
40
41#include <limits.h>
42#include <pthread.h>
43#include <stdio.h>
44#include <stdlib.h>
45
46#ifndef kSize
47# define kSize 1
48#endif
49
50#ifndef UseThread
51# define UseThread 0
52#endif
53
54#ifndef kStackSize
55# define kStackSize 0
56#endif
57
58__attribute__((noinline))
59char *Ident(char *x) {
60 fprintf(stderr, format: "1: %p\n", x);
61 return x;
62}
63
64__attribute__((noinline))
65char *Func1() {
66 char local[kSize];
67 return Ident(x: local);
68}
69
70__attribute__((noinline))
71void Func2(char *x) {
72 fprintf(stderr, format: "2: %p\n", x);
73 *x = 1;
74 // CHECK: WRITE of size 1 {{.*}} thread T0
75 // CHECK: #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-2]]
76 // CHECK: is located in stack of thread T0 at offset
77 // CHECK: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
78 // THREAD: WRITE of size 1 {{.*}} thread T{{[1-9]}}
79 // THREAD: #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-6]]
80 // THREAD: is located in stack of thread T{{[1-9]}} at offset
81 // THREAD: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
82 // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20
83 // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24
84}
85
86void *Thread(void *unused) {
87 Func2(x: Func1());
88 return NULL;
89}
90
91int main(int argc, char **argv) {
92#if UseThread
93 pthread_attr_t attr;
94 pthread_attr_init(&attr);
95 if (kStackSize > 0) {
96 size_t desired_stack_size = kStackSize;
97#ifdef PTHREAD_STACK_MIN
98 if (desired_stack_size < PTHREAD_STACK_MIN) {
99 desired_stack_size = PTHREAD_STACK_MIN;
100 }
101#endif
102
103 int ret = pthread_attr_setstacksize(&attr, desired_stack_size);
104 if (ret != 0) {
105 fprintf(stderr, "pthread_attr_setstacksize returned %d\n", ret);
106 abort();
107 }
108
109 size_t stacksize_check;
110 ret = pthread_attr_getstacksize(&attr, &stacksize_check);
111 if (ret != 0) {
112 fprintf(stderr, "pthread_attr_getstacksize returned %d\n", ret);
113 abort();
114 }
115
116 if (stacksize_check != desired_stack_size) {
117 fprintf(stderr, "Unable to set stack size to %d, the stack size is %d.\n",
118 (int)desired_stack_size, (int)stacksize_check);
119 abort();
120 }
121 }
122 pthread_t t;
123 pthread_create(&t, &attr, Thread, 0);
124 pthread_attr_destroy(&attr);
125 pthread_join(t, 0);
126#else
127 Func2(x: Func1());
128#endif
129 return 0;
130}
131

source code of compiler-rt/test/asan/TestCases/Posix/stack-use-after-return.cpp