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 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_UNSIGNED_TRUNCATION:.*]] = {{.*}}, i32 100, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 1 } 10 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_INT:.*]] = {{.*}} c"'int'\00" } 11 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_200_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 200, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 } 12 // CHECK-SANITIZE-ANYRECOVER: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" } 13 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_300_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 300, i32 10 }, {{.*}}* @[[UNSIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 } 14 // CHECK-SANITIZE-ANYRECOVER: @[[LINE_400_SIGNED_TRUNCATION:.*]] = {{.*}}, i32 400, i32 10 }, {{.*}}* @[[SIGNED_INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 } 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 }, {{.*}}* @[[UINT32]], {{.*}}* @[[UINT8]], i8 1 } 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_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 34 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100_UNSIGNED_TRUNCATION]] 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_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 54 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200_SIGNED_TRUNCATION]] 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_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 74 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300_SIGNED_TRUNCATION]] 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_SIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 94 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400_SIGNED_TRUNCATION]] 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_UNSIGNED_TRUNCATION]] to i8*), i64 %[[EXTSRC]], i64 %[[EXTDST]]){{.*}}, !nosanitize 121 // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500_UNSIGNED_TRUNCATION]] 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 return (unsigned short)c; 143 } 144 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 150 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: @blacklist_0 162 __attribute__((no_sanitize("undefined"))) unsigned char blacklist_0(unsigned int src) { 163 // We are not in "undefined" group, so that doesn't work. 164 // CHECK-SANITIZE: call 165 return src; 166 } 167 168 // CHECK-LABEL: @blacklist_1 169 __attribute__((no_sanitize("integer"))) unsigned char blacklist_1(unsigned int src) { 170 return src; 171 } 172 173 // CHECK-LABEL: @blacklist_2 174 __attribute__((no_sanitize("implicit-conversion"))) unsigned char blacklist_2(unsigned int src) { 175 return src; 176 } 177 178 // CHECK-LABEL: @blacklist_3 179 __attribute__((no_sanitize("implicit-integer-truncation"))) unsigned char blacklist_3(unsigned int src) { 180 return src; 181 } 182 183 // Explicit truncating conversions. 184 // ========================================================================== // 185 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; 189 } 190 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; 194 } 195 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; 199 } 200 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; 204 } 205 206 // Explicit NOP conversions. 207 // ========================================================================== // 208 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; 212 } 213 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; 217 } 218 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; 222 } 223 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; 227 } 228 229 // upcasts. 230 // ========================================================================== // 231 232 // CHECK-LABEL: @unsigned_char_to_unsigned_int 233 unsigned int unsigned_char_to_unsigned_int(unsigned char src) { 234 return src; 235 } 236 237 // CHECK-LABEL: @signed_char_to_unsigned_int 238 unsigned int signed_char_to_unsigned_int(signed char src) { 239 return src; 240 } 241 242 // CHECK-LABEL: @unsigned_char_to_signed_int 243 signed int unsigned_char_to_signed_int(unsigned char src) { 244 return src; 245 } 246 247 // CHECK-LABEL: @signed_char_to_signed_int 248 signed 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_int 256 unsigned 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_int 261 unsigned 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_int 266 signed 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_int 271 signed 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_bool 279 _Bool unsigned_int_to_bool(unsigned int src) { 280 return src; 281 } 282 283 // CHECK-LABEL: @signed_int_to_bool 284 _Bool signed_int_to_bool(signed int src) { 285 return src; 286 } 287 288 // CHECK-LABEL: @explicit_unsigned_int_to_bool 289 _Bool explicit_unsigned_int_to_bool(unsigned int src) { 290 return (_Bool)src; 291 } 292 293 // CHECK-LABEL: @explicit_signed_int_to_bool 294 _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_char 304 unsigned char explicit_voidptr_to_unsigned_char(void *src) { 305 return (unsigned char)src; 306 } 307 308 // CHECK-LABEL: @explicit_voidptr_to_signed_char 309 signed 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_int 317 unsigned int float_to_unsigned_int(float src) { 318 return src; 319 } 320 321 // CHECK-LABEL: @float_to_signed_int 322 signed int float_to_signed_int(float src) { 323 return src; 324 } 325 326 // CHECK-LABEL: @double_to_unsigned_int 327 unsigned int double_to_unsigned_int(double src) { 328 return src; 329 } 330 331 // CHECK-LABEL: @double_to_signed_int 332 signed 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_float 340 float double_to_float(double src) { 341 return src; 342 } 343