1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK 2 // RUN: %clang_cc1 -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-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-integer-truncation -fsanitize-recover=implicit-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-integer-truncation -fsanitize-trap=implicit-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 5 6 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_INT:.*]] = {{.*}} c"'unsigned int'\00" } 7 // CHECK-SANITIZE-ANYRECOVER: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" } 8 9 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 } 10 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" } 11 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 0 } 12 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" } 13 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 } 14 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 0 } 15 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:.*]] = {{.*}}, i32 500, i32 10 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 0 } 19 20 // ========================================================================== // 21 // The expected true-positives. These are implicit conversions, and they truncate. 22 // ========================================================================== // 23 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(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 35 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 36 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize 37 // CHECK-SANITIZE: [[CONT]]: 38 // CHECK-NEXT: ret i8 %[[DST]] 39 // CHECK-NEXT: } 40 #line 100 41 return src; 42 } 43 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(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 54 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 55 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 56 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize 57 // CHECK-SANITIZE: [[CONT]]: 58 // CHECK-NEXT: ret i8 %[[DST]] 59 // CHECK-NEXT: } 60 #line 200 61 return src; 62 } 63 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(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 74 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 75 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 76 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize 77 // CHECK-SANITIZE: [[CONT]]: 78 // CHECK-NEXT: ret i8 %[[DST]] 79 // CHECK-NEXT: } 80 #line 300 81 return src; 82 } 83 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(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 94 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 95 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 96 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize 97 // CHECK-SANITIZE: [[CONT]]: 98 // CHECK-NEXT: ret i8 %[[DST]] 99 // CHECK-NEXT: } 100 #line 400 101 return src; 102 } 103 104 // ========================================================================== // 105 // Check canonical type stuff 106 // ========================================================================== // 107 108 typedef unsigned int uint32_t; 109 typedef unsigned char uint8_t; 110 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(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 121 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 122 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize 123 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize 124 // CHECK-SANITIZE: [[CONT]]: 125 // CHECK-NEXT: ret i8 %[[DST]] 126 // CHECK-NEXT: } 127 #line 500 128 return src; 129 } 130 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. 136 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 // CHECK: } 143 return (unsigned short)c; 144 } 145 146 // Implicit truncation before explicit truncation. 147 // CHECK-LABEL: @explicit_conversion_interference1 148 unsigned char explicit_conversion_interference1(unsigned int c) { 149 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize 150 // CHECK-SANITIZE: call 151 // CHECK: } 152 unsigned short b; 153 return (unsigned char)(b = c); 154 } 155 156 // ========================================================================== // 157 // The expected true-negatives. 158 // ========================================================================== // 159 160 // Sanitization is explicitly disabled. 161 // ========================================================================== // 162 163 // CHECK-LABEL: @blacklist_0 164 __attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) { 165 // We are not in "undefined" group, so that doesn't work. 166 // CHECK-SANITIZE: call 167 // CHECK: } 168 return src; 169 } 170 171 // CHECK-LABEL: @blacklist_1 172 __attribute__((no_sanitize("integer"))) unsigned char blacklist_1(unsigned int src) { 173 // CHECK: } 174 return src; 175 } 176 177 // CHECK-LABEL: @blacklist_2 178 __attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_2(unsigned int src) { 179 // CHECK: } 180 return src; 181 } 182 183 // CHECK-LABEL: @blacklist_3 184 __attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_3(unsigned int src) { 185 // CHECK: } 186 return src; 187 } 188 189 // Explicit truncating conversions. 190 // ========================================================================== // 191 192 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char 193 unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) { 194 // CHECK: } 195 return (unsigned char)src; 196 } 197 198 // CHECK-LABEL: @explicit_signed_int_to_unsigned_char 199 unsigned char explicit_signed_int_to_unsigned_char(signed int src) { 200 // CHECK: } 201 return (unsigned char)src; 202 } 203 204 // CHECK-LABEL: @explicit_unsigned_int_to_signed_char 205 signed char explicit_unsigned_int_to_signed_char(unsigned int src) { 206 // CHECK: } 207 return (signed char)src; 208 } 209 210 // CHECK-LABEL: @explicit_signed_int_to_signed_char 211 signed char explicit_signed_int_to_signed_char(signed int src) { 212 // CHECK: } 213 return (signed char)src; 214 } 215 216 // Explicit NOP conversions. 217 // ========================================================================== // 218 219 // CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int 220 unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) { 221 // CHECK: } 222 return (unsigned int)src; 223 } 224 225 // CHECK-LABEL: @explicit_signed_int_to_signed_int 226 signed int explicit_signed_int_to_signed_int(signed int src) { 227 // CHECK: } 228 return (signed int)src; 229 } 230 231 // CHECK-LABEL: @explicit_unsigned_char_to_signed_char 232 unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) { 233 // CHECK: } 234 return (unsigned char)src; 235 } 236 237 // CHECK-LABEL: @explicit_signed_char_to_signed_char 238 signed char explicit_signed_char_to_signed_char(signed char src) { 239 // CHECK: } 240 return (signed char)src; 241 } 242 243 // upcasts. 244 // ========================================================================== // 245 246 // CHECK-LABEL: @unsigned_char_to_unsigned_int 247 unsigned int unsigned_char_to_unsigned_int(unsigned char src) { 248 // CHECK: } 249 return src; 250 } 251 252 // CHECK-LABEL: @signed_char_to_unsigned_int 253 unsigned int signed_char_to_unsigned_int(signed char src) { 254 // CHECK: } 255 return src; 256 } 257 258 // CHECK-LABEL: @unsigned_char_to_signed_int 259 signed int unsigned_char_to_signed_int(unsigned char src) { 260 // CHECK: } 261 return src; 262 } 263 264 // CHECK-LABEL: @signed_char_to_signed_int 265 signed int signed_char_to_signed_int(signed char src) { 266 // CHECK: } 267 return src; 268 } 269 270 // Explicit upcasts. 271 // ========================================================================== // 272 273 // CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int 274 unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) { 275 // CHECK: } 276 return (unsigned int)src; 277 } 278 279 // CHECK-LABEL: @explicit_signed_char_to_unsigned_int 280 unsigned int explicit_signed_char_to_unsigned_int(signed char src) { 281 // CHECK: } 282 return (unsigned int)src; 283 } 284 285 // CHECK-LABEL: @explicit_unsigned_char_to_signed_int 286 signed int explicit_unsigned_char_to_signed_int(unsigned char src) { 287 // CHECK: } 288 return (signed int)src; 289 } 290 291 // CHECK-LABEL: @explicit_signed_char_to_signed_int 292 signed int explicit_signed_char_to_signed_int(signed char src) { 293 // CHECK: } 294 return (signed int)src; 295 } 296 297 // conversions to to boolean type are not counted as truncation. 298 // ========================================================================== // 299 300 // CHECK-LABEL: @unsigned_int_to_bool 301 _Bool unsigned_int_to_bool(unsigned int src) { 302 // CHECK: } 303 return src; 304 } 305 306 // CHECK-LABEL: @signed_int_to_bool 307 _Bool signed_int_to_bool(signed int src) { 308 // CHECK: } 309 return src; 310 } 311 312 // CHECK-LABEL: @explicit_unsigned_int_to_bool 313 _Bool explicit_unsigned_int_to_bool(unsigned int src) { 314 // CHECK: } 315 return (_Bool)src; 316 } 317 318 // CHECK-LABEL: @explicit_signed_int_to_bool 319 _Bool explicit_signed_int_to_bool(signed int src) { 320 // CHECK: } 321 return (_Bool)src; 322 } 323 324 // Explicit truncating conversions from pointer to a much-smaller integer. 325 // Can not have an implicit conversion from pointer to an integer. 326 // Can not have an implicit conversion between two enums. 327 // ========================================================================== // 328 329 // CHECK-LABEL: @explicit_voidptr_to_unsigned_char 330 unsigned char explicit_voidptr_to_unsigned_char(void *src) { 331 // CHECK: } 332 return (unsigned char)src; 333 } 334 335 // CHECK-LABEL: @explicit_voidptr_to_signed_char 336 signed char explicit_voidptr_to_signed_char(void *src) { 337 // CHECK: } 338 return (signed char)src; 339 } 340 341 // Implicit truncating conversions from floating-point may result in precision loss. 342 // ========================================================================== // 343 344 // CHECK-LABEL: @float_to_unsigned_int 345 unsigned int float_to_unsigned_int(float src) { 346 // CHECK: } 347 return src; 348 } 349 350 // CHECK-LABEL: @float_to_signed_int 351 signed int float_to_signed_int(float src) { 352 // CHECK: } 353 return src; 354 } 355 356 // CHECK-LABEL: @double_to_unsigned_int 357 unsigned int double_to_unsigned_int(double src) { 358 // CHECK: } 359 return src; 360 } 361 362 // CHECK-LABEL: @double_to_signed_int 363 signed int double_to_signed_int(double src) { 364 // CHECK: } 365 return src; 366 } 367 368 // Implicit truncating conversions between fp may result in precision loss. 369 // ========================================================================== // 370 371 // CHECK-LABEL: @double_to_float 372 float double_to_float(double src) { 373 // CHECK: } 374 return src; 375 } 376