1 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
2 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY,CHECK
3 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
4 ; RUN: opt -passes=hwasan -hwasan-instrument-stack=0 -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSTACK,CHECK
6 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
7 target triple = "aarch64-unknown-linux-gnu"
9 ; Check a safe alloca to ensure it does not get a tag.
10 define i32 @test_simple(i32* %a) sanitize_hwaddress {
12 ; CHECK-LABEL: @test_simple
13 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
14 ; NOSAFETY: call {{.*}}__hwasan_store
15 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
16 ; SAFETY-NOT: call {{.*}}__hwasan_store
17 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
18 ; NOSTACK-NOT: call {{.*}}__hwasan_store
19 %buf.sroa.0 = alloca i8, align 4
20 call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
21 store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8
22 call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
26 ; Check a non-safe alloca to ensure it gets a tag.
27 define i32 @test_use(i32* %a) sanitize_hwaddress {
29 ; CHECK-LABEL: @test_use
30 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
31 ; NOSAFETY: call {{.*}}__hwasan_store
32 ; SAFETY: call {{.*}}__hwasan_generate_tag
33 ; SAFETY-NOT: call {{.*}}__hwasan_store
34 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
35 ; NOSTACK-NOT: call {{.*}}__hwasan_store
36 %buf.sroa.0 = alloca i8, align 4
37 call void @use(i8* nonnull %buf.sroa.0)
38 call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
39 store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8
40 call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
44 ; Check an alloca with in range GEP to ensure it does not get a tag or check.
45 define i32 @test_in_range(i32* %a) sanitize_hwaddress {
47 ; CHECK-LABEL: @test_in_range
48 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
49 ; NOSAFETY: call {{.*}}__hwasan_store
50 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
51 ; SAFETY-NOT: call {{.*}}__hwasan_store
52 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
53 ; NOSTACK-NOT: call {{.*}}__hwasan_store
54 %buf.sroa.0 = alloca [10 x i8], align 4
55 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 0
56 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
57 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
58 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
62 ; Check an alloca with in range GEP to ensure it does not get a tag or check.
63 define i32 @test_in_range2(i32* %a) sanitize_hwaddress {
65 ; CHECK-LABEL: @test_in_range2
66 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
67 ; NOSAFETY: call {{.*}}__hwasan_store
68 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
69 ; SAFETY-NOT: call {{.*}}__hwasan_store
70 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
71 ; NOSTACK-NOT: call {{.*}}__hwasan_store
72 %buf.sroa.0 = alloca [10 x i8], align 4
73 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
74 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
75 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
76 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
77 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
81 define i32 @test_in_range3(i32* %a) sanitize_hwaddress {
83 ; CHECK-LABEL: @test_in_range3
84 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
85 ; NOSAFETY: call {{.*}}__hwasan_memset
86 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
87 ; SAFETY-NOT: call {{.*}}__hwasan_memset
88 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
89 ; NOSTACK-NOT: call {{.*}}__hwasan_memset
90 %buf.sroa.0 = alloca [10 x i8], align 4
91 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
92 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
93 call void @llvm.memset.p0i8.i32(i8* %ptr, i8 0, i32 1, i1 true)
97 define i32 @test_in_range4(i32* %a) sanitize_hwaddress {
99 ; CHECK-LABEL: @test_in_range4
100 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
101 ; NOSAFETY: call {{.*}}__hwasan_memmove
102 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
103 ; SAFETY-NOT: call {{.*}}__hwasan_memmove
104 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
105 ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
106 %buf.sroa.0 = alloca [10 x i8], align 4
107 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
108 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
109 call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr, i32 1, i1 true)
113 define i32 @test_in_range5(i32* %a) sanitize_hwaddress {
115 ; CHECK-LABEL: @test_in_range5
116 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
117 ; NOSAFETY: call {{.*}}__hwasan_memmove
118 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
119 ; SAFETY-NOT: call {{.*}}__hwasan_memmove
120 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
121 ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
122 %buf.sroa.0 = alloca [10 x i8], align 4
123 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
124 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
125 %buf.sroa.1 = alloca [10 x i8], align 4
126 %ptr1 = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
127 %y = bitcast [10 x i8]* %buf.sroa.1 to i8*
128 call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr1, i32 1, i1 true)
132 ; Check an alloca with out of range GEP to ensure it gets a tag and check.
133 define i32 @test_out_of_range(i32* %a) sanitize_hwaddress {
135 ; CHECK-LABEL: @test_out_of_range
136 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
137 ; NOSAFETY: call {{.*}}__hwasan_store
138 ; SAFETY: call {{.*}}__hwasan_generate_tag
139 ; SAFETY: call {{.*}}__hwasan_store
140 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
141 ; NOSTACK-NOT: call {{.*}}__hwasan_store
142 %buf.sroa.0 = alloca [10 x i8], align 4
143 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 10
144 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
145 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
146 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
147 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
151 define i32 @test_out_of_range3(i32* %a) sanitize_hwaddress {
153 ; CHECK-LABEL: @test_out_of_range3
154 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
155 ; NOSAFETY: call {{.*}}__hwasan_memset
156 ; SAFETY: call {{.*}}__hwasan_generate_tag
157 ; SAFETY: call {{.*}}__hwasan_memset
158 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
159 ; NOSTACK-NOT: call {{.*}}__hwasan_memset
160 %buf.sroa.0 = alloca [10 x i8], align 4
161 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
162 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
163 call void @llvm.memset.p0i8.i32(i8* %ptr, i8 0, i32 2, i1 true)
167 define i32 @test_out_of_range4(i32* %a) sanitize_hwaddress {
169 ; CHECK-LABEL: @test_out_of_range4
170 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
171 ; NOSAFETY: call {{.*}}__hwasan_memmove
172 ; SAFETY: call {{.*}}__hwasan_generate_tag
173 ; SAFETY: call {{.*}}__hwasan_memmove
174 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
175 ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
176 %buf.sroa.0 = alloca [10 x i8], align 4
177 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
178 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
179 call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr, i32 2, i1 true)
183 define i32 @test_out_of_range5(i32* %a) sanitize_hwaddress {
185 ; CHECK-LABEL: @test_out_of_range5
186 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
187 ; NOSAFETY: call {{.*}}__hwasan_memmove
188 ; SAFETY: call {{.*}}__hwasan_generate_tag
189 ; SAFETY: call {{.*}}__hwasan_memmove
190 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
191 ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
192 %buf.sroa.0 = alloca [10 x i8], align 4
193 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
194 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
195 %buf.sroa.1 = alloca [10 x i8], align 4
196 %ptr1 = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
197 %y = bitcast [10 x i8]* %buf.sroa.1 to i8*
198 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
199 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
200 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %y)
201 call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr1, i32 1, i1 true)
202 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %y)
206 ; Check an alloca with potentially out of range GEP to ensure it gets a tag and
208 define i32 @test_potentially_out_of_range(i32* %a) sanitize_hwaddress {
210 ; CHECK-LABEL: @test_potentially_out_of_range
211 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
212 ; NOSAFETY: call {{.*}}__hwasan_store
213 ; SAFETY: call {{.*}}__hwasan_generate_tag
214 ; SAFETY: call {{.*}}__hwasan_store
215 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
216 ; NOSTACK-NOT: call {{.*}}__hwasan_store
217 %buf.sroa.0 = alloca [10 x i8], align 4
218 %off = call i32 @getoffset()
219 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 %off
220 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
221 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
222 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
226 define i32 @test_potentially_out_of_range2(i8* %a) sanitize_hwaddress {
228 ; CHECK-LABEL: @test_potentially_out_of_range2
229 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
230 ; NOSAFETY: call {{.*}}__hwasan_memmove
231 ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
232 ; SAFETY: call {{.*}}__hwasan_memmove
233 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
234 ; NOSTACK: call {{.*}}__hwasan_memmove
235 %buf.sroa.0 = alloca [10 x i8], align 4
236 %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
237 %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
238 call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %a, i32 1, i1 true)
241 ; Check an alloca with potentially out of range GEP to ensure it gets a tag and
243 define i32 @test_unclear(i32* %a) sanitize_hwaddress {
245 ; CHECK-LABEL: @test_unclear
246 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
247 ; NOSAFETY: call {{.*}}__hwasan_store
248 ; SAFETY: call {{.*}}__hwasan_generate_tag
249 ; SAFETY: call {{.*}}__hwasan_store
250 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
251 ; NOSTACK: call {{.*}}__hwasan_store
252 %buf.sroa.0 = alloca i8, align 4
253 %ptr = call i8* @getptr(i8* %buf.sroa.0)
254 call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
255 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
256 call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
260 define i32 @test_select(i8* %a) sanitize_hwaddress {
262 ; CHECK-LABEL: @test_select
263 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
264 ; NOSAFETY: call {{.*}}__hwasan_store
265 ; SAFETY: call {{.*}}__hwasan_generate_tag
266 ; SAFETY: call {{.*}}__hwasan_store
267 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
268 ; NOSTACK: call {{.*}}__hwasan_store
269 %x = call i8* @getptr(i8* %a)
270 %buf.sroa.0 = alloca i8, align 4
271 call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
273 %ptr = select i1 %c, i8* %x, i8* %buf.sroa.0
274 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
275 call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
279 ; Check whether we see through the returns attribute of functions.
280 define i32 @test_retptr(i32* %a) sanitize_hwaddress {
282 ; CHECK-LABEL: @test_retptr
283 ; NOSAFETY: call {{.*}}__hwasan_generate_tag
284 ; NOSAFETY: call {{.*}}__hwasan_store
285 ; SAFETY: call {{.*}}__hwasan_generate_tag
286 ; SAFETY-NOT: call {{.*}}__hwasan_store
287 ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
288 ; NOSTACK-NOT: call {{.*}}__hwasan_store
289 %buf.sroa.0 = alloca i8, align 4
290 call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
291 %ptr = call i8* @retptr(i8* %buf.sroa.0)
292 store volatile i8 0, i8* %ptr, align 4, !tbaa !8
293 call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
297 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
298 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
300 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
301 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
303 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1)
304 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
305 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i1)
308 declare void @use(i8* nocapture)
309 declare i32 @getoffset()
310 declare i8* @getptr(i8* nocapture)
311 declare i8* @retptr(i8* returned)
313 !8 = !{!9, !9, i64 0}
314 !9 = !{!"omnipotent char", !10, i64 0}
315 !10 = !{!"Simple C/C++ TBAA"}