xref: /llvm-project/clang/test/CodeGen/ext-int-sanitizer.cpp (revision 9ad72df55cb74b29193270c28f6974d2af8e0b71)
1 // RUN: %clang_cc1 -triple x86_64-gnu-linux -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
2 
3 
4 // CHECK: define{{.*}} void @_Z6BoundsRA10_KiDB15_
5 void Bounds(const int (&Array)[10], _BitInt(15) Index) {
6   int I1 = Array[Index];
7   // CHECK: %[[SEXT:.+]] = sext i15 %{{.+}} to i64
8   // CHECK: %[[CMP:.+]] = icmp ult i64 %[[SEXT]], 10
9   // CHECK: br i1 %[[CMP]]
10   // CHECK: call void @__ubsan_handle_out_of_bounds
11 }
12 
13 // CHECK: define{{.*}} void @_Z4Enumv
14 void Enum() {
15   enum E1 { e1a = 0, e1b = 127 }
16   e1;
17   enum E2 { e2a = -1, e2b = 64 }
18   e2;
19   enum E3 { e3a = (1u << 31) - 1 }
20   e3;
21 
22   _BitInt(34) a = e1;
23   // CHECK: %[[E1:.+]] = icmp ule i32 %{{.*}}, 127
24   // CHECK: br i1 %[[E1]]
25   // CHECK: call void @__ubsan_handle_load_invalid_value_abort
26   _BitInt(34) b = e2;
27   // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127
28   // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128
29   // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]
30   // CHECK: br i1 %[[E2]]
31   // CHECK: call void @__ubsan_handle_load_invalid_value_abort
32   _BitInt(34) c = e3;
33   // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647
34   // CHECK: br i1 %[[E3]]
35   // CHECK: call void @__ubsan_handle_load_invalid_value_abort
36 }
37 
38 // CHECK: define{{.*}} void @_Z13FloatOverflowfd
39 void FloatOverflow(float f, double d) {
40   _BitInt(10) E = f;
41   // CHECK: fcmp ogt float %{{.+}}, -5.130000e+02
42   // CHECK: fcmp olt float %{{.+}}, 5.120000e+02
43   _BitInt(10) E2 = d;
44   // CHECK: fcmp ogt double %{{.+}}, -5.130000e+02
45   // CHECK: fcmp olt double %{{.+}}, 5.120000e+02
46   _BitInt(7) E3 = f;
47   // CHECK: fcmp ogt float %{{.+}}, -6.500000e+01
48   // CHECK: fcmp olt float %{{.+}}, 6.400000e+01
49   _BitInt(7) E4 = d;
50   // CHECK: fcmp ogt double %{{.+}}, -6.500000e+01
51   // CHECK: fcmp olt double %{{.+}}, 6.400000e+01
52 }
53 
54 // CHECK: define{{.*}} void @_Z14UIntTruncationDU35_jy
55 void UIntTruncation(unsigned _BitInt(35) E, unsigned int i, unsigned long long ll) {
56 
57   i = E;
58   // CHECK: %[[LOADE:.+]] = load i64
59   // CHECK: %[[E1:.+]] = trunc i64 %[[LOADE]] to i35
60   // CHECK: %[[STOREDV:.+]] = zext i35 %[[E1]] to i64
61   // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]
62   // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]
63   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE2]] to i35
64   // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADEDV]] to i32
65   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
66   // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADEDV]]
67   // CHECK: br i1 %[[CHECK]]
68   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
69 
70   E = ll;
71   // CHECK: %[[LOADLL:.+]] = load i64
72   // CHECK: %[[CONV:.+]] = trunc i64 %[[LOADLL]] to i35
73   // CHECK: %[[EXT:.+]] = zext i35 %[[CONV]] to i64
74   // CHECK: %[[CHECK:.+]] = icmp eq i64 %[[EXT]], %[[LOADLL]]
75   // CHECK: br i1 %[[CHECK]]
76   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
77 }
78 
79 // CHECK: define{{.*}} void @_Z13IntTruncationDB35_DU42_ij
80 void IntTruncation(_BitInt(35) E, unsigned _BitInt(42) UE, int i, unsigned j) {
81 
82   j = E;
83   // CHECK: %[[LOADE:.+]] = load i64
84   // CHECK: %[[E1:.+]] = trunc i64 %[[LOADE]] to i35
85   // CHECK: %[[STOREDV:.+]] = sext i35 %[[E1]] to i64
86   // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]
87   // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]
88   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE2]] to i35
89   // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADEDV]] to i32
90   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
91   // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADEDV]]
92   // CHECK: br i1 %[[CHECK]]
93   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
94 
95   j = UE;
96   // CHECK: %[[LOADUE:.+]] = load i64
97   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i42
98   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i32
99   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i42
100   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]
101   // CHECK: br i1 %[[CHECK]]
102   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
103 
104   // Note: also triggers sign change check.
105   i = UE;
106   // CHECK: %[[LOADUE:.+]] = load i64
107   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i42
108   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i32
109   // CHECK: %[[NEG:.+]] = icmp slt i32 %[[CONV]], 0
110   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
111   // CHECK: %[[EXT:.+]] = sext i32 %[[CONV]] to i42
112   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]
113   // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
114   // CHECK: br i1 %[[CHECKBOTH]]
115   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
116 
117   // Note: also triggers sign change check.
118   E = UE;
119   // CHECK: %[[LOADUE:.+]] = load i64
120   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i42
121   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i35
122   // CHECK: %[[NEG:.+]] = icmp slt i35 %[[CONV]], 0
123   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
124   // CHECK: %[[EXT:.+]] = sext i35 %[[CONV]] to i42
125   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]
126   // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
127   // CHECK: br i1 %[[CHECKBOTH]]
128   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
129 }
130 
131 // CHECK: define{{.*}} void @_Z15SignChangeCheckDU39_DB39_
132 void SignChangeCheck(unsigned _BitInt(39) UE, _BitInt(39) E) {
133   UE = E;
134   // CHECK: %[[LOADEU:.+]] = load i64
135   // CHECK: %[[LOADE:.+]] = load i64
136   // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE]] to i39
137   // CHECK: %[[STOREDV:.+]] = sext i39 %[[LOADEDV]] to i64
138   // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]
139   // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]
140   // CHECK: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i39
141   // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADEDV2]], 0
142   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 %[[NEG]], false
143   // CHECK: br i1 %[[SIGNCHECK]]
144   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
145 
146   E = UE;
147   // CHECK: %[[STOREDV2:.+]] = zext i39 %[[LOADEDV2]] to i64
148   // CHECK: store i64 %[[STOREDV2]], ptr %[[UEADDR:.+]]
149   // CHECK: %[[LOADUE2:.+]] = load i64, ptr %[[UEADDR]]
150   // CHECK: %[[LOADEDV3:.+]] = trunc i64 %[[LOADUE2]] to i39
151   // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADEDV3]], 0
152   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
153   // CHECK: br i1 %[[SIGNCHECK]]
154   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
155 }
156 
157 // CHECK: define{{.*}} void @_Z9DivByZeroDB11_i
158 void DivByZero(_BitInt(11) E, int i) {
159 
160   // Also triggers signed integer overflow.
161   E / E;
162   // CHECK: %[[EADDR:.+]] = alloca i16
163   // CHECK: %[[E:.+]] = load i16, ptr %[[EADDR]]
164   // CHECK: %[[LOADEDE:.+]] = trunc i16 %[[E]] to i11
165   // CHECK: %[[E2:.+]] = load i16, ptr %[[EADDR]]
166   // CHECK: %[[LOADEDE2:.+]] = trunc i16 %[[E2]] to i11
167   // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[LOADEDE2]], 0
168   // CHECK: %[[NEMIN:.+]] = icmp ne i11 %[[LOADEDE]], -1024
169   // CHECK: %[[NENEG1:.+]] = icmp ne i11 %[[LOADEDE2]], -1
170   // CHECK: %[[OR:.+]] = or i1 %[[NEMIN]], %[[NENEG1]]
171   // CHECK: %[[AND:.+]] = and i1 %[[NEZERO]], %[[OR]]
172   // CHECK: br i1 %[[AND]]
173   // CHECK: call void @__ubsan_handle_divrem_overflow_abort
174 }
175 
176 // TODO:
177 //-fsanitize=shift: (shift-base, shift-exponent) Shift operators where the amount shifted is greater or equal to the promoted bit-width of the left hand side or less than zero, or where the left hand side is negative. For a signed left shift, also checks for signed overflow in C, and for unsigned overflow in C++. You can use -fsanitize=shift-base or -fsanitize=shift-exponent to check only left-hand side or right-hand side of shift operation, respectively.
178 // CHECK: define{{.*}} void @_Z6ShiftsDB9_
179 void Shifts(_BitInt(9) E) {
180   E >> E;
181   // CHECK: %[[EADDR:.+]] = alloca i16
182   // CHECK: %[[LHSE:.+]] = load i16, ptr %[[EADDR]]
183   // CHECK: %[[RHSE:.+]] = load i16, ptr %[[EADDR]]
184   // CHECK: %[[LOADED:.+]] = trunc i16 %[[RHSE]] to i9
185   // CHECK: %[[CMP:.+]] = icmp ule i9 %[[LOADED]], 8
186   // CHECK: br i1 %[[CMP]]
187   // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
188 
189   E << E;
190   // CHECK: %[[LHSE:.+]] = load i16, ptr
191   // CHECK: %[[LOADEDL:.+]] = trunc i16 %[[LHSE]] to i9
192   // CHECK: %[[RHSE:.+]] = load i16, ptr
193   // CHECK: %[[LOADED:.+]] = trunc i16 %[[RHSE]] to i9
194   // CHECK: %[[CMP:.+]] = icmp ule i9 %[[LOADED]], 8
195   // CHECK: br i1 %[[CMP]]
196   // CHECK: %[[ZEROS:.+]] = sub nuw nsw i9 8, %[[LOADED]]
197   // CHECK: %[[CHECK:.+]] = lshr i9 %[[LOADEDL]], %[[ZEROS]]
198   // CHECK: %[[SKIPSIGN:.+]] = lshr i9 %[[CHECK]], 1
199   // CHECK: %[[CHECK:.+]] = icmp eq i9 %[[SKIPSIGN]]
200   // CHECK: %[[PHI:.+]] = phi i1 [ true, %{{.+}} ], [ %[[CHECK]], %{{.+}} ]
201   // CHECK: and i1 %[[CMP]], %[[PHI]]
202   // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
203 }
204 
205 // CHECK: define{{.*}} void @_Z21SignedIntegerOverflowDB93_DB4_DB31_
206 void SignedIntegerOverflow(_BitInt(93) BiggestE,
207                            _BitInt(4) SmallestE,
208                            _BitInt(31) JustRightE) {
209   BiggestE + BiggestE;
210   // CHECK: %[[LOADBIGGESTE2:.+]] = load i128
211   // CHECK: %[[LOADEDV:.+]] = trunc i128 %[[LOADBIGGESTE2]] to i93
212   // CHECK: %[[STOREDV:.+]] = sext i93 %[[LOADEDV]] to i128
213   // CHECK: store i128 %[[STOREDV]], ptr %[[BIGGESTEADDR:.+]]
214   // CHECK: %[[LOAD1:.+]] = load i128, ptr %[[BIGGESTEADDR]]
215   // CHECK: %[[LOADEDV1:.+]] = trunc i128 %[[LOAD1]] to i93
216   // CHECK: %[[LOAD2:.+]] = load i128, ptr %[[BIGGESTEADDR]]
217   // CHECK: %[[LOADEDV2:.+]] = trunc i128 %[[LOAD2]] to i93
218   // CHECK: %[[OFCALL:.+]] = call { i93, i1 } @llvm.sadd.with.overflow.i93(i93 %[[LOADEDV1]], i93 %[[LOADEDV2]])
219   // CHECK: %[[EXRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 0
220   // CHECK: %[[OFRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 1
221   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
222   // CHECK: br i1 %[[CHECK]]
223   // CHECK: call void @__ubsan_handle_add_overflow_abort
224 
225   SmallestE - SmallestE;
226   // CHECK: %[[LOAD1:.+]] = load i8, ptr
227   // CHECK: %[[LOADEDV1:.+]] = trunc i8 %[[LOAD1]] to i4
228   // CHECK: %[[LOAD2:.+]] = load i8, ptr
229   // CHECK: %[[LOADEDV2:.+]] = trunc i8 %[[LOAD2]] to i4
230   // CHECK: %[[OFCALL:.+]] = call { i4, i1 } @llvm.ssub.with.overflow.i4(i4 %[[LOADEDV1]], i4 %[[LOADEDV2]])
231   // CHECK: %[[EXRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 0
232   // CHECK: %[[OFRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 1
233   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
234   // CHECK: br i1 %[[CHECK]]
235   // CHECK: call void @__ubsan_handle_sub_overflow_abort
236 
237   JustRightE * JustRightE;
238   // CHECK: %[[LOAD1:.+]] = load i32, ptr
239   // CHECK: %[[LOADEDV1:.+]] = trunc i32 %[[LOAD1]] to i31
240   // CHECK: %[[LOAD2:.+]] = load i32, ptr
241   // CHECK: %[[LOADEDV2:.+]] = trunc i32 %[[LOAD2]] to i31
242   // CHECK: %[[OFCALL:.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %[[LOADEDV1]], i31 %[[LOADEDV2]])
243   // CHECK: %[[EXRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 0
244   // CHECK: %[[OFRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 1
245   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
246   // CHECK: br i1 %[[CHECK]]
247   // CHECK: call void @__ubsan_handle_mul_overflow_abort
248 }
249 
250 // CHECK: define{{.*}} void @_Z23UnsignedIntegerOverflowjDU23_DU35_
251 void UnsignedIntegerOverflow(unsigned u,
252                              unsigned _BitInt(23) SmallE,
253                              unsigned _BitInt(35) BigE) {
254   u = SmallE + SmallE;
255   // CHECK: %[[LOADE1:.+]] = load i32, ptr
256   // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i32 %[[LOADE1]] to i23
257   // CHECK: %[[LOADE2:.+]] = load i32, ptr
258   // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i32 %[[LOADE2]] to i23
259   // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADEDV1]], i23 %[[LOADEDV2]])
260   // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
261   // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
262   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
263   // CHECK: br i1 %[[CHECK]]
264   // CHECK: call void @__ubsan_handle_add_overflow_abort
265 
266   SmallE = u + u;
267   // CHECK: %[[LOADU1:.+]] = load i32, ptr
268   // CHECK: %[[LOADU2:.+]] = load i32, ptr
269   // CHECK: %[[OFCALL:.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %[[LOADU1]], i32 %[[LOADU2]])
270   // CHECK: %[[EXRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 0
271   // CHECK: %[[OFRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 1
272   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
273   // CHECK: br i1 %[[CHECK]]
274   // CHECK: call void @__ubsan_handle_add_overflow_abort
275 
276   SmallE = SmallE + SmallE;
277   // CHECK: %[[LOADE1:.+]] = load i32, ptr
278   // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i32 %[[LOADE1]] to i23
279   // CHECK: %[[LOADE2:.+]] = load i32, ptr
280   // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i32 %[[LOADE2]] to i23
281   // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADEDV1]], i23 %[[LOADEDV2]])
282   // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
283   // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
284   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
285   // CHECK: br i1 %[[CHECK]]
286   // CHECK: call void @__ubsan_handle_add_overflow_abort
287 
288   SmallE = BigE + BigE;
289   // CHECK: %[[LOADE1:.+]] = load i64, ptr
290   // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i64 %[[LOADE1]] to i35
291   // CHECK: %[[LOADE2:.+]] = load i64, ptr
292   // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i35
293   // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADEDV1]], i35 %[[LOADEDV2]])
294   // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
295   // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1
296   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
297   // CHECK: br i1 %[[CHECK]]
298   // CHECK: call void @__ubsan_handle_add_overflow_abort
299 
300   BigE = BigE + BigE;
301   // CHECK: %[[LOADE1:.+]] = load i64, ptr
302   // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i64 %[[LOADE1]] to i35
303   // CHECK: %[[LOADE2:.+]] = load i64, ptr
304   // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i35
305   // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADEDV1]], i35 %[[LOADEDV2]])
306   // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
307   // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1
308   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
309   // CHECK: br i1 %[[CHECK]]
310   // CHECK: call void @__ubsan_handle_add_overflow_abort
311 }
312