• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return -S | FileCheck %s
2; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return -S | FileCheck %s
3
4; Source (-O0 -fsanitize=address -fsanitize-address-use-after-scope):
5;; struct S { int x, y; };
6;; void swap(S *a, S *b, bool doit) {
7;;   if (!doit)
8;;     return;
9;;   auto tmp = *a;
10;;   *a = *b;
11;;   *b = tmp;
12;; }
13
14target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
15target triple = "x86_64-apple-macosx10.14.0"
16
17%struct.S = type { i32, i32 }
18
19; CHECK-LABEL: define {{.*}} @_Z4swapP1SS0_b(
20
21; First come the argument allocas.
22; CHECK:      [[argA:%.*]] = alloca %struct.S*,
23; CHECK-NEXT: [[argB:%.*]] = alloca %struct.S*,
24; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,
25
26; Next, the stores into the argument allocas.
27; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argA]]
28; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argB]]
29; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i8
30; CHECK-NEXT: store i8 [[frombool]], i8* [[argDoit]]
31
32define void @_Z4swapP1SS0_b(%struct.S* %a, %struct.S* %b, i1 zeroext %doit) sanitize_address {
33entry:
34  %a.addr = alloca %struct.S*, align 8
35  %b.addr = alloca %struct.S*, align 8
36  %doit.addr = alloca i8, align 1
37  %tmp = alloca %struct.S, align 4
38  store %struct.S* %a, %struct.S** %a.addr, align 8
39  store %struct.S* %b, %struct.S** %b.addr, align 8
40  %frombool = zext i1 %doit to i8
41  store i8 %frombool, i8* %doit.addr, align 1
42  %0 = load i8, i8* %doit.addr, align 1
43  %tobool = trunc i8 %0 to i1
44  br i1 %tobool, label %if.end, label %if.then
45
46if.then:                                          ; preds = %entry
47  br label %return
48
49if.end:                                           ; preds = %entry
50  %1 = load %struct.S*, %struct.S** %a.addr, align 8
51  %2 = bitcast %struct.S* %tmp to i8*
52  %3 = bitcast %struct.S* %1 to i8*
53  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %2, i8* align 4 %3, i64 8, i1 false)
54  %4 = load %struct.S*, %struct.S** %b.addr, align 8
55  %5 = load %struct.S*, %struct.S** %a.addr, align 8
56  %6 = bitcast %struct.S* %5 to i8*
57  %7 = bitcast %struct.S* %4 to i8*
58  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %6, i8* align 4 %7, i64 8, i1 false)
59  %8 = load %struct.S*, %struct.S** %b.addr, align 8
60  %9 = bitcast %struct.S* %8 to i8*
61  %10 = bitcast %struct.S* %tmp to i8*
62  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %9, i8* align 4 %10, i64 8, i1 false)
63  br label %return
64
65return:                                           ; preds = %if.end, %if.then
66  ret void
67}
68
69; Synthetic test case, meant to check that we do not reorder instructions past
70; a load when attempting to hoist argument init insts.
71; CHECK-LABEL: define {{.*}} @func_with_load_in_arginit_sequence
72; CHECK:      [[argA:%.*]] = alloca %struct.S*,
73; CHECK-NEXT: [[argB:%.*]] = alloca %struct.S*,
74; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,
75; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argA]]
76; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argB]]
77; CHECK-NEXT: [[stack_base:%.*]] = alloca i64
78define void @func_with_load_in_arginit_sequence(%struct.S* %a, %struct.S* %b, i1 zeroext %doit) sanitize_address {
79entry:
80  %a.addr = alloca %struct.S*, align 8
81  %b.addr = alloca %struct.S*, align 8
82  %doit.addr = alloca i8, align 1
83  %tmp = alloca %struct.S, align 4
84  store %struct.S* %a, %struct.S** %a.addr, align 8
85  store %struct.S* %b, %struct.S** %b.addr, align 8
86
87  ; This load prevents the next argument init sequence from being moved.
88  %0 = load i8, i8* %doit.addr, align 1
89
90  %frombool = zext i1 %doit to i8
91  store i8 %frombool, i8* %doit.addr, align 1
92  %tobool = trunc i8 %0 to i1
93  br i1 %tobool, label %if.end, label %if.then
94
95if.then:                                          ; preds = %entry
96  br label %return
97
98if.end:                                           ; preds = %entry
99  %1 = load %struct.S*, %struct.S** %a.addr, align 8
100  %2 = bitcast %struct.S* %tmp to i8*
101  %3 = bitcast %struct.S* %1 to i8*
102  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %2, i8* align 4 %3, i64 8, i1 false)
103  %4 = load %struct.S*, %struct.S** %b.addr, align 8
104  %5 = load %struct.S*, %struct.S** %a.addr, align 8
105  %6 = bitcast %struct.S* %5 to i8*
106  %7 = bitcast %struct.S* %4 to i8*
107  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %6, i8* align 4 %7, i64 8, i1 false)
108  %8 = load %struct.S*, %struct.S** %b.addr, align 8
109  %9 = bitcast %struct.S* %8 to i8*
110  %10 = bitcast %struct.S* %tmp to i8*
111  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %9, i8* align 4 %10, i64 8, i1 false)
112  br label %return
113
114return:                                           ; preds = %if.end, %if.then
115  ret void
116}
117
118; Synthetic test case, meant to check that we can handle functions with more
119; than one interesting alloca.
120; CHECK-LABEL: define {{.*}} @func_with_multiple_interesting_allocas
121; CHECK:      [[argA:%.*]] = alloca %struct.S*,
122; CHECK-NEXT: [[argB:%.*]] = alloca %struct.S*,
123; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,
124; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argA]]
125; CHECK-NEXT: store %struct.S* {{.*}}, %struct.S** [[argB]]
126; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i8
127; CHECK-NEXT: store i8 [[frombool]], i8* [[argDoit]]
128define void @func_with_multiple_interesting_allocas(%struct.S* %a, %struct.S* %b, i1 zeroext %doit) sanitize_address {
129entry:
130  %a.addr = alloca %struct.S*, align 8
131  %b.addr = alloca %struct.S*, align 8
132  %doit.addr = alloca i8, align 1
133  %tmp = alloca %struct.S, align 4
134  %tmp2 = alloca %struct.S, align 4
135  store %struct.S* %a, %struct.S** %a.addr, align 8
136  store %struct.S* %b, %struct.S** %b.addr, align 8
137  %frombool = zext i1 %doit to i8
138  store i8 %frombool, i8* %doit.addr, align 1
139  %0 = load i8, i8* %doit.addr, align 1
140  %tobool = trunc i8 %0 to i1
141  br i1 %tobool, label %if.end, label %if.then
142
143if.then:                                          ; preds = %entry
144  br label %return
145
146if.end:                                           ; preds = %entry
147  %1 = load %struct.S*, %struct.S** %a.addr, align 8
148  %2 = bitcast %struct.S* %tmp to i8*
149  %3 = bitcast %struct.S* %1 to i8*
150  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %2, i8* align 4 %3, i64 8, i1 false)
151  %4 = load %struct.S*, %struct.S** %b.addr, align 8
152  %5 = bitcast %struct.S* %tmp2 to i8*
153  %6 = bitcast %struct.S* %4 to i8*
154  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %5, i8* align 4 %6, i64 8, i1 false)
155  %7 = load %struct.S*, %struct.S** %b.addr, align 8
156  %8 = load %struct.S*, %struct.S** %a.addr, align 8
157  %9 = bitcast %struct.S* %8 to i8*
158  %10 = bitcast %struct.S* %7 to i8*
159  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %9, i8* align 4 %10, i64 8, i1 false)
160  %11 = load %struct.S*, %struct.S** %b.addr, align 8
161  %12 = bitcast %struct.S* %11 to i8*
162  %13 = bitcast %struct.S* %tmp to i8*
163  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %12, i8* align 4 %13, i64 8, i1 false)
164  %14 = load %struct.S*, %struct.S** %a.addr, align 8
165  %15 = bitcast %struct.S* %14 to i8*
166  %16 = bitcast %struct.S* %tmp2 to i8*
167  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %15, i8* align 4 %16, i64 8, i1 false)
168  br label %return
169
170return:                                           ; preds = %if.end, %if.then
171  ret void
172}
173
174declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg)
175