From: Vedant Kumar Date: Sat, 25 Feb 2017 00:43:39 +0000 (+0000) Subject: [ubsan] Detect signed overflow UB in remainder operations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d9ca335a547ef2193420e49e1ba5c6b3cefd87ca;p=clang [ubsan] Detect signed overflow UB in remainder operations Teach ubsan to diagnose remainder operations which have undefined behavior due to signed overflow (e.g INT_MIN % -1). Differential Revision: https://reviews.llvm.org/D29437 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296214 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index c14e6d12da..529642cb83 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -2403,12 +2403,12 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { // Rem in C can't be a floating point type: C99 6.5.5p2. - if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) { + if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) || + CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) && + Ops.Ty->isIntegerType()) { CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - - if (Ops.Ty->isIntegerType()) - EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false); + EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false); } if (Ops.Ty->hasUnsignedIntegerRepresentation()) diff --git a/test/CodeGen/ubsan-promoted-arith.cpp b/test/CodeGen/ubsan-promoted-arith.cpp index 19cbc0ebda..5a2898b542 100644 --- a/test/CodeGen/ubsan-promoted-arith.cpp +++ b/test/CodeGen/ubsan-promoted-arith.cpp @@ -2,6 +2,7 @@ typedef unsigned char uchar; typedef unsigned short ushort; +typedef int int4 __attribute__((ext_vector_type(4))); enum E1 : int { a @@ -101,12 +102,14 @@ char rem1(char c) { return c % c; } // CHECK-NOT: ubsan_handle_divrem_overflow uchar rem2(uchar uc) { return uc % uc; } -// FIXME: This is a long-standing false negative. -// // CHECK-LABEL: define signext i8 @_Z4rem3 -// rdar30301609: ubsan_handle_divrem_overflow +// CHECK: ubsan_handle_divrem_overflow char rem3(int i, char c) { return i % c; } +// CHECK-LABEL: define signext i8 @_Z4rem4 +// CHECK-NOT: ubsan_handle_divrem_overflow +char rem4(char c, int i) { return c % i; } + // CHECK-LABEL: define signext i8 @_Z4inc1 // CHECK-NOT: sadd.with.overflow char inc1(char c) { return c++ + (char)0; } @@ -122,3 +125,7 @@ void inc3(char c) { c++; } // CHECK-LABEL: define void @_Z4inc4 // CHECK-NOT: uadd.with.overflow void inc4(uchar uc) { uc++; } + +// CHECK-LABEL: define <4 x i32> @_Z4vremDv4_iS_ +// CHECK-NOT: ubsan_handle_divrem_overflow +int4 vrem(int4 a, int4 b) { return a % b; }