File: stack-use-after-return.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (130 lines) | stat: -rw-r--r-- 5,450 bytes parent folder | download | duplicates (21)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// RUN: %clangxx_asan  -O0 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O1 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O3 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t
// RUN: %clangxx_asan  -O0 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O1 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O2 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O3 %s -pthread -o %t -fsanitize-address-use-after-return=always && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan  -O3 %s -pthread -o %t -fsanitize-address-use-after-return=never && %run %t
// Regression test for a CHECK failure with small stack size and large frame.
// 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
// 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
//
// Test that we can find UAR in a thread other than main (UAR mode: runtime):
// 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
//
// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
// (uses the previous)
//
// 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
// 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
//
// Test that we can find UAR in a thread other than main (UAR mode: always):
// 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
//
// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
// (uses the previous)
//
// RUN: %env_asan_opts=max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
// 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

// This test runs out of stack on AArch64.
// UNSUPPORTED: target=aarch64{{.*}}
// stack size log lower than expected
// XFAIL: target={{.*(freebsd|netbsd).*}}

// FIXME: Fix this test for dynamic runtime on arm linux.
// UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime

#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef kSize
# define kSize 1
#endif

#ifndef UseThread
# define UseThread 0
#endif

#ifndef kStackSize
# define kStackSize 0
#endif

__attribute__((noinline))
char *Ident(char *x) {
  fprintf(stderr, "1: %p\n", x);
  return x;
}

__attribute__((noinline))
char *Func1() {
  char local[kSize];
  return Ident(local);
}

__attribute__((noinline))
void Func2(char *x) {
  fprintf(stderr, "2: %p\n", x);
  *x = 1;
  // CHECK: WRITE of size 1 {{.*}} thread T0
  // CHECK:     #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-2]]
  // CHECK: is located in stack of thread T0 at offset
  // CHECK: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
  // THREAD: WRITE of size 1 {{.*}} thread T{{[1-9]}}
  // THREAD:     #0{{.*}}Func2{{.*}}stack-use-after-return.cpp:[[@LINE-6]]
  // THREAD: is located in stack of thread T{{[1-9]}} at offset
  // THREAD: 'local'{{.*}} <== Memory access at offset {{16|32}} is inside this variable
  // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20
  // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24
}

void *Thread(void *unused)  {
  Func2(Func1());
  return NULL;
}

int main(int argc, char **argv) {
#if UseThread
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  if (kStackSize > 0) {
    size_t desired_stack_size = kStackSize;
#ifdef PTHREAD_STACK_MIN
    if (desired_stack_size < PTHREAD_STACK_MIN) {
      desired_stack_size = PTHREAD_STACK_MIN;
    }
#endif

    int ret = pthread_attr_setstacksize(&attr, desired_stack_size);
    if (ret != 0) {
      fprintf(stderr, "pthread_attr_setstacksize returned %d\n", ret);
      abort();
    }

    size_t stacksize_check;
    ret = pthread_attr_getstacksize(&attr, &stacksize_check);
    if (ret != 0) {
      fprintf(stderr, "pthread_attr_getstacksize returned %d\n", ret);
      abort();
    }

    if (stacksize_check != desired_stack_size) {
      fprintf(stderr, "Unable to set stack size to %d, the stack size is %d.\n",
              (int)desired_stack_size, (int)stacksize_check);
      abort();
    }
  }
  pthread_t t;
  pthread_create(&t, &attr, Thread, 0);
  pthread_attr_destroy(&attr);
  pthread_join(t, 0);
#else
  Func2(Func1());
#endif
  return 0;
}