I checked in r304486 to try and address the issue. thanks, vedant
> On Jun 1, 2017, at 3:21 PM, Vedant Kumar via cfe-commits > <cfe-commits@lists.llvm.org> wrote: > > Taking a look. > > vedant > >> On Jun 1, 2017, at 2:45 PM, Galina Kistanova <gkistan...@gmail.com >> <mailto:gkistan...@gmail.com>> wrote: >> >> Hello Vedant, >> >> This commit broke tests on some of our builders: >> >> Failing Tests (1): >> Clang :: CodeGen/ubsan-pointer-overflow.m >> >> http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/2865/steps/test-check-all/logs/stdio >> >> <http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/2865/steps/test-check-all/logs/stdio> >> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/10259 >> >> <http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/10259> >> http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/3097 >> <http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/3097> >> etc >> >> Thanks >> >> Galina >> >> On Thu, Jun 1, 2017 at 12:22 PM, Vedant Kumar via cfe-commits >> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote: >> Author: vedantk >> Date: Thu Jun 1 14:22:18 2017 >> New Revision: 304459 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=304459&view=rev >> <http://llvm.org/viewvc/llvm-project?rev=304459&view=rev> >> Log: >> [ubsan] Add a check for pointer overflow UB >> >> Check pointer arithmetic for overflow. >> >> For some more background on this check, see: >> >> https://wdtz.org/catching-pointer-overflow-bugs.html >> <https://wdtz.org/catching-pointer-overflow-bugs.html> >> https://reviews.llvm.org/D20322 <https://reviews.llvm.org/D20322> >> >> Patch by Will Dietz and John Regehr! >> >> This version of the patch is different from the original in a few ways: >> >> - It introduces the EmitCheckedInBoundsGEP utility which inserts >> checks when the pointer overflow check is enabled. >> >> - It does some constant-folding to reduce instrumentation overhead. >> >> - It does not check some GEPs in CGExprCXX. I'm not sure that >> inserting checks here, or in CGClass, would catch many bugs. >> >> Possible future directions for this check: >> >> - Introduce CGF.EmitCheckedStructGEP, to detect overflows when >> accessing structures. >> >> Testing: Apart from the added lit test, I ran check-llvm and check-clang >> with a stage2, ubsan-instrumented clang. Will and John have also done >> extensive testing on numerous open source projects. >> >> Differential Revision: https://reviews.llvm.org/D33305 >> <https://reviews.llvm.org/D33305> >> >> Added: >> cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m >> Modified: >> cfe/trunk/docs/UndefinedBehaviorSanitizer.rst >> cfe/trunk/include/clang/Basic/Sanitizers.def >> cfe/trunk/lib/CodeGen/CGExpr.cpp >> cfe/trunk/lib/CodeGen/CGExprScalar.cpp >> cfe/trunk/lib/CodeGen/CodeGenFunction.h >> cfe/trunk/test/Driver/fsanitize.c >> >> Modified: cfe/trunk/docs/UndefinedBehaviorSanitizer.rst >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UndefinedBehaviorSanitizer.rst?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UndefinedBehaviorSanitizer.rst?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/docs/UndefinedBehaviorSanitizer.rst (original) >> +++ cfe/trunk/docs/UndefinedBehaviorSanitizer.rst Thu Jun 1 14:22:18 2017 >> @@ -106,6 +106,8 @@ Available checks are: >> invalid pointers. These checks are made in terms of >> ``__builtin_object_size``, and consequently may be able to detect more >> problems at higher optimization levels. >> + - ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which >> + overflows. >> - ``-fsanitize=return``: In C++, reaching the end of a >> value-returning function without returning a value. >> - ``-fsanitize=returns-nonnull-attribute``: Returning null pointer >> >> Modified: cfe/trunk/include/clang/Basic/Sanitizers.def >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/include/clang/Basic/Sanitizers.def (original) >> +++ cfe/trunk/include/clang/Basic/Sanitizers.def Thu Jun 1 14:22:18 2017 >> @@ -73,6 +73,7 @@ SANITIZER("nullability-return", Nullabil >> SANITIZER_GROUP("nullability", Nullability, >> NullabilityArg | NullabilityAssign | NullabilityReturn) >> SANITIZER("object-size", ObjectSize) >> +SANITIZER("pointer-overflow", PointerOverflow) >> SANITIZER("return", Return) >> SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute) >> SANITIZER("shift-base", ShiftBase) >> @@ -108,9 +109,9 @@ SANITIZER("safe-stack", SafeStack) >> SANITIZER_GROUP("undefined", Undefined, >> Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | >> FloatDivideByZero | IntegerDivideByZero | >> NonnullAttribute | >> - Null | ObjectSize | Return | ReturnsNonnullAttribute | >> - Shift | SignedIntegerOverflow | Unreachable | VLABound | >> - Function | Vptr) >> + Null | ObjectSize | PointerOverflow | Return | >> + ReturnsNonnullAttribute | Shift | SignedIntegerOverflow >> | >> + Unreachable | VLABound | Function | Vptr) >> >> // -fsanitize=undefined-trap is an alias for -fsanitize=undefined. >> SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined) >> >> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jun 1 14:22:18 2017 >> @@ -3002,9 +3002,10 @@ static llvm::Value *emitArraySubscriptGE >> llvm::Value *ptr, >> ArrayRef<llvm::Value*> indices, >> bool inbounds, >> + SourceLocation loc, >> const llvm::Twine &name = "arrayidx") { >> if (inbounds) { >> - return CGF.Builder.CreateInBoundsGEP(ptr, indices, name); >> + return CGF.EmitCheckedInBoundsGEP(ptr, indices, loc, name); >> } else { >> return CGF.Builder.CreateGEP(ptr, indices, name); >> } >> @@ -3035,8 +3036,9 @@ static QualType getFixedSizeElementType( >> } >> >> static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, >> - ArrayRef<llvm::Value*> indices, >> + ArrayRef<llvm::Value *> indices, >> QualType eltType, bool inbounds, >> + SourceLocation loc, >> const llvm::Twine &name = "arrayidx") { >> // All the indices except that last must be zero. >> #ifndef NDEBUG >> @@ -3057,7 +3059,7 @@ static Address emitArraySubscriptGEP(Cod >> getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); >> >> llvm::Value *eltPtr = >> - emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, name); >> + emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, >> name); >> return Address(eltPtr, eltAlign); >> } >> >> @@ -3110,7 +3112,8 @@ LValue CodeGenFunction::EmitArraySubscri >> Address Addr = EmitExtVectorElementLValue(LV); >> >> QualType EltType = LV.getType()->castAs<VectorType>()->getElementType(); >> - Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ >> true); >> + Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ >> true, >> + E->getExprLoc()); >> return MakeAddrLValue(Addr, EltType, LV.getBaseInfo()); >> } >> >> @@ -3138,7 +3141,8 @@ LValue CodeGenFunction::EmitArraySubscri >> } >> >> Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), >> - !getLangOpts().isSignedOverflowDefined()); >> + !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> >> } else if (const ObjCObjectType *OIT = >> E->getType()->getAs<ObjCObjectType>()){ >> // Indexing over an interface, as in "NSString *P; P[4];" >> @@ -3163,8 +3167,8 @@ LValue CodeGenFunction::EmitArraySubscri >> // Do the GEP. >> CharUnits EltAlign = >> getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); >> - llvm::Value *EltPtr = >> - emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false); >> + llvm::Value *EltPtr = emitArraySubscriptGEP( >> + *this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc()); >> Addr = Address(EltPtr, EltAlign); >> >> // Cast back. >> @@ -3189,14 +3193,16 @@ LValue CodeGenFunction::EmitArraySubscri >> Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(), >> {CGM.getSize(CharUnits::Zero()), Idx}, >> E->getType(), >> - !getLangOpts().isSignedOverflowDefined()); >> + !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> BaseInfo = ArrayLV.getBaseInfo(); >> } else { >> // The base must be a pointer; emit it with an estimate of its >> alignment. >> Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo); >> auto *Idx = EmitIdxAfterBase(/*Promote*/true); >> Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), >> - !getLangOpts().isSignedOverflowDefined()); >> + !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> } >> >> LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo); >> @@ -3368,7 +3374,8 @@ LValue CodeGenFunction::EmitOMPArraySect >> else >> Idx = Builder.CreateNSWMul(Idx, NumElements); >> EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), >> - >> !getLangOpts().isSignedOverflowDefined()); >> + !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { >> // If this is A[i] where A is an array, the frontend will have decayed >> the >> // base to be a ArrayToPointerDecay implicit cast. While correct, it is >> @@ -3387,13 +3394,15 @@ LValue CodeGenFunction::EmitOMPArraySect >> // Propagate the alignment from the array itself to the result. >> EltPtr = emitArraySubscriptGEP( >> *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, >> - ResultExprTy, !getLangOpts().isSignedOverflowDefined()); >> + ResultExprTy, !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> BaseInfo = ArrayLV.getBaseInfo(); >> } else { >> Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, >> BaseTy, ResultExprTy, >> IsLowerBound); >> EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, >> - >> !getLangOpts().isSignedOverflowDefined()); >> + !getLangOpts().isSignedOverflowDefined(), >> + E->getExprLoc()); >> } >> >> return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo); >> >> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Jun 1 14:22:18 2017 >> @@ -30,6 +30,7 @@ >> #include "llvm/IR/Constants.h" >> #include "llvm/IR/DataLayout.h" >> #include "llvm/IR/Function.h" >> +#include "llvm/IR/GetElementPtrTypeIterator.h" >> #include "llvm/IR/GlobalVariable.h" >> #include "llvm/IR/Intrinsics.h" >> #include "llvm/IR/Module.h" >> @@ -44,6 +45,43 @@ using llvm::Value; >> >> //===----------------------------------------------------------------------===// >> >> namespace { >> + >> +/// Determine whether the given binary operation may overflow. >> +/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul, >> +/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned >> BO_{Div,Rem}, >> +/// the returned overflow check is precise. The returned value is 'true' for >> +/// all other opcodes, to be conservative. >> +bool mayHaveIntegerOverflow(llvm::ConstantInt *LHS, llvm::ConstantInt *RHS, >> + BinaryOperator::Opcode Opcode, bool Signed, >> + llvm::APInt &Result) { >> + // Assume overflow is possible, unless we can prove otherwise. >> + bool Overflow = true; >> + const auto &LHSAP = LHS->getValue(); >> + const auto &RHSAP = RHS->getValue(); >> + if (Opcode == BO_Add) { >> + if (Signed) >> + Result = LHSAP.sadd_ov(RHSAP, Overflow); >> + else >> + Result = LHSAP.uadd_ov(RHSAP, Overflow); >> + } else if (Opcode == BO_Sub) { >> + if (Signed) >> + Result = LHSAP.ssub_ov(RHSAP, Overflow); >> + else >> + Result = LHSAP.usub_ov(RHSAP, Overflow); >> + } else if (Opcode == BO_Mul) { >> + if (Signed) >> + Result = LHSAP.smul_ov(RHSAP, Overflow); >> + else >> + Result = LHSAP.umul_ov(RHSAP, Overflow); >> + } else if (Opcode == BO_Div || Opcode == BO_Rem) { >> + if (Signed && !RHS->isZero()) >> + Result = LHSAP.sdiv_ov(RHSAP, Overflow); >> + else >> + return false; >> + } >> + return Overflow; >> +} >> + >> struct BinOpInfo { >> Value *LHS; >> Value *RHS; >> @@ -55,37 +93,14 @@ struct BinOpInfo { >> /// Check if the binop can result in integer overflow. >> bool mayHaveIntegerOverflow() const { >> // Without constant input, we can't rule out overflow. >> - const auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS); >> - const auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS); >> + auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS); >> + auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS); >> if (!LHSCI || !RHSCI) >> return true; >> >> - // Assume overflow is possible, unless we can prove otherwise. >> - bool Overflow = true; >> - const auto &LHSAP = LHSCI->getValue(); >> - const auto &RHSAP = RHSCI->getValue(); >> - if (Opcode == BO_Add) { >> - if (Ty->hasSignedIntegerRepresentation()) >> - (void)LHSAP.sadd_ov(RHSAP, Overflow); >> - else >> - (void)LHSAP.uadd_ov(RHSAP, Overflow); >> - } else if (Opcode == BO_Sub) { >> - if (Ty->hasSignedIntegerRepresentation()) >> - (void)LHSAP.ssub_ov(RHSAP, Overflow); >> - else >> - (void)LHSAP.usub_ov(RHSAP, Overflow); >> - } else if (Opcode == BO_Mul) { >> - if (Ty->hasSignedIntegerRepresentation()) >> - (void)LHSAP.smul_ov(RHSAP, Overflow); >> - else >> - (void)LHSAP.umul_ov(RHSAP, Overflow); >> - } else if (Opcode == BO_Div || Opcode == BO_Rem) { >> - if (Ty->hasSignedIntegerRepresentation() && !RHSCI->isZero()) >> - (void)LHSAP.sdiv_ov(RHSAP, Overflow); >> - else >> - return false; >> - } >> - return Overflow; >> + llvm::APInt Result; >> + return ::mayHaveIntegerOverflow( >> + LHSCI, RHSCI, Opcode, Ty->hasSignedIntegerRepresentation(), Result); >> } >> >> /// Check if the binop computes a division or a remainder. >> @@ -1925,7 +1940,8 @@ ScalarExprEmitter::EmitScalarPrePostIncD >> if (CGF.getLangOpts().isSignedOverflowDefined()) >> value = Builder.CreateGEP(value, numElts, "vla.inc"); >> else >> - value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc"); >> + value = CGF.EmitCheckedInBoundsGEP(value, numElts, E->getExprLoc(), >> + "vla.inc"); >> >> // Arithmetic on function pointers (!) is just +-1. >> } else if (type->isFunctionType()) { >> @@ -1935,7 +1951,8 @@ ScalarExprEmitter::EmitScalarPrePostIncD >> if (CGF.getLangOpts().isSignedOverflowDefined()) >> value = Builder.CreateGEP(value, amt, "incdec.funcptr"); >> else >> - value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); >> + value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), >> + "incdec.funcptr"); >> value = Builder.CreateBitCast(value, input->getType()); >> >> // For everything else, we can just do a simple increment. >> @@ -1944,7 +1961,8 @@ ScalarExprEmitter::EmitScalarPrePostIncD >> if (CGF.getLangOpts().isSignedOverflowDefined()) >> value = Builder.CreateGEP(value, amt, "incdec.ptr"); >> else >> - value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); >> + value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(), >> + "incdec.ptr"); >> } >> >> // Vector increment/decrement. >> @@ -2025,7 +2043,8 @@ ScalarExprEmitter::EmitScalarPrePostIncD >> if (CGF.getLangOpts().isSignedOverflowDefined()) >> value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); >> else >> - value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); >> + value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, E->getExprLoc(), >> + "incdec.objptr"); >> value = Builder.CreateBitCast(value, input->getType()); >> } >> >> @@ -2692,7 +2711,8 @@ static Value *emitPointerArithmetic(Code >> pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr"); >> } else { >> index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index"); >> - pointer = CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr"); >> + pointer = CGF.EmitCheckedInBoundsGEP(pointer, index, >> op.E->getExprLoc(), >> + "add.ptr"); >> } >> return pointer; >> } >> @@ -2709,7 +2729,8 @@ static Value *emitPointerArithmetic(Code >> if (CGF.getLangOpts().isSignedOverflowDefined()) >> return CGF.Builder.CreateGEP(pointer, index, "add.ptr"); >> >> - return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr"); >> + return CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(), >> + "add.ptr"); >> } >> >> // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and >> @@ -3824,3 +3845,124 @@ LValue CodeGenFunction::EmitCompoundAssi >> >> llvm_unreachable("Unhandled compound assignment operator"); >> } >> + >> +Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, >> + ArrayRef<Value *> IdxList, >> + SourceLocation Loc, >> + const Twine &Name) { >> + Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name); >> + >> + // If the pointer overflow sanitizer isn't enabled, do nothing. >> + if (!SanOpts.has(SanitizerKind::PointerOverflow)) >> + return GEPVal; >> + >> + // If the GEP has already been reduced to a constant, leave it be. >> + if (isa<llvm::Constant>(GEPVal)) >> + return GEPVal; >> + >> + // Only check for overflows in the default address space. >> + if (GEPVal->getType()->getPointerAddressSpace()) >> + return GEPVal; >> + >> + auto *GEP = cast<llvm::GEPOperator>(GEPVal); >> + assert(GEP->isInBounds() && "Expected inbounds GEP"); >> + >> + SanitizerScope SanScope(this); >> + auto &VMContext = getLLVMContext(); >> + const auto &DL = CGM.getDataLayout(); >> + auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType()); >> + >> + // Grab references to the signed add/mul overflow intrinsics for intptr_t. >> + auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); >> + auto *SAddIntrinsic = >> + CGM.getIntrinsic(llvm::Intrinsic::sadd_with_overflow, IntPtrTy); >> + auto *SMulIntrinsic = >> + CGM.getIntrinsic(llvm::Intrinsic::smul_with_overflow, IntPtrTy); >> + >> + // The total (signed) byte offset for the GEP. >> + llvm::Value *TotalOffset = nullptr; >> + // The offset overflow flag - true if the total offset overflows. >> + llvm::Value *OffsetOverflows = Builder.getFalse(); >> + >> + /// Return the result of the given binary operation. >> + auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS, >> + llvm::Value *RHS) -> llvm::Value * { >> + assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop"); >> + >> + // If the operands are constants, return a constant result. >> + if (auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS)) { >> + if (auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS)) { >> + llvm::APInt N; >> + bool HasOverflow = mayHaveIntegerOverflow(LHSCI, RHSCI, Opcode, >> + /*Signed=*/true, N); >> + if (HasOverflow) >> + OffsetOverflows = Builder.getTrue(); >> + return llvm::ConstantInt::get(VMContext, N); >> + } >> + } >> + >> + // Otherwise, compute the result with checked arithmetic. >> + auto *ResultAndOverflow = Builder.CreateCall( >> + (Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS}); >> + OffsetOverflows = Builder.CreateOr( >> + OffsetOverflows, Builder.CreateExtractValue(ResultAndOverflow, 1)); >> + return Builder.CreateExtractValue(ResultAndOverflow, 0); >> + }; >> + >> + // Determine the total byte offset by looking at each GEP operand. >> + for (auto GTI = llvm::gep_type_begin(GEP), GTE = llvm::gep_type_end(GEP); >> + GTI != GTE; ++GTI) { >> + llvm::Value *LocalOffset; >> + auto *Index = GTI.getOperand(); >> + // Compute the local offset contributed by this indexing step: >> + if (auto *STy = GTI.getStructTypeOrNull()) { >> + // For struct indexing, the local offset is the byte position of the >> + // specified field. >> + unsigned FieldNo = cast<llvm::ConstantInt>(Index)->getZExtValue(); >> + LocalOffset = llvm::ConstantInt::get( >> + IntPtrTy, DL.getStructLayout(STy)->getElementOffset(FieldNo)); >> + } else { >> + // Otherwise this is array-like indexing. The local offset is the >> index >> + // multiplied by the element size. >> + auto *ElementSize = llvm::ConstantInt::get( >> + IntPtrTy, DL.getTypeAllocSize(GTI.getIndexedType())); >> + auto *IndexS = Builder.CreateIntCast(Index, IntPtrTy, >> /*isSigned=*/true); >> + LocalOffset = eval(BO_Mul, ElementSize, IndexS); >> + } >> + >> + // If this is the first offset, set it as the total offset. Otherwise, >> add >> + // the local offset into the running total. >> + if (!TotalOffset || TotalOffset == Zero) >> + TotalOffset = LocalOffset; >> + else >> + TotalOffset = eval(BO_Add, TotalOffset, LocalOffset); >> + } >> + >> + // Common case: if the total offset is zero, don't emit a check. >> + if (TotalOffset == Zero) >> + return GEPVal; >> + >> + // Now that we've computed the total offset, add it to the base pointer >> (with >> + // wrapping semantics). >> + auto *IntPtr = Builder.CreatePtrToInt(GEP->getPointerOperand(), IntPtrTy); >> + auto *ComputedGEP = Builder.CreateAdd(IntPtr, TotalOffset); >> + >> + // The GEP is valid if: >> + // 1) The total offset doesn't overflow, and >> + // 2) The sign of the difference between the computed address and the base >> + // pointer matches the sign of the total offset. >> + llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); >> + llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); >> + auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); >> + llvm::Value *ValidGEP = Builder.CreateAnd( >> + Builder.CreateNot(OffsetOverflows), >> + Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid)); >> + >> + llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)}; >> + // Pass the computed GEP to the runtime to avoid emitting poisoned >> arguments. >> + llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP}; >> + EmitCheck(std::make_pair(ValidGEP, SanitizerKind::PointerOverflow), >> + SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs); >> + >> + return GEPVal; >> +} >> >> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) >> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Jun 1 14:22:18 2017 >> @@ -120,6 +120,7 @@ enum TypeEvaluationKind { >> SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) >> \ >> SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) >> \ >> SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) >> \ >> + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) >> \ >> SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) >> \ >> SANITIZER_CHECK(SubOverflow, sub_overflow, 0) >> \ >> SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) >> \ >> @@ -3551,6 +3552,13 @@ public: >> /// nonnull, if \p LHS is marked _Nonnull. >> void EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, SourceLocation >> Loc); >> >> + /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check >> to >> + /// detect undefined behavior when the pointer overflow sanitizer is >> enabled. >> + llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr, >> + ArrayRef<llvm::Value *> IdxList, >> + SourceLocation Loc, >> + const Twine &Name = ""); >> + >> /// \brief Emit a description of a type in a format suitable for passing >> to >> /// a runtime sanitizer handler. >> llvm::Constant *EmitCheckTypeDescriptor(QualType T); >> >> Added: cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m?rev=304459&view=auto >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m?rev=304459&view=auto> >> ============================================================================== >> --- cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m (added) >> +++ cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m Thu Jun 1 14:22:18 2017 >> @@ -0,0 +1,171 @@ >> +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s >> -fsanitize=pointer-overflow | FileCheck %s >> + >> +// CHECK-LABEL: define void @unary_arith >> +void unary_arith(char *p) { >> + // CHECK: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize >> + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 1, !nosanitize >> + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 true, i1 [[POSVALID]], i1 >> [[NEGVALID]], !nosanitize >> + // CHECK-NEXT: [[VALID:%.*]] = and i1 true, [[DIFFVALID]], !nosanitize >> + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], >> i64 [[COMPGEP]]){{.*}}, !nosanitize >> + ++p; >> + >> + // CHECK: ptrtoint i8* {{.*}} to i64, !nosanitize >> + // CHECK-NEXT: add i64 {{.*}}, -1, !nosanitize >> + // CHECK: select i1 false{{.*}}, !nosanitize >> + // CHECK-NEXT: and i1 true{{.*}}, !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + --p; >> + >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + p++; >> + >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + p--; >> +} >> + >> +// CHECK-LABEL: define void @binary_arith >> +void binary_arith(char *p, int i) { >> + // CHECK: [[SMUL:%.*]] = call { i64, i1 } >> @llvm.smul.with.overflow.i64(i64 1, i64 %{{.*}}), !nosanitize >> + // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, >> !nosanitize >> + // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], >> !nosanitize >> + // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, >> !nosanitize >> + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize >> + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], >> !nosanitize >> + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, >> !nosanitize >> + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, >> !nosanitize >> + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 >> [[POSVALID]], i1 [[NEGVALID]], !nosanitize >> + // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], >> !nosanitize >> + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], >> i64 [[COMPGEP]]){{.*}}, !nosanitize >> + p + i; >> + >> + // CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}} >> + // CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]] >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + p - i; >> +} >> + >> +// CHECK-LABEL: define void @fixed_len_array >> +void fixed_len_array(int k) { >> + // CHECK: getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* >> [[ARR:%.*]], i64 0, i64 [[IDXPROM:%.*]] >> + // CHECK-NEXT: [[SMUL:%.*]] = call { i64, i1 } >> @llvm.smul.with.overflow.i64(i64 40, i64 [[IDXPROM]]), !nosanitize >> + // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, >> !nosanitize >> + // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], >> !nosanitize >> + // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, >> !nosanitize >> + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint [10 x [10 x i32]]* [[ARR]] to i64, >> !nosanitize >> + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], >> !nosanitize >> + // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], >> !nosanitize >> + // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, >> !nosanitize >> + // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, >> !nosanitize >> + // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 >> [[POSVALID]], i1 [[NEGVALID]], !nosanitize >> + // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], >> !nosanitize >> + // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], >> i64 [[COMPGEP]]){{.*}}, !nosanitize >> + >> + // CHECK: getelementptr inbounds [10 x i32], [10 x i32]* {{.*}}, i64 0, >> i64 [[IDXPROM1:%.*]] >> + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), >> !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + >> + int arr[10][10]; >> + arr[k][k]; >> +} >> + >> +// CHECK-LABEL: define void @variable_len_array >> +void variable_len_array(int n, int k) { >> + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]] >> + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), >> !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + >> + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM1:%.*]] >> + // CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), >> !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + >> + int arr[n][n]; >> + arr[k][k]; >> +} >> + >> +// CHECK-LABEL: define void @pointer_array >> +void pointer_array(int **arr, int k) { >> + // CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + >> + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 {{.*}}), !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + >> + arr[k][k]; >> +} >> + >> +struct S1 { >> + int pad1; >> + union { >> + char leaf; >> + struct S1 *link; >> + } u; >> + struct S1 *arr; >> +}; >> + >> +// TODO: Currently, structure GEPs are not checked, so there are several >> +// potentially unsafe GEPs here which we don't instrument. >> +// >> +// CHECK-LABEL: define void @struct_index >> +void struct_index(struct S1 *p) { >> + // CHECK: getelementptr inbounds %struct.S1, %struct.S1* [[P:%.*]], i64 10 >> + // CHECK-NEXT: [[BASE:%.*]] = ptrtoint %struct.S1* [[P]] to i64, >> !nosanitize >> + // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 240, !nosanitize >> + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} i64 [[BASE]], i64 >> [[COMPGEP]]) {{.*}}, !nosanitize >> + >> + // CHECK-NOT: @__ubsan_handle_pointer_overflow >> + >> + p->arr[10].u.link->u.leaf; >> +} >> + >> +typedef void (*funcptr_t)(void); >> + >> +// CHECK-LABEL: define void @function_pointer_arith >> +void function_pointer_arith(funcptr_t *p, int k) { >> + // CHECK: add i64 {{.*}}, 8, !nosanitize >> + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} >> + ++p; >> + >> + // CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + p + k; >> +} >> + >> +// CHECK-LABEL: define void @variable_len_array_arith >> +void variable_len_array_arith(int n, int k) { >> + int vla[n]; >> + int (*p)[n] = &vla; >> + >> + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[INC:%.*]] >> + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[INC]]), !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + ++p; >> + >> + // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]] >> + // CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), >> !nosanitize >> + // CHECK: call void @__ubsan_handle_pointer_overflow{{.*}} >> + p + k; >> +} >> + >> +// CHECK-LABEL: define void @objc_id >> +void objc_id(id *p) { >> + // CHECK: add i64 {{.*}}, 8, !nosanitize >> + // CHECK: @__ubsan_handle_pointer_overflow{{.*}} >> + p++; >> +} >> + >> +// CHECK-LABEL: define void @dont_emit_checks_for_no_op_GEPs >> +// CHECK-NOT: __ubsan_handle_pointer_overflow >> +void dont_emit_checks_for_no_op_GEPs(char *p) { >> + &p[0]; >> + >> + int arr[10][10]; >> + &arr[0][0]; >> +} >> >> Modified: cfe/trunk/test/Driver/fsanitize.c >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=304459&r1=304458&r2=304459&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=304459&r1=304458&r2=304459&view=diff> >> ============================================================================== >> --- cfe/trunk/test/Driver/fsanitize.c (original) >> +++ cfe/trunk/test/Driver/fsanitize.c Thu Jun 1 14:22:18 2017 >> @@ -3,18 +3,18 @@ >> // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined >> -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-UNDEFINED-TRAP >> // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap >> -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-UNDEFINED-TRAP >> // RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error >> -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-UNDEFINED-TRAP >> -// CHECK-UNDEFINED-TRAP: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} >> -// CHECK-UNDEFINED-TRAP: >> "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" >> -// CHECK-UNDEFINED-TRAP2: >> "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" >> +// CHECK-UNDEFINED-TRAP: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}} >> +// CHECK-UNDEFINED-TRAP: >> "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" >> +// CHECK-UNDEFINED-TRAP2: >> "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" >> >> // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | >> FileCheck %s --check-prefix=CHECK-UNDEFINED >> -// CHECK-UNDEFINED: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){19}"}} >> +// CHECK-UNDEFINED: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){20}"}} >> >> // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### >> 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN >> -// CHECK-UNDEFINED-DARWIN: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} >> +// CHECK-UNDEFINED-DARWIN: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} >> >> // RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### >> 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD >> -// CHECK-UNDEFINED-OPENBSD: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} >> +// CHECK-UNDEFINED-OPENBSD: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} >> >> // RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | >> FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN >> --check-prefix=CHECK-UNDEFINED-WIN32 >> // RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### >> 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN >> --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX >> @@ -23,7 +23,7 @@ >> // CHECK-UNDEFINED-WIN32: >> "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" >> // CHECK-UNDEFINED-WIN64: >> "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib" >> // CHECK-UNDEFINED-WIN-CXX: >> "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib" >> -// CHECK-UNDEFINED-WIN-SAME: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} >> +// CHECK-UNDEFINED-WIN-SAME: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} >> >> // RUN: %clang -target i386-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | >> FileCheck %s --check-prefix=CHECK-COVERAGE-WIN32 >> // CHECK-COVERAGE-WIN32: >> "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" >> @@ -43,7 +43,7 @@ >> // CHECK-FNO-SANITIZE-ALL: "-fsanitize=thread" >> >> // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined >> -fno-sanitize=thread -fno-sanitize=float-cast-overflow,vptr,bool,enum %s >> -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED >> -// CHECK-PARTIAL-UNDEFINED: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){15}"}} >> +// CHECK-PARTIAL-UNDEFINED: >> "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){16}"}} >> >> // RUN: %clang -target x86_64-linux-gnu -fsanitize=shift >> -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-FSANITIZE-SHIFT-PARTIAL >> // CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent" >> @@ -217,7 +217,7 @@ >> // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined >> -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-NO-RECOVER-UBSAN >> // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined >> -fno-sanitize-recover=all -fsanitize-recover=thread -### 2>&1 | FileCheck %s >> --check-prefix=CHECK-NO-RECOVER-UBSAN >> // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined >> -fsanitize-recover=all -fno-sanitize-recover=undefined -### 2>&1 | FileCheck >> %s --check-prefix=CHECK-NO-RECOVER-UBSAN >> -// CHECK-RECOVER-UBSAN: >> "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}} >> +// CHECK-RECOVER-UBSAN: >> "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}} >> // CHECK-NO-RECOVER-UBSAN-NOT: sanitize-recover >> >> // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined >> -fno-sanitize-recover=all -fsanitize-recover=object-size,shift-base -### >> 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-RECOVER >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits> >> > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits