From 8f03dcdc91326fcccaa7aabe2fe898fd3c9c4e58 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 6 Sep 2019 14:18:57 +0000 Subject: [PATCH] [NFC][CodeGen][UBSan] EmitCheckedInBoundsGEP(): refactor EmitGEPOffsetInBytes() helper It shouldn't really be inlined into the EmitCheckedInBoundsGEP(). Refactoring it beforehand will make follow-up changes more obvious. This was originally part of https://reviews.llvm.org/D67122 llvm-svn: 371207 --- clang/lib/CodeGen/CGExprScalar.cpp | 77 +++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 1221527..fc5f072 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4533,31 +4533,24 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue( llvm_unreachable("Unhandled compound assignment operator"); } -Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, - ArrayRef IdxList, - bool SignedIndices, - bool IsSubtraction, - 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(GEPVal)) - return GEPVal; - - // Only check for overflows in the default address space. - if (GEPVal->getType()->getPointerAddressSpace()) - return GEPVal; +struct GEPOffsetAndOverflow { + // The total (signed) byte offset for the GEP. + llvm::Value *TotalOffset; + // The offset overflow flag - true if the total offset overflows. + llvm::Value *OffsetOverflows; +}; +/// Evaluate given GEPVal, which must be an inbounds GEP, +/// and compute the total offset it applies from it's base pointer BasePtr. +/// Returns offset in bytes and a boolean flag whether an overflow happened +/// during evaluation. +static GEPOffsetAndOverflow EmitGEPOffsetInBytes(Value *BasePtr, Value *GEPVal, + llvm::LLVMContext &VMContext, + CodeGenModule &CGM, + CGBuilderTy Builder) { auto *GEP = cast(GEPVal); assert(GEP->isInBounds() && "Expected inbounds GEP"); - SanitizerScope SanScope(this); - auto &VMContext = getLLVMContext(); const auto &DL = CGM.getDataLayout(); auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType()); @@ -4627,21 +4620,54 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, TotalOffset = eval(BO_Add, TotalOffset, LocalOffset); } + return {TotalOffset, OffsetOverflows}; +} + +Value * +CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, ArrayRef IdxList, + bool SignedIndices, bool IsSubtraction, + 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(GEPVal)) + return GEPVal; + + // Only check for overflows in the default address space. + if (GEPVal->getType()->getPointerAddressSpace()) + return GEPVal; + + SanitizerScope SanScope(this); + + GEPOffsetAndOverflow EvaluatedGEP = + EmitGEPOffsetInBytes(Ptr, GEPVal, getLLVMContext(), CGM, Builder); + + auto *GEP = cast(GEPVal); + + const auto &DL = CGM.getDataLayout(); + auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType()); + + auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); + // Common case: if the total offset is zero, don't emit a check. - if (TotalOffset == Zero) + if (EvaluatedGEP.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); + auto *ComputedGEP = Builder.CreateAdd(IntPtr, EvaluatedGEP.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 *ValidGEP; - auto *NoOffsetOverflow = Builder.CreateNot(OffsetOverflows); + auto *NoOffsetOverflow = Builder.CreateNot(EvaluatedGEP.OffsetOverflows); if (SignedIndices) { // GEP is computed as `unsigned base + signed offset`, therefore: // * If offset was positive, then the computed pointer can not be @@ -4649,7 +4675,8 @@ Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, // * If offset was negative, then the computed pointer can not be // [unsigned] greater than the bas pointere, unless it overflowed. auto *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr); - auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero); + auto *PosOrZeroOffset = + Builder.CreateICmpSGE(EvaluatedGEP.TotalOffset, Zero); llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr); ValidGEP = Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid); } else if (!IsSubtraction) { -- 2.7.4