fix PR17635: false positive with packed structures
authorNuno Lopes <nunoplopes@sapo.pt>
Thu, 24 Oct 2013 09:17:24 +0000 (09:17 +0000)
committerNuno Lopes <nunoplopes@sapo.pt>
Thu, 24 Oct 2013 09:17:24 +0000 (09:17 +0000)
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
lib/Analysis/MemoryBuiltins.cpp
lib/Transforms/Instrumentation/BoundsChecking.cpp
test/Instrumentation/BoundsChecking/simple-32.ll [new file with mode: 0644]

index c54b7e6dfb5f615065f47b57cc600a2f732cf97b..91224ad94ac2983e3f4008a54b2e33a914b528d3 100644 (file)
@@ -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) {
index a2fb544c6575f358328d0ed2a0d3685d37faa7e3..1db0f634c941e4da86a61179fc73ca301cba2eab 100644 (file)
@@ -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),
index 4a9e9503675050637980fa122de557a51f0bcf04..7a9f0f69fbdf22e3c2e44f9a4739f972fcbc085c 100644 (file)
@@ -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 (file)
index 0000000..38b210f
--- /dev/null
@@ -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
+}