xref: /llvm-project/clang/test/CodeGen/ext-int-sanitizer.cpp (revision 5f0903e9bec97e67bf34d887bcbe9d05790de934)
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_KiU7_ExtIntILi15EEi
5 void Bounds(const int (&Array)[10], _ExtInt(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   _ExtInt(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   _ExtInt(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   _ExtInt(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   _ExtInt(10) E = f;
41   // CHECK: fcmp ogt float %{{.+}}, -5.130000e+02
42   // CHECK: fcmp olt float %{{.+}}, 5.120000e+02
43   _ExtInt(10) E2 = d;
44   // CHECK: fcmp ogt double %{{.+}}, -5.130000e+02
45   // CHECK: fcmp olt double %{{.+}}, 5.120000e+02
46   _ExtInt(7) E3 = f;
47   // CHECK: fcmp ogt float %{{.+}}, -6.500000e+01
48   // CHECK: fcmp olt float %{{.+}}, 6.400000e+01
49   _ExtInt(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 @_Z14UIntTruncationU7_ExtIntILi35EEjjy
55 void UIntTruncation(unsigned _ExtInt(35) E, unsigned int i, unsigned long long ll) {
56 
57   i = E;
58   // CHECK: %[[LOADE:.+]] = load i35
59   // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
60   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
61   // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
62   // CHECK: br i1 %[[CHECK]]
63   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
64 
65   E = ll;
66   // CHECK: %[[LOADLL:.+]] = load i64
67   // CHECK: %[[CONV:.+]] = trunc i64 %[[LOADLL]] to i35
68   // CHECK: %[[EXT:.+]] = zext i35 %[[CONV]] to i64
69   // CHECK: %[[CHECK:.+]] = icmp eq i64 %[[EXT]], %[[LOADLL]]
70   // CHECK: br i1 %[[CHECK]]
71   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
72 }
73 
74 // CHECK: define void @_Z13IntTruncationU7_ExtIntILi35EEiU7_ExtIntILi42EEjij
75 void IntTruncation(_ExtInt(35) E, unsigned _ExtInt(42) UE, int i, unsigned j) {
76 
77   j = E;
78   // CHECK: %[[LOADE:.+]] = load i35
79   // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADE]] to i32
80   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i35
81   // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADE]]
82   // CHECK: br i1 %[[CHECK]]
83   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
84 
85   j = UE;
86   // CHECK: %[[LOADUE:.+]] = load i42
87   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i32
88   // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i42
89   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
90   // CHECK: br i1 %[[CHECK]]
91   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
92 
93   // Note: also triggers sign change check.
94   i = UE;
95   // CHECK: %[[LOADUE:.+]] = load i42
96   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i32
97   // CHECK: %[[NEG:.+]] = icmp slt i32 %[[CONV]], 0
98   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
99   // CHECK: %[[EXT:.+]] = sext i32 %[[CONV]] to i42
100   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
101   // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
102   // CHECK: br i1 %[[CHECKBOTH]]
103   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
104 
105   // Note: also triggers sign change check.
106   E = UE;
107   // CHECK: %[[LOADUE:.+]] = load i42
108   // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADUE]] to i35
109   // CHECK: %[[NEG:.+]] = icmp slt i35 %[[CONV]], 0
110   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
111   // CHECK: %[[EXT:.+]] = sext i35 %[[CONV]] to i42
112   // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADUE]]
113   // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]
114   // CHECK: br i1 %[[CHECKBOTH]]
115   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
116 }
117 
118 // CHECK: define void @_Z15SignChangeCheckU7_ExtIntILi39EEjU7_ExtIntILi39EEi
119 void SignChangeCheck(unsigned _ExtInt(39) UE, _ExtInt(39) E) {
120   UE = E;
121   // CHECK: %[[LOADE:.+]] = load i39
122   // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADE]], 0
123   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 %[[NEG]], false
124   // CHECK: br i1 %[[SIGNCHECK]]
125   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
126 
127 
128   E = UE;
129   // CHECK: %[[LOADUE:.+]] = load i39
130   // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADUE]], 0
131   // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]
132   // CHECK: br i1 %[[SIGNCHECK]]
133   // CHECK: call void @__ubsan_handle_implicit_conversion_abort
134 }
135 
136 // CHECK: define void @_Z9DivByZeroU7_ExtIntILi11EEii
137 void DivByZero(_ExtInt(11) E, int i) {
138 
139   // Also triggers signed integer overflow.
140   E / E;
141   // CHECK: %[[E:.+]] = load i11, i11*
142   // CHECK: %[[E2:.+]] = load i11, i11*
143   // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[E2]], 0
144   // CHECK: %[[NEMIN:.+]] = icmp ne i11 %[[E]], -1024
145   // CHECK: %[[NENEG1:.+]] = icmp ne i11 %[[E2]], -1
146   // CHECK: %[[OR:.+]] = or i1 %[[NEMIN]], %[[NENEG1]]
147   // CHECK: %[[AND:.+]] = and i1 %[[NEZERO]], %[[OR]]
148   // CHECK: br i1 %[[AND]]
149   // CHECK: call void @__ubsan_handle_divrem_overflow_abort
150 }
151 
152 // TODO:
153 //-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.
154 // CHECK: define void @_Z6ShiftsU7_ExtIntILi9EEi
155 void Shifts(_ExtInt(9) E) {
156   E >> E;
157   // CHECK: %[[LHSE:.+]] = load i9, i9*
158   // CHECK: %[[RHSE:.+]] = load i9, i9*
159   // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8
160   // CHECK: br i1 %[[CMP]]
161   // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
162 
163   E << E;
164   // CHECK: %[[LHSE:.+]] = load i9, i9*
165   // CHECK: %[[RHSE:.+]] = load i9, i9*
166   // CHECK: %[[CMP:.+]] = icmp ule i9 %[[RHSE]], 8
167   // CHECK: br i1 %[[CMP]]
168   // CHECK: %[[ZEROS:.+]] = sub nuw nsw i9 8, %[[RHSE]]
169   // CHECK: %[[CHECK:.+]] = lshr i9 %[[LHSE]], %[[ZEROS]]
170   // CHECK: %[[SKIPSIGN:.+]] = lshr i9 %[[CHECK]], 1
171   // CHECK: %[[CHECK:.+]] = icmp eq i9 %[[SKIPSIGN]]
172   // CHECK: %[[PHI:.+]] = phi i1 [ true, %{{.+}} ], [ %[[CHECK]], %{{.+}} ]
173   // CHECK: and i1 %[[CMP]], %[[PHI]]
174   // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort
175 }
176 
177 // CHECK: define void @_Z21SignedIntegerOverflowU7_ExtIntILi93EEiU7_ExtIntILi4EEiU7_ExtIntILi31EEi
178 void SignedIntegerOverflow(_ExtInt(93) BiggestE,
179                            _ExtInt(4) SmallestE,
180                            _ExtInt(31) JustRightE) {
181   BiggestE + BiggestE;
182   // CHECK: %[[LOAD1:.+]] = load i93, i93*
183   // CHECK: %[[LOAD2:.+]] = load i93, i93*
184   // CHECK: %[[OFCALL:.+]] = call { i93, i1 } @llvm.sadd.with.overflow.i93(i93 %[[LOAD1]], i93 %[[LOAD2]])
185   // CHECK: %[[EXRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 0
186   // CHECK: %[[OFRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 1
187   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
188   // CHECK: br i1 %[[CHECK]]
189   // CHECK: call void @__ubsan_handle_add_overflow_abort
190 
191   SmallestE - SmallestE;
192   // CHECK: %[[LOAD1:.+]] = load i4, i4*
193   // CHECK: %[[LOAD2:.+]] = load i4, i4*
194   // CHECK: %[[OFCALL:.+]] = call { i4, i1 } @llvm.ssub.with.overflow.i4(i4 %[[LOAD1]], i4 %[[LOAD2]])
195   // CHECK: %[[EXRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 0
196   // CHECK: %[[OFRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 1
197   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
198   // CHECK: br i1 %[[CHECK]]
199   // CHECK: call void @__ubsan_handle_sub_overflow_abort
200 
201   JustRightE * JustRightE;
202   // CHECK: %[[LOAD1:.+]] = load i31, i31*
203   // CHECK: %[[LOAD2:.+]] = load i31, i31*
204   // CHECK: %[[OFCALL:.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %[[LOAD1]], i31 %[[LOAD2]])
205   // CHECK: %[[EXRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 0
206   // CHECK: %[[OFRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 1
207   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
208   // CHECK: br i1 %[[CHECK]]
209   // CHECK: call void @__ubsan_handle_mul_overflow_abort
210 }
211 
212 // CHECK: define void @_Z23UnsignedIntegerOverflowjU7_ExtIntILi23EEjU7_ExtIntILi35EEj
213 void UnsignedIntegerOverflow(unsigned u,
214                              unsigned _ExtInt(23) SmallE,
215                              unsigned _ExtInt(35) BigE) {
216   u = SmallE + SmallE;
217   // CHECK: %[[LOADE1:.+]] = load i23, i23*
218   // CHECK: %[[LOADE2:.+]] = load i23, i23*
219   // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]])
220   // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
221   // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
222   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
223   // CHECK: br i1 %[[CHECK]]
224   // CHECK: call void @__ubsan_handle_add_overflow_abort
225 
226   SmallE = u + u;
227   // CHECK: %[[LOADU1:.+]] = load i32, i32*
228   // CHECK: %[[LOADU2:.+]] = load i32, i32*
229   // CHECK: %[[OFCALL:.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %[[LOADU1]], i32 %[[LOADU2]])
230   // CHECK: %[[EXRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 0
231   // CHECK: %[[OFRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 1
232   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
233   // CHECK: br i1 %[[CHECK]]
234   // CHECK: call void @__ubsan_handle_add_overflow_abort
235 
236   SmallE = SmallE + SmallE;
237   // CHECK: %[[LOADE1:.+]] = load i23, i23*
238   // CHECK: %[[LOADE2:.+]] = load i23, i23*
239   // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADE1]], i23 %[[LOADE2]])
240   // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0
241   // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1
242   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
243   // CHECK: br i1 %[[CHECK]]
244   // CHECK: call void @__ubsan_handle_add_overflow_abort
245 
246   SmallE = BigE + BigE;
247   // CHECK: %[[LOADE1:.+]] = load i35, i35*
248   // CHECK: %[[LOADE2:.+]] = load i35, i35*
249   // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADE1]], i35 %[[LOADE2]])
250   // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
251   // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1
252   // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true
253   // CHECK: br i1 %[[CHECK]]
254   // CHECK: call void @__ubsan_handle_add_overflow_abort
255 
256   BigE = BigE + BigE;
257   // CHECK: %[[LOADE1:.+]] = load i35, i35*
258   // CHECK: %[[LOADE2:.+]] = load i35, i35*
259   // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADE1]], i35 %[[LOADE2]])
260   // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0
261   // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, 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