312 lines · cpp
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 %s2 3 4// CHECK: define{{.*}} void @_Z6BoundsRA10_KiDB15_5void Bounds(const int (&Array)[10], _BitInt(15) Index) {6 int I1 = Array[Index];7 // CHECK: %[[SEXT:.+]] = sext i15 %{{.+}} to i648 // CHECK: %[[CMP:.+]] = icmp ult i64 %[[SEXT]], 109 // CHECK: br i1 %[[CMP]]10 // CHECK: call void @__ubsan_handle_out_of_bounds11}12 13// CHECK: define{{.*}} void @_Z4Enumv14void 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 _BitInt(34) a = e1;23 // CHECK: %[[E1:.+]] = icmp ule i32 %{{.*}}, 12724 // CHECK: br i1 %[[E1]]25 // CHECK: call void @__ubsan_handle_load_invalid_value_abort26 _BitInt(34) b = e2;27 // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 12728 // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -12829 // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]30 // CHECK: br i1 %[[E2]]31 // CHECK: call void @__ubsan_handle_load_invalid_value_abort32 _BitInt(34) c = e3;33 // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 214748364734 // CHECK: br i1 %[[E3]]35 // CHECK: call void @__ubsan_handle_load_invalid_value_abort36}37 38// CHECK: define{{.*}} void @_Z13FloatOverflowfd39void FloatOverflow(float f, double d) {40 _BitInt(10) E = f;41 // CHECK: fcmp ogt float %{{.+}}, -5.130000e+0242 // CHECK: fcmp olt float %{{.+}}, 5.120000e+0243 _BitInt(10) E2 = d;44 // CHECK: fcmp ogt double %{{.+}}, -5.130000e+0245 // CHECK: fcmp olt double %{{.+}}, 5.120000e+0246 _BitInt(7) E3 = f;47 // CHECK: fcmp ogt float %{{.+}}, -6.500000e+0148 // CHECK: fcmp olt float %{{.+}}, 6.400000e+0149 _BitInt(7) E4 = d;50 // CHECK: fcmp ogt double %{{.+}}, -6.500000e+0151 // CHECK: fcmp olt double %{{.+}}, 6.400000e+0152}53 54// CHECK: define{{.*}} void @_Z14UIntTruncationDU35_jy55void UIntTruncation(unsigned _BitInt(35) E, unsigned int i, unsigned long long ll) {56 57 i = E;58 // CHECK: %[[LOADE:.+]] = load i6459 // CHECK: %[[E1:.+]] = trunc i64 %[[LOADE]] to i3560 // CHECK: %[[STOREDV:.+]] = zext i35 %[[E1]] to i6461 // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]62 // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]63 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE2]] to i3564 // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADEDV]] to i3265 // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i3566 // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADEDV]]67 // CHECK: br i1 %[[CHECK]]68 // CHECK: call void @__ubsan_handle_implicit_conversion_abort69 70 E = ll;71 // CHECK: %[[LOADLL:.+]] = load i6472 // CHECK: %[[CONV:.+]] = trunc i64 %[[LOADLL]] to i3573 // CHECK: %[[EXT:.+]] = zext i35 %[[CONV]] to i6474 // CHECK: %[[CHECK:.+]] = icmp eq i64 %[[EXT]], %[[LOADLL]]75 // CHECK: br i1 %[[CHECK]]76 // CHECK: call void @__ubsan_handle_implicit_conversion_abort77}78 79// CHECK: define{{.*}} void @_Z13IntTruncationDB35_DU42_ij80void IntTruncation(_BitInt(35) E, unsigned _BitInt(42) UE, int i, unsigned j) {81 82 j = E;83 // CHECK: %[[LOADE:.+]] = load i6484 // CHECK: %[[E1:.+]] = trunc i64 %[[LOADE]] to i3585 // CHECK: %[[STOREDV:.+]] = sext i35 %[[E1]] to i6486 // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]87 // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]88 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE2]] to i3589 // CHECK: %[[CONV:.+]] = trunc i35 %[[LOADEDV]] to i3290 // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i3591 // CHECK: %[[CHECK:.+]] = icmp eq i35 %[[EXT]], %[[LOADEDV]]92 // CHECK: br i1 %[[CHECK]]93 // CHECK: call void @__ubsan_handle_implicit_conversion_abort94 95 j = UE;96 // CHECK: %[[LOADUE:.+]] = load i6497 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i4298 // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i3299 // CHECK: %[[EXT:.+]] = zext i32 %[[CONV]] to i42100 // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]101 // CHECK: br i1 %[[CHECK]]102 // CHECK: call void @__ubsan_handle_implicit_conversion_abort103 104 // Note: also triggers sign change check.105 i = UE;106 // CHECK: %[[LOADUE:.+]] = load i64107 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i42108 // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i32109 // CHECK: %[[NEG:.+]] = icmp slt i32 %[[CONV]], 0110 // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]111 // CHECK: %[[EXT:.+]] = sext i32 %[[CONV]] to i42112 // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]113 // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]114 // CHECK: br i1 %[[CHECKBOTH]]115 // CHECK: call void @__ubsan_handle_implicit_conversion_abort116 117 // Note: also triggers sign change check.118 E = UE;119 // CHECK: %[[LOADUE:.+]] = load i64120 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADUE]] to i42121 // CHECK: %[[CONV:.+]] = trunc i42 %[[LOADEDV]] to i35122 // CHECK: %[[NEG:.+]] = icmp slt i35 %[[CONV]], 0123 // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]124 // CHECK: %[[EXT:.+]] = sext i35 %[[CONV]] to i42125 // CHECK: %[[CHECK:.+]] = icmp eq i42 %[[EXT]], %[[LOADEDV]]126 // CHECK: %[[CHECKBOTH:.+]] = and i1 %[[SIGNCHECK]], %[[CHECK]]127 // CHECK: br i1 %[[CHECKBOTH]]128 // CHECK: call void @__ubsan_handle_implicit_conversion_abort129}130 131// CHECK: define{{.*}} void @_Z15SignChangeCheckDU39_DB39_132void SignChangeCheck(unsigned _BitInt(39) UE, _BitInt(39) E) {133 UE = E;134 // CHECK: %[[LOADEU:.+]] = load i64135 // CHECK: %[[LOADE:.+]] = load i64136 // CHECK: %[[LOADEDV:.+]] = trunc i64 %[[LOADE]] to i39137 // CHECK: %[[STOREDV:.+]] = sext i39 %[[LOADEDV]] to i64138 // CHECK: store i64 %[[STOREDV]], ptr %[[EADDR:.+]]139 // CHECK: %[[LOADE2:.+]] = load i64, ptr %[[EADDR]]140 // CHECK: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i39141 // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADEDV2]], 0142 // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 %[[NEG]], false143 // CHECK: br i1 %[[SIGNCHECK]]144 // CHECK: call void @__ubsan_handle_implicit_conversion_abort145 146 E = UE;147 // CHECK: %[[STOREDV2:.+]] = zext i39 %[[LOADEDV2]] to i64148 // CHECK: store i64 %[[STOREDV2]], ptr %[[UEADDR:.+]]149 // CHECK: %[[LOADUE2:.+]] = load i64, ptr %[[UEADDR]]150 // CHECK: %[[LOADEDV3:.+]] = trunc i64 %[[LOADUE2]] to i39151 // CHECK: %[[NEG:.+]] = icmp slt i39 %[[LOADEDV3]], 0152 // CHECK: %[[SIGNCHECK:.+]] = icmp eq i1 false, %[[NEG]]153 // CHECK: br i1 %[[SIGNCHECK]]154 // CHECK: call void @__ubsan_handle_implicit_conversion_abort155}156 157// CHECK: define{{.*}} void @_Z9DivByZeroDB11_i158void DivByZero(_BitInt(11) E, int i) {159 160 // Also triggers signed integer overflow.161 E / E;162 // CHECK: %[[EADDR:.+]] = alloca i16163 // CHECK: %[[E:.+]] = load i16, ptr %[[EADDR]]164 // CHECK: %[[LOADEDE:.+]] = trunc i16 %[[E]] to i11165 // CHECK: %[[E2:.+]] = load i16, ptr %[[EADDR]]166 // CHECK: %[[LOADEDE2:.+]] = trunc i16 %[[E2]] to i11167 // CHECK: %[[NEZERO:.+]] = icmp ne i11 %[[LOADEDE2]], 0168 // CHECK: %[[NEMIN:.+]] = icmp ne i11 %[[LOADEDE]], -1024169 // CHECK: %[[NENEG1:.+]] = icmp ne i11 %[[LOADEDE2]], -1170 // CHECK: %[[OR:.+]] = or i1 %[[NEMIN]], %[[NENEG1]]171 // CHECK: %[[AND:.+]] = and i1 %[[NEZERO]], %[[OR]]172 // CHECK: br i1 %[[AND]]173 // CHECK: call void @__ubsan_handle_divrem_overflow_abort174}175 176// TODO:177//-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.178// CHECK: define{{.*}} void @_Z6ShiftsDB9_179void Shifts(_BitInt(9) E) {180 E >> E;181 // CHECK: %[[EADDR:.+]] = alloca i16182 // CHECK: %[[LHSE:.+]] = load i16, ptr %[[EADDR]]183 // CHECK: %[[RHSE:.+]] = load i16, ptr %[[EADDR]]184 // CHECK: %[[LOADED:.+]] = trunc i16 %[[RHSE]] to i9185 // CHECK: %[[CMP:.+]] = icmp ule i9 %[[LOADED]], 8186 // CHECK: br i1 %[[CMP]]187 // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort188 189 E << E;190 // CHECK: %[[LHSE:.+]] = load i16, ptr191 // CHECK: %[[LOADEDL:.+]] = trunc i16 %[[LHSE]] to i9192 // CHECK: %[[RHSE:.+]] = load i16, ptr193 // CHECK: %[[LOADED:.+]] = trunc i16 %[[RHSE]] to i9194 // CHECK: %[[CMP:.+]] = icmp ule i9 %[[LOADED]], 8195 // CHECK: br i1 %[[CMP]]196 // CHECK: %[[ZEROS:.+]] = sub nuw nsw i9 8, %[[LOADED]]197 // CHECK: %[[CHECK:.+]] = lshr i9 %[[LOADEDL]], %[[ZEROS]]198 // CHECK: %[[SKIPSIGN:.+]] = lshr i9 %[[CHECK]], 1199 // CHECK: %[[CHECK:.+]] = icmp eq i9 %[[SKIPSIGN]]200 // CHECK: %[[PHI:.+]] = phi i1 [ true, %{{.+}} ], [ %[[CHECK]], %{{.+}} ]201 // CHECK: and i1 %[[CMP]], %[[PHI]]202 // CHECK: call void @__ubsan_handle_shift_out_of_bounds_abort203}204 205// CHECK: define{{.*}} void @_Z21SignedIntegerOverflowDB93_DB4_DB31_206void SignedIntegerOverflow(_BitInt(93) BiggestE,207 _BitInt(4) SmallestE,208 _BitInt(31) JustRightE) {209 BiggestE + BiggestE;210 // CHECK: %[[LOADBIGGESTE2:.+]] = load i128211 // CHECK: %[[LOADEDV:.+]] = trunc i128 %[[LOADBIGGESTE2]] to i93212 // CHECK: %[[STOREDV:.+]] = sext i93 %[[LOADEDV]] to i128213 // CHECK: store i128 %[[STOREDV]], ptr %[[BIGGESTEADDR:.+]]214 // CHECK: %[[LOAD1:.+]] = load i128, ptr %[[BIGGESTEADDR]]215 // CHECK: %[[LOADEDV1:.+]] = trunc i128 %[[LOAD1]] to i93216 // CHECK: %[[LOAD2:.+]] = load i128, ptr %[[BIGGESTEADDR]]217 // CHECK: %[[LOADEDV2:.+]] = trunc i128 %[[LOAD2]] to i93218 // CHECK: %[[OFCALL:.+]] = call { i93, i1 } @llvm.sadd.with.overflow.i93(i93 %[[LOADEDV1]], i93 %[[LOADEDV2]])219 // CHECK: %[[EXRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 0220 // CHECK: %[[OFRESULT:.+]] = extractvalue { i93, i1 } %[[OFCALL]], 1221 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true222 // CHECK: br i1 %[[CHECK]]223 // CHECK: call void @__ubsan_handle_add_overflow_abort224 225 SmallestE - SmallestE;226 // CHECK: %[[LOAD1:.+]] = load i8, ptr227 // CHECK: %[[LOADEDV1:.+]] = trunc i8 %[[LOAD1]] to i4228 // CHECK: %[[LOAD2:.+]] = load i8, ptr229 // CHECK: %[[LOADEDV2:.+]] = trunc i8 %[[LOAD2]] to i4230 // CHECK: %[[OFCALL:.+]] = call { i4, i1 } @llvm.ssub.with.overflow.i4(i4 %[[LOADEDV1]], i4 %[[LOADEDV2]])231 // CHECK: %[[EXRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 0232 // CHECK: %[[OFRESULT:.+]] = extractvalue { i4, i1 } %[[OFCALL]], 1233 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true234 // CHECK: br i1 %[[CHECK]]235 // CHECK: call void @__ubsan_handle_sub_overflow_abort236 237 JustRightE * JustRightE;238 // CHECK: %[[LOAD1:.+]] = load i32, ptr239 // CHECK: %[[LOADEDV1:.+]] = trunc i32 %[[LOAD1]] to i31240 // CHECK: %[[LOAD2:.+]] = load i32, ptr241 // CHECK: %[[LOADEDV2:.+]] = trunc i32 %[[LOAD2]] to i31242 // CHECK: %[[OFCALL:.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %[[LOADEDV1]], i31 %[[LOADEDV2]])243 // CHECK: %[[EXRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 0244 // CHECK: %[[OFRESULT:.+]] = extractvalue { i31, i1 } %[[OFCALL]], 1245 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true246 // CHECK: br i1 %[[CHECK]]247 // CHECK: call void @__ubsan_handle_mul_overflow_abort248}249 250// CHECK: define{{.*}} void @_Z23UnsignedIntegerOverflowjDU23_DU35_251void UnsignedIntegerOverflow(unsigned u,252 unsigned _BitInt(23) SmallE,253 unsigned _BitInt(35) BigE) {254 u = SmallE + SmallE;255 // CHECK: %[[LOADE1:.+]] = load i32, ptr256 // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i32 %[[LOADE1]] to i23257 // CHECK: %[[LOADE2:.+]] = load i32, ptr258 // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i32 %[[LOADE2]] to i23259 // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADEDV1]], i23 %[[LOADEDV2]])260 // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0261 // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1262 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true263 // CHECK: br i1 %[[CHECK]]264 // CHECK: call void @__ubsan_handle_add_overflow_abort265 266 SmallE = u + u;267 // CHECK: %[[LOADU1:.+]] = load i32, ptr268 // CHECK: %[[LOADU2:.+]] = load i32, ptr269 // CHECK: %[[OFCALL:.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %[[LOADU1]], i32 %[[LOADU2]])270 // CHECK: %[[EXRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 0271 // CHECK: %[[OFRESULT:.+]] = extractvalue { i32, i1 } %[[OFCALL]], 1272 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true273 // CHECK: br i1 %[[CHECK]]274 // CHECK: call void @__ubsan_handle_add_overflow_abort275 276 SmallE = SmallE + SmallE;277 // CHECK: %[[LOADE1:.+]] = load i32, ptr278 // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i32 %[[LOADE1]] to i23279 // CHECK: %[[LOADE2:.+]] = load i32, ptr280 // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i32 %[[LOADE2]] to i23281 // CHECK: %[[OFCALL:.+]] = call { i23, i1 } @llvm.uadd.with.overflow.i23(i23 %[[LOADEDV1]], i23 %[[LOADEDV2]])282 // CHECK: %[[EXRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 0283 // CHECK: %[[OFRESULT:.+]] = extractvalue { i23, i1 } %[[OFCALL]], 1284 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true285 // CHECK: br i1 %[[CHECK]]286 // CHECK: call void @__ubsan_handle_add_overflow_abort287 288 SmallE = BigE + BigE;289 // CHECK: %[[LOADE1:.+]] = load i64, ptr290 // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i64 %[[LOADE1]] to i35291 // CHECK: %[[LOADE2:.+]] = load i64, ptr292 // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i35293 // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADEDV1]], i35 %[[LOADEDV2]])294 // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0295 // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1296 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true297 // CHECK: br i1 %[[CHECK]]298 // CHECK: call void @__ubsan_handle_add_overflow_abort299 300 BigE = BigE + BigE;301 // CHECK: %[[LOADE1:.+]] = load i64, ptr302 // CHECK-NEXT: %[[LOADEDV1:.+]] = trunc i64 %[[LOADE1]] to i35303 // CHECK: %[[LOADE2:.+]] = load i64, ptr304 // CHECK-NEXT: %[[LOADEDV2:.+]] = trunc i64 %[[LOADE2]] to i35305 // CHECK: %[[OFCALL:.+]] = call { i35, i1 } @llvm.uadd.with.overflow.i35(i35 %[[LOADEDV1]], i35 %[[LOADEDV2]])306 // CHECK: %[[EXRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 0307 // CHECK: %[[OFRESULT:.+]] = extractvalue { i35, i1 } %[[OFCALL]], 1308 // CHECK: %[[CHECK:.+]] = xor i1 %[[OFRESULT]], true309 // CHECK: br i1 %[[CHECK]]310 // CHECK: call void @__ubsan_handle_add_overflow_abort311}312