343 lines · c
1// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK2// 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-UNREACHABLE3// 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-RECOVER4// 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-UNREACHABLE5 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_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 }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_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 500, i32 10 }, ptr @[[UINT32]], ptr @[[UINT8]], i8 1, i32 0 }19 20// ========================================================================== //21// The expected true-positives. These are implicit conversions, and they truncate.22// ========================================================================== //23 24// CHECK-LABEL: @unsigned_int_to_unsigned_char25unsigned char unsigned_int_to_unsigned_char(unsigned int src) {26 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i827 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize28 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize29 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize30 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:31 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize32 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize33 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_100_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_100_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize35 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize36 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize37 // CHECK-SANITIZE: [[CONT]]:38 // CHECK-NEXT: ret i8 %[[DST]]39 // CHECK-NEXT: }40#line 10041 return src;42}43 44// CHECK-LABEL: @signed_int_to_unsigned_char45unsigned char signed_int_to_unsigned_char(signed int src) {46 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i847 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize48 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize49 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize50 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:51 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize52 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize53 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_200_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize54 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_200_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize55 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize56 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize57 // CHECK-SANITIZE: [[CONT]]:58 // CHECK-NEXT: ret i8 %[[DST]]59 // CHECK-NEXT: }60#line 20061 return src;62}63 64// CHECK-LABEL: @unsigned_int_to_signed_char65signed char unsigned_int_to_signed_char(unsigned int src) {66 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i867 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize68 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize69 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize70 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:71 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize72 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize73 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_300_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize74 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_300_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize75 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize76 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize77 // CHECK-SANITIZE: [[CONT]]:78 // CHECK-NEXT: ret i8 %[[DST]]79 // CHECK-NEXT: }80#line 30081 return src;82}83 84// CHECK-LABEL: @signed_int_to_signed_char85signed char signed_int_to_signed_char(signed int src) {86 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i887 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = sext i8 %[[DST]] to i32, !nosanitize88 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize89 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize90 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:91 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize92 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize93 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_400_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize94 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_400_SIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize95 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize96 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize97 // CHECK-SANITIZE: [[CONT]]:98 // CHECK-NEXT: ret i8 %[[DST]]99 // CHECK-NEXT: }100#line 400101 return src;102}103 104// ========================================================================== //105// Check canonical type stuff106// ========================================================================== //107 108typedef unsigned int uint32_t;109typedef unsigned char uint8_t;110 111// CHECK-LABEL: @uint32_to_uint8112uint8_t uint32_to_uint8(uint32_t src) {113 // CHECK: %[[DST:.*]] = trunc i32 %[[SRC:.*]] to i8114 // CHECK-SANITIZE-NEXT: %[[ANYEXT:.*]] = zext i8 %[[DST]] to i32, !nosanitize115 // CHECK-SANITIZE-NEXT: %[[TRUNCHECK:.*]] = icmp eq i32 %[[ANYEXT]], %[[SRC]], !nosanitize116 // CHECK-SANITIZE-NEXT: br i1 %[[TRUNCHECK]], label %[[CONT:.*]], label %[[HANDLER_IMPLICIT_CONVERSION:[^,]+]],{{.*}} !nosanitize117 // CHECK-SANITIZE: [[HANDLER_IMPLICIT_CONVERSION]]:118 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTSRC:.*]] = zext i32 %[[SRC]] to i64, !nosanitize119 // CHECK-SANITIZE-ANYRECOVER-NEXT: %[[EXTDST:.*]] = zext i8 %[[DST]] to i64, !nosanitize120 // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_implicit_conversion_abort(ptr @[[LINE_500_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize121 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(ptr @[[LINE_500_UNSIGNED_TRUNCATION]], i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize122 // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 7){{.*}}, !nosanitize123 // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize124 // CHECK-SANITIZE: [[CONT]]:125 // CHECK-NEXT: ret i8 %[[DST]]126 // CHECK-NEXT: }127#line 500128 return src;129}130 131// ========================================================================== //132// Check that explicit conversion does not interfere with implicit conversion133// ========================================================================== //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_interference0139unsigned char explicit_conversion_interference0(unsigned int c) {140 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i8 %[[DST:.*]] to i16, !nosanitize141 // CHECK-SANITIZE: call142 return (unsigned short)c;143}144 145// Implicit truncation before explicit truncation.146// CHECK-LABEL: @explicit_conversion_interference1147unsigned char explicit_conversion_interference1(unsigned int c) {148 // CHECK-SANITIZE: %[[ANYEXT:.*]] = zext i16 %[[DST:.*]] to i32, !nosanitize149 // CHECK-SANITIZE: call150 unsigned short b;151 return (unsigned char)(b = c);152}153 154// ========================================================================== //155// The expected true-negatives.156// ========================================================================== //157 158// Sanitization is explicitly disabled.159// ========================================================================== //160 161// CHECK-LABEL: @ignorelist_0162__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: call165 return src;166}167 168// CHECK-LABEL: @ignorelist_1169__attribute__((no_sanitize("integer"))) unsigned char ignorelist_1(unsigned int src) {170 return src;171}172 173// CHECK-LABEL: @ignorelist_2174__attribute__((no_sanitize("implicit-conversion"))) unsigned char ignorelist_2(unsigned int src) {175 return src;176}177 178// CHECK-LABEL: @ignorelist_3179__attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char ignorelist_3(unsigned int src) {180 return src;181}182 183// Explicit truncating conversions.184// ========================================================================== //185 186// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_char187unsigned char explicit_unsigned_int_to_unsigned_char(unsigned int src) {188 return (unsigned char)src;189}190 191// CHECK-LABEL: @explicit_signed_int_to_unsigned_char192unsigned char explicit_signed_int_to_unsigned_char(signed int src) {193 return (unsigned char)src;194}195 196// CHECK-LABEL: @explicit_unsigned_int_to_signed_char197signed char explicit_unsigned_int_to_signed_char(unsigned int src) {198 return (signed char)src;199}200 201// CHECK-LABEL: @explicit_signed_int_to_signed_char202signed char explicit_signed_int_to_signed_char(signed int src) {203 return (signed char)src;204}205 206// Explicit NOP conversions.207// ========================================================================== //208 209// CHECK-LABEL: @explicit_unsigned_int_to_unsigned_int210unsigned int explicit_unsigned_int_to_unsigned_int(unsigned int src) {211 return (unsigned int)src;212}213 214// CHECK-LABEL: @explicit_signed_int_to_signed_int215signed int explicit_signed_int_to_signed_int(signed int src) {216 return (signed int)src;217}218 219// CHECK-LABEL: @explicit_unsigned_char_to_signed_char220unsigned char explicit_unsigned_char_to_signed_char(unsigned char src) {221 return (unsigned char)src;222}223 224// CHECK-LABEL: @explicit_signed_char_to_signed_char225signed char explicit_signed_char_to_signed_char(signed char src) {226 return (signed char)src;227}228 229// upcasts.230// ========================================================================== //231 232// CHECK-LABEL: @unsigned_char_to_unsigned_int233unsigned int unsigned_char_to_unsigned_int(unsigned char src) {234 return src;235}236 237// CHECK-LABEL: @signed_char_to_unsigned_int238unsigned int signed_char_to_unsigned_int(signed char src) {239 return src;240}241 242// CHECK-LABEL: @unsigned_char_to_signed_int243signed int unsigned_char_to_signed_int(unsigned char src) {244 return src;245}246 247// CHECK-LABEL: @signed_char_to_signed_int248signed int signed_char_to_signed_int(signed char src) {249 return src;250}251 252// Explicit upcasts.253// ========================================================================== //254 255// CHECK-LABEL: @explicit_unsigned_char_to_unsigned_int256unsigned int explicit_unsigned_char_to_unsigned_int(unsigned char src) {257 return (unsigned int)src;258}259 260// CHECK-LABEL: @explicit_signed_char_to_unsigned_int261unsigned int explicit_signed_char_to_unsigned_int(signed char src) {262 return (unsigned int)src;263}264 265// CHECK-LABEL: @explicit_unsigned_char_to_signed_int266signed int explicit_unsigned_char_to_signed_int(unsigned char src) {267 return (signed int)src;268}269 270// CHECK-LABEL: @explicit_signed_char_to_signed_int271signed int explicit_signed_char_to_signed_int(signed char src) {272 return (signed int)src;273}274 275// conversions to to boolean type are not counted as truncation.276// ========================================================================== //277 278// CHECK-LABEL: @unsigned_int_to_bool279_Bool unsigned_int_to_bool(unsigned int src) {280 return src;281}282 283// CHECK-LABEL: @signed_int_to_bool284_Bool signed_int_to_bool(signed int src) {285 return src;286}287 288// CHECK-LABEL: @explicit_unsigned_int_to_bool289_Bool explicit_unsigned_int_to_bool(unsigned int src) {290 return (_Bool)src;291}292 293// CHECK-LABEL: @explicit_signed_int_to_bool294_Bool explicit_signed_int_to_bool(signed int src) {295 return (_Bool)src;296}297 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// ========================================================================== //302 303// CHECK-LABEL: @explicit_voidptr_to_unsigned_char304unsigned char explicit_voidptr_to_unsigned_char(void *src) {305 return (unsigned char)src;306}307 308// CHECK-LABEL: @explicit_voidptr_to_signed_char309signed char explicit_voidptr_to_signed_char(void *src) {310 return (signed char)src;311}312 313// Implicit truncating conversions from floating-point may result in precision loss.314// ========================================================================== //315 316// CHECK-LABEL: @float_to_unsigned_int317unsigned int float_to_unsigned_int(float src) {318 return src;319}320 321// CHECK-LABEL: @float_to_signed_int322signed int float_to_signed_int(float src) {323 return src;324}325 326// CHECK-LABEL: @double_to_unsigned_int327unsigned int double_to_unsigned_int(double src) {328 return src;329}330 331// CHECK-LABEL: @double_to_signed_int332signed int double_to_signed_int(double src) {333 return src;334}335 336// Implicit truncating conversions between fp may result in precision loss.337// ========================================================================== //338 339// CHECK-LABEL: @double_to_float340float double_to_float(double src) {341 return src;342}343