1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK
2 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fno-sanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
3 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
4 // RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
6 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" }
7 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
9 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_100_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, ptr @[[UNSIGNED_INT]], ptr @[[UNSIGNED_CHAR]], i8 1, i32 0 }
10 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" }
11 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, ptr @[[SIGNED_INT]], ptr @[[UNSIGNED_CHAR]], i8 2, i32 0 }
12 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
13 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, ptr @[[UNSIGNED_INT]], ptr @[[SIGNED_CHAR]], i8 2, i32 0 }
14 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, ptr @[[SIGNED_INT]], ptr @[[SIGNED_CHAR]], i8 2, i32 0 }
16 // CHECK-SANITIZE-ANYRECOVER: @[[UINT32:.*]] = {{.*}} c"'uint32_t' (aka 'unsigned int')\00" }
17 // CHECK-SANITIZE-ANYRECOVER: @[[UINT8:.*]] = {{.*}} c"'uint8_t' (aka 'unsigned char')\00" }
18 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_500_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, ptr @[[UINT32]], ptr @[[UINT8]], i8 1, i32 0 }
20 // ========================================================================== //
21 // The expected true-positives. These are implicit conversions, and they truncate.
22 // ========================================================================== //
24 // CHECK-LABEL: @unsigned_int_to_unsigned_char
25 unsigned char unsigned_int_to_unsigned_char(unsigned int src
) {
26 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
27 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
28 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
29 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
30 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
31 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
32 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
33 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_100_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_100_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
35 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize
36 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
37 // CHECK-SANITIZE: [[CONT]]:
38 // CHECK-NEXT: ret i8 %[[DST]]
44 // CHECK-LABEL: @signed_int_to_unsigned_char
45 unsigned char signed_int_to_unsigned_char(signed int src
) {
46 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
47 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
48 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
49 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
50 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
51 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
52 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
53 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_200_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
54 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_200_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
55 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize
56 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
57 // CHECK-SANITIZE: [[CONT]]:
58 // CHECK-NEXT: ret i8 %[[DST]]
64 // CHECK-LABEL: @unsigned_int_to_signed_char
65 signed char unsigned_int_to_signed_char(unsigned int src
) {
66 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
67 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
68 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
69 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
70 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
71 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
72 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
73 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_300_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
74 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_300_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
75 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize
76 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
77 // CHECK-SANITIZE: [[CONT]]:
78 // CHECK-NEXT: ret i8 %[[DST]]
84 // CHECK-LABEL: @signed_int_to_signed_char
85 signed char signed_int_to_signed_char(signed int src
) {
86 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
87 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize
88 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
89 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
90 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
91 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
92 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
93 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_400_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
94 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_400_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
95 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize
96 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
97 // CHECK-SANITIZE: [[CONT]]:
98 // CHECK-NEXT: ret i8 %[[DST]]
104 // ========================================================================== //
105 // Check canonical type stuff
106 // ========================================================================== //
108 typedef unsigned int uint32_t;
109 typedef unsigned char uint8_t;
111 // CHECK-LABEL: @uint32_to_uint8
112 uint8_t uint32_to_uint8(uint32_t src
) {
113 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8
114 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize
115 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize
116 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize
117 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:
118 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize
119 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize
120 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_500_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
121 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_500_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize
122 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize
123 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
124 // CHECK-SANITIZE: [[CONT]]:
125 // CHECK-NEXT: ret i8 %[[DST]]
131 // ========================================================================== //
132 // Check that explicit conversion does not interfere with implicit conversion
133 // ========================================================================== //
134 // These contain one implicit truncating conversion, and one explicit truncating conversion.
135 // We want to make sure that we still diagnose the implicit conversion.
137 // Implicit truncation after explicit truncation.
138 // CHECK-LABEL: @explicit_conversion_interference0
139 unsigned char explicit_conversion_interference0(unsigned int c
) {
140 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize
141 // CHECK-SANITIZE: call
142 return (unsigned short)c
;
145 // Implicit truncation before explicit truncation.
146 // CHECK-LABEL: @explicit_conversion_interference1
147 unsigned char explicit_conversion_interference1(unsigned int c
) {
148 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize
149 // CHECK-SANITIZE: call
151 return (unsigned char)(b
= c
);
154 // ========================================================================== //
155 // The expected true-negatives.
156 // ========================================================================== //
158 // Sanitization is explicitly disabled.
159 // ========================================================================== //
161 // CHECK-LABEL: @ignorelist_0
162 __attribute__((no_sanitize("undefined"))) unsigned char ignorelist_0(unsigned int src
) {
163 // We are not in "undefined" group, so that doesn't work.
164 // CHECK-SANITIZE: call
168 // CHECK-LABEL: @ignorelist_1
169 __attribute__((no_sanitize("integer"))) unsigned char ignorelist_1(unsigned int src
) {
173 // CHECK-LABEL: @ignorelist_2
174 __attribute__((no_sanitize("implicit-conversion"))) unsigned char ignorelist_2(unsigned int src
) {
178 // CHECK-LABEL: @ignorelist_3
179 __attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char ignorelist_3(unsigned int src
) {
183 // Explicit truncating conversions.
184 // ========================================================================== //
186 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char
187 unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src
) {
188 return (unsigned char)src
;
191 // CHECK-LABEL: @explicit_signed_int_to_unsigned_char
192 unsigned char explicit_signed_int_to_unsigned_char(signed int src
) {
193 return (unsigned char)src
;
196 // CHECK-LABEL: @explicit_unsigned_int_to_signed_char
197 signed char explicit_unsigned_int_to_signed_char(unsigned int src
) {
198 return (signed char)src
;
201 // CHECK-LABEL: @explicit_signed_int_to_signed_char
202 signed char explicit_signed_int_to_signed_char(signed int src
) {
203 return (signed char)src
;
206 // Explicit NOP conversions.
207 // ========================================================================== //
209 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int
210 unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src
) {
211 return (unsigned int)src
;
214 // CHECK-LABEL: @explicit_signed_int_to_signed_int
215 signed int explicit_signed_int_to_signed_int(signed int src
) {
216 return (signed int)src
;
219 // CHECK-LABEL: @explicit_unsigned_char_to_signed_char
220 unsigned char explicit_unsigned_char_to_signed_char(unsigned char src
) {
221 return (unsigned char)src
;
224 // CHECK-LABEL: @explicit_signed_char_to_signed_char
225 signed char explicit_signed_char_to_signed_char(signed char src
) {
226 return (signed char)src
;
230 // ========================================================================== //
232 // CHECK-LABEL: @unsigned_char_to_unsigned_int
233 unsigned int unsigned_char_to_unsigned_int(unsigned char src
) {
237 // CHECK-LABEL: @signed_char_to_unsigned_int
238 unsigned int signed_char_to_unsigned_int(signed char src
) {
242 // CHECK-LABEL: @unsigned_char_to_signed_int
243 signed int unsigned_char_to_signed_int(unsigned char src
) {
247 // CHECK-LABEL: @signed_char_to_signed_int
248 signed int signed_char_to_signed_int(signed char src
) {
253 // ========================================================================== //
255 // CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int
256 unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src
) {
257 return (unsigned int)src
;
260 // CHECK-LABEL: @explicit_signed_char_to_unsigned_int
261 unsigned int explicit_signed_char_to_unsigned_int(signed char src
) {
262 return (unsigned int)src
;
265 // CHECK-LABEL: @explicit_unsigned_char_to_signed_int
266 signed int explicit_unsigned_char_to_signed_int(unsigned char src
) {
267 return (signed int)src
;
270 // CHECK-LABEL: @explicit_signed_char_to_signed_int
271 signed int explicit_signed_char_to_signed_int(signed char src
) {
272 return (signed int)src
;
275 // conversions to to boolean type are not counted as truncation.
276 // ========================================================================== //
278 // CHECK-LABEL: @unsigned_int_to_bool
279 _Bool
unsigned_int_to_bool(unsigned int src
) {
283 // CHECK-LABEL: @signed_int_to_bool
284 _Bool
signed_int_to_bool(signed int src
) {
288 // CHECK-LABEL: @explicit_unsigned_int_to_bool
289 _Bool
explicit_unsigned_int_to_bool(unsigned int src
) {
293 // CHECK-LABEL: @explicit_signed_int_to_bool
294 _Bool
explicit_signed_int_to_bool(signed int src
) {
298 // Explicit truncating conversions from pointer to a much-smaller integer.
299 // Can not have an implicit conversion from pointer to an integer.
300 // Can not have an implicit conversion between two enums.
301 // ========================================================================== //
303 // CHECK-LABEL: @explicit_voidptr_to_unsigned_char
304 unsigned char explicit_voidptr_to_unsigned_char(void *src
) {
305 return (unsigned char)src
;
308 // CHECK-LABEL: @explicit_voidptr_to_signed_char
309 signed char explicit_voidptr_to_signed_char(void *src
) {
310 return (signed char)src
;
313 // Implicit truncating conversions from floating-point may result in precision loss.
314 // ========================================================================== //
316 // CHECK-LABEL: @float_to_unsigned_int
317 unsigned int float_to_unsigned_int(float src
) {
321 // CHECK-LABEL: @float_to_signed_int
322 signed int float_to_signed_int(float src
) {
326 // CHECK-LABEL: @double_to_unsigned_int
327 unsigned int double_to_unsigned_int(double src
) {
331 // CHECK-LABEL: @double_to_signed_int
332 signed int double_to_signed_int(double src
) {
336 // Implicit truncating conversions between fp may result in precision loss.
337 // ========================================================================== //
339 // CHECK-LABEL: @double_to_float
340 float double_to_float(double src
) {