From 5e1d0d39db5fefe013f58c124a94694f96bce2f1 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Thu, 24 Oct 2013 09:17:24 +0000 Subject: [PATCH] fix PR17635: false positive with packed structures LLVM optimizers may widen accesses to packed structures that overflow the structure itself, but should be in bounds up to the alignment of the object git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193317 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/MemoryBuiltins.h | 3 +- lib/Analysis/MemoryBuiltins.cpp | 8 +++-- .../Instrumentation/BoundsChecking.cpp | 3 +- .../BoundsChecking/simple-32.ll | 29 +++++++++++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 test/Instrumentation/BoundsChecking/simple-32.ll diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index c54b7e6dfb5..91224ad94ac 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -228,6 +228,7 @@ class ObjectSizeOffsetEvaluator Value *Zero; CacheMapTy CacheMap; PtrSetTy SeenVals; + bool RoundToAlign; SizeOffsetEvalType unknown() { return std::make_pair((Value*)0, (Value*)0); @@ -236,7 +237,7 @@ class ObjectSizeOffsetEvaluator public: ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, - LLVMContext &Context); + LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); bool knownSize(SizeOffsetEvalType SizeOffset) { diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index a2fb544c657..1db0f634c94 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -588,8 +588,10 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, - LLVMContext &Context) -: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)) { + LLVMContext &Context, + bool RoundToAlign) +: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)), + RoundToAlign(RoundToAlign) { IntTy = DL->getIntPtrType(Context); Zero = ConstantInt::get(IntTy, 0); } @@ -614,7 +616,7 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) { } SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { - ObjectSizeOffsetVisitor Visitor(DL, TLI, Context); + ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign); SizeOffsetType Const = Visitor.compute(V); if (Visitor.bothKnown(Const)) return std::make_pair(ConstantInt::get(Context, Const.first), diff --git a/lib/Transforms/Instrumentation/BoundsChecking.cpp b/lib/Transforms/Instrumentation/BoundsChecking.cpp index 4a9e9503675..7a9f0f69fbd 100644 --- a/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -172,7 +172,8 @@ bool BoundsChecking::runOnFunction(Function &F) { TrapBB = 0; BuilderTy TheBuilder(F.getContext(), TargetFolder(TD)); Builder = &TheBuilder; - ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext()); + ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext(), + /*RoundToAlign=*/true); ObjSizeEval = &TheObjSizeEval; // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory diff --git a/test/Instrumentation/BoundsChecking/simple-32.ll b/test/Instrumentation/BoundsChecking/simple-32.ll new file mode 100644 index 00000000000..38b210f7e23 --- /dev/null +++ b/test/Instrumentation/BoundsChecking/simple-32.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -bounds-checking -S | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" + +%struct.s2_packed = type <{ i64, i32, i32, i32, i16, i8 }> + +; CHECK-LABEL: @f +; CHECK-NOT: trap +define i16 @f() { +entry: + %packed1 = alloca %struct.s2_packed, align 8 + %gep = getelementptr inbounds %struct.s2_packed* %packed1, i32 0, i32 4 + %ptr = bitcast i16* %gep to i32* + %val = load i32* %ptr, align 4 + %valt = trunc i32 %val to i16 + ret i16 %valt +} + +; CHECK-LABEL: @f +; CHECK: call void @llvm.trap() +define i16 @f2() { +entry: + %packed1 = alloca %struct.s2_packed, align 8 + %gep = getelementptr inbounds %struct.s2_packed* %packed1, i32 0, i32 4 + %ptr = bitcast i16* %gep to i48* + %val = load i48* %ptr, align 4 + %valt = trunc i48 %val to i16 + ret i16 %valt +} -- 2.34.1