[ubsan] Sanity-check shift amounts before truncation (fixes PR27271)

Ubsan does not report UB shifts in some cases where the shift exponent
needs to be truncated to match the type of the shift base. We perform a
range check on the truncated shift amount, leading to false negatives.

Fix the issue (PR27271) by performing the range check on the original
shift amount.

Differential Revision: https://reviews.llvm.org/D29234

llvm-svn: 293343
This commit is contained in:
Vedant Kumar 2017-01-27 23:02:44 +00:00
parent 5ad775f2e8
commit 3db9974b2d
2 changed files with 31 additions and 2 deletions

View File

@ -2751,8 +2751,8 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
SmallVector<std::pair<Value *, SanitizerMask>, 2> Checks;
llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
llvm::Value *ValidExponent = Builder.CreateICmpULE(RHS, WidthMinusOne);
llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, Ops.RHS);
llvm::Value *ValidExponent = Builder.CreateICmpULE(Ops.RHS, WidthMinusOne);
if (SanitizeExponent) {
Checks.push_back(

View File

@ -0,0 +1,29 @@
// RUN: %clang_cc1 -triple=x86_64-apple-darwin -fsanitize=shift-exponent -emit-llvm %s -o - | FileCheck %s
// CHECK-LABEL: define i32 @f1
int f1(int c, int shamt) {
// CHECK: icmp ule i32 %{{.*}}, 31, !nosanitize
// CHECK: icmp ule i32 %{{.*}}, 31, !nosanitize
return 1 << (c << shamt);
}
// CHECK-LABEL: define i32 @f2
int f2(long c, int shamt) {
// CHECK: icmp ule i32 %{{.*}}, 63, !nosanitize
// CHECK: icmp ule i64 %{{.*}}, 31, !nosanitize
return 1 << (c << shamt);
}
// CHECK-LABEL: define i32 @f3
unsigned f3(unsigned c, int shamt) {
// CHECK: icmp ule i32 %{{.*}}, 31, !nosanitize
// CHECK: icmp ule i32 %{{.*}}, 31, !nosanitize
return 1U << (c << shamt);
}
// CHECK-LABEL: define i32 @f4
unsigned f4(unsigned long c, int shamt) {
// CHECK: icmp ule i32 %{{.*}}, 63, !nosanitize
// CHECK: icmp ule i64 %{{.*}}, 31, !nosanitize
return 1U << (c << shamt);
}