[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

Török Edvin edwin at clamav.net
Sun Apr 4 01:20:41 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit a45651d4cb5c5cf9f1e4f20d68b9b6d8169c14de
Author: Török Edvin <edwin at clamav.net>
Date:   Mon Feb 15 17:45:33 2010 +0200

    add another missing file

diff --git a/libclamav/c++/ClamBCRTChecks.cpp b/libclamav/c++/ClamBCRTChecks.cpp
new file mode 100644
index 0000000..ef401c5
--- /dev/null
+++ b/libclamav/c++/ClamBCRTChecks.cpp
@@ -0,0 +1,392 @@
+/*
+ *  Compile LLVM bytecode to ClamAV bytecode.
+ *
+ *  Copyright (C) 2009-2010 Sourcefire, Inc.
+ *
+ *  Authors: Török Edvin
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301, USA.
+ */
+#define DEBUG_TYPE "clambc-rtcheck"
+#include "ClamBCModule.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Dominators.h"
+#include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/Analysis/LiveValues.h"
+#include "llvm/Analysis/PointerTracking.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Config/config.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DataFlow.h"
+#include "llvm/Support/InstIterator.h"
+#include "llvm/Support/InstVisitor.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+namespace {
+
+  class PtrVerifier : public FunctionPass {
+  public:
+    static char ID;
+    PtrVerifier() : FunctionPass((intptr_t)&ID) {}
+
+    virtual bool runOnFunction(Function &F) {
+      DEBUG(F.dump());
+      Changed = false;
+      BaseMap.clear();
+      BoundsMap.clear();
+      AbrtBB = 0;
+      valid = true;
+
+      BasicBlock::iterator It = F.getEntryBlock().begin();
+      while (isa<AllocaInst>(It) || isa<PHINode>(It)) ++It;
+      EP = &*It;
+
+      TD = &getAnalysis<TargetData>();
+      SE = &getAnalysis<ScalarEvolution>();
+      PT = &getAnalysis<PointerTracking>();
+      DT = &getAnalysis<DominatorTree>();
+
+      std::vector<Instruction*> insns;
+
+      for (inst_iterator I=inst_begin(F),E=inst_end(F); I != E;++I) {
+        Instruction *II = &*I;
+        if (isa<LoadInst>(II) || isa<StoreInst>(II) || isa<MemIntrinsic>(II))
+          insns.push_back(II);
+      }
+      while (!insns.empty()) {
+        Instruction *II = insns.back();
+        insns.pop_back();
+        DEBUG(dbgs() << "checking " << *II << "\n");
+        if (LoadInst *LI = dyn_cast<LoadInst>(II)) {
+          const Type *Ty = LI->getType();
+          valid &= validateAccess(LI->getPointerOperand(),
+                                  TD->getTypeAllocSize(Ty), LI);
+        } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
+          const Type *Ty = SI->getOperand(0)->getType();
+          valid &= validateAccess(SI->getPointerOperand(),
+                                  TD->getTypeAllocSize(Ty), SI);
+        } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(II)) {
+          valid &= validateAccess(MI->getDest(), MI->getLength(), MI);
+          if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
+            valid &= validateAccess(MTI->getSource(), MI->getLength(), MI);
+          }
+        }
+      }
+
+      if (!valid) {
+        ClamBCModule::stop("Verification found errors!", &F, 0);	
+	// replace function with call to abort
+        std::vector<const Type*>args;
+        FunctionType* abrtTy = FunctionType::get(
+          Type::getVoidTy(F.getContext()),args,false);
+        Constant *func_abort =
+          F.getParent()->getOrInsertFunction("abort", abrtTy);
+
+	BasicBlock *BB = &F.getEntryBlock();
+	Instruction *I = &*BB->begin();
+	Instruction *UI = new UnreachableInst(F.getContext(), I);
+	CallInst *AbrtC = CallInst::Create(func_abort, "", UI);
+        AbrtC->setCallingConv(CallingConv::C);
+        AbrtC->setTailCall(true);
+        AbrtC->setDoesNotReturn(true);
+        AbrtC->setDoesNotThrow(true);
+	// remove all instructions from entry
+	BasicBlock::iterator BBI = I, BBE=BB->end();
+	while (BBI != BBE) {
+	    if (!BBI->use_empty())
+		BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
+	    BB->getInstList().erase(BBI++);
+	}
+      }
+      return Changed;
+    }
+
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired<TargetData>();
+      AU.addRequired<DominatorTree>();
+      AU.addRequired<ScalarEvolution>();
+      AU.addRequired<PointerTracking>();
+    }
+
+    bool isValid() const { return valid; }
+  private:
+    PointerTracking *PT;
+    TargetData *TD;
+    ScalarEvolution *SE;
+    DominatorTree *DT;
+    DenseMap<Value*, Value*> BaseMap;
+    DenseMap<Value*, Value*> BoundsMap;
+    BasicBlock *AbrtBB;
+    bool Changed;
+    bool valid;
+    Instruction *EP;
+
+    Instruction *getInsertPoint(Value *V)
+    {
+      BasicBlock::iterator It =  EP;
+      if (Instruction *I = dyn_cast<Instruction>(V)) {
+        It = I;
+        ++It;
+      }
+      return &*It;
+    }
+
+    Value *getPointerBase(Value *Ptr)
+    {
+      if (BaseMap.count(Ptr))
+        return BaseMap[Ptr];
+      Value *P = Ptr->stripPointerCasts();
+      if (BaseMap.count(P)) {
+        return BaseMap[Ptr] = BaseMap[P];
+      }
+      Value *P2 = P->getUnderlyingObject();
+      if (P2 != P) {
+        Value *V = getPointerBase(P2);
+        return BaseMap[Ptr] = V;
+      }
+
+      const Type *P8Ty =
+        PointerType::getUnqual(Type::getInt8Ty(Ptr->getContext()));
+      if (PHINode *PN = dyn_cast<PHINode>(Ptr)) {
+        BasicBlock::iterator It = PN;
+        ++It;
+        PHINode *newPN = PHINode::Create(P8Ty, ".verif.base", &*It);
+        Changed = true;
+        BaseMap[Ptr] = newPN;
+
+        for (unsigned i=0;i<PN->getNumIncomingValues();i++) {
+          Value *Inc = PN->getIncomingValue(i);
+          Value *V = getPointerBase(Inc);
+          newPN->addIncoming(V, PN->getIncomingBlock(i));
+        }
+        return newPN;
+      }
+      if (Ptr->getType() != P8Ty) {
+        if (Constant *C = dyn_cast<Constant>(Ptr))
+          Ptr = ConstantExpr::getPointerCast(C, P8Ty);
+        else {
+          Instruction *I = getInsertPoint(Ptr);
+          Ptr = new BitCastInst(Ptr, P8Ty, "", I);
+        }
+      }
+      return BaseMap[Ptr] = Ptr;
+    }
+
+    Value* getPointerBounds(Value *Base) {
+      if (BoundsMap.count(Base))
+        return BoundsMap[Base];
+      const Type *I64Ty =
+        Type::getInt64Ty(Base->getContext());
+      if (PHINode *PN = dyn_cast<PHINode>(Base)) {
+        BasicBlock::iterator It = PN;
+        ++It;
+        PHINode *newPN = PHINode::Create(I64Ty, ".verif.bounds", &*It);
+        Changed = true;
+        BoundsMap[Base] = newPN;
+
+        bool good = true;
+        for (unsigned i=0;i<PN->getNumIncomingValues();i++) {
+          Value *Inc = PN->getIncomingValue(i);
+          Value *B = getPointerBounds(Inc);
+          if (!B) {
+            good = false;
+            B = ConstantInt::get(PN->getType(), 0);
+            DEBUG(dbgs() << "bounds not found while solving phi node: " << *Inc
+                  << "\n");
+          }
+          newPN->addIncoming(B, PN->getIncomingBlock(i));
+        }
+        if (!good)
+          newPN = 0;
+        return BoundsMap[Base] = newPN;
+      }
+
+      const Type *Ty;
+      Value *V = PT->computeAllocationCountValue(Base, Ty);
+      if (!V)
+        return BoundsMap[Base] = 0;
+      unsigned size = TD->getTypeAllocSize(Ty);
+      if (size > 1) {
+        Constant *C = cast<Constant>(V);
+        C = ConstantExpr::getMul(C,
+                                 ConstantInt::get(Type::getInt32Ty(C->getContext()),
+                                                                   size));
+        V = C;
+      }
+      if (V->getType() != I64Ty) {
+        if (Constant *C = dyn_cast<Constant>(V))
+          V = ConstantExpr::getZExt(C, I64Ty);
+        else {
+          Instruction *I = getInsertPoint(V);
+          V = new ZExtInst(V, I64Ty, "", I);
+        }
+      }
+      return BoundsMap[Base] = V;
+    }
+
+    bool insertCheck(const SCEV *Idx, const SCEV *Limit, Instruction *I)
+    {
+      if (isa<SCEVCouldNotCompute>(Idx) && isa<SCEVCouldNotCompute>(Limit)) {
+        errs() << "Could not compute the index and the limit!: \n" << *I << "\n";
+        return false;
+      }
+      if (isa<SCEVCouldNotCompute>(Idx)) {
+        errs() << "Could not compute index: \n" << *I << "\n";
+        return false;
+      }
+      if (isa<SCEVCouldNotCompute>(Limit)) {
+        errs() << "Could not compute limit: " << *I << "\n";
+        return false;
+      }
+      BasicBlock *BB = I->getParent();
+      BasicBlock::iterator It = I;
+      BasicBlock *newBB = SplitBlock(BB, &*It, this);
+      //verifyFunction(*BB->getParent());
+      if (!AbrtBB) {
+        std::vector<const Type*>args;
+        FunctionType* abrtTy = FunctionType::get(
+          Type::getVoidTy(BB->getContext()),args,false);
+        Constant *func_abort =
+          BB->getParent()->getParent()->getOrInsertFunction("abort", abrtTy);
+        AbrtBB = BasicBlock::Create(BB->getContext(), "", BB->getParent());
+        CallInst* AbrtC = CallInst::Create(func_abort, "", AbrtBB);
+        AbrtC->setCallingConv(CallingConv::C);
+        AbrtC->setTailCall(true);
+        AbrtC->setDoesNotReturn(true);
+        AbrtC->setDoesNotThrow(true);
+        new UnreachableInst(BB->getContext(), AbrtBB);
+        DT->addNewBlock(AbrtBB, BB);
+        //verifyFunction(*BB->getParent());
+      }
+      TerminatorInst *TI = BB->getTerminator();
+      SCEVExpander expander(*SE);
+      Value *IdxV = expander.expandCodeFor(Idx, Idx->getType(), TI);
+      //verifyFunction(*BB->getParent());
+      Value *LimitV = expander.expandCodeFor(Limit, Limit->getType(), TI);
+      //verifyFunction(*BB->getParent());
+      Value *Cond = new ICmpInst(TI, ICmpInst::ICMP_ULT, IdxV, LimitV);
+      //verifyFunction(*BB->getParent());
+      BranchInst::Create(newBB, AbrtBB, Cond, TI);
+      TI->eraseFromParent();
+      // Update dominator info
+      BasicBlock *DomBB =
+        DT->findNearestCommonDominator(BB,
+                                       DT->getNode(AbrtBB)->getIDom()->getBlock());
+      DT->changeImmediateDominator(AbrtBB, DomBB);
+      //verifyFunction(*BB->getParent());
+      return true;
+    }
+   
+    static void MakeCompatible(ScalarEvolution *SE, const SCEV*& LHS, const SCEV*& RHS) 
+    {
+      if (const SCEVZeroExtendExpr *ZL = dyn_cast<SCEVZeroExtendExpr>(LHS))
+        LHS = ZL->getOperand();
+      if (const SCEVZeroExtendExpr *ZR = dyn_cast<SCEVZeroExtendExpr>(RHS))
+        RHS = ZR->getOperand();
+
+      const Type* LTy = SE->getEffectiveSCEVType(LHS->getType());
+      const Type *RTy = SE->getEffectiveSCEVType(RHS->getType());
+      if (SE->getTypeSizeInBits(RTy) > SE->getTypeSizeInBits(LTy))
+        LTy = RTy;
+      LHS = SE->getNoopOrZeroExtend(LHS, LTy);
+      RHS = SE->getNoopOrZeroExtend(RHS, LTy);
+    }
+    bool validateAccess(Value *Pointer, Value *Length, Instruction *I)
+    {
+        // get base
+        Value *Base = getPointerBase(Pointer);
+
+        // get bounds
+        Value *Bounds = getPointerBounds(Base);
+        if (!Bounds) {
+          errs() << "No bounds for base " << *Base << "\n";
+          errs() << " while checking access to " << *Pointer << " of length "
+            << *Length << " at " << *I << "\n";
+
+          return false;
+        }
+
+        const Type *I64Ty =
+          Type::getInt64Ty(Base->getContext());
+        const SCEV *SLen = SE->getSCEV(Length);
+        const SCEV *OffsetP = SE->getMinusSCEV(SE->getSCEV(Pointer),
+                                               SE->getSCEV(Base));
+        SLen = SE->getNoopOrZeroExtend(SLen, I64Ty);
+        OffsetP = SE->getNoopOrZeroExtend(OffsetP, I64Ty);
+        const SCEV *Limit = SE->getSCEV(Bounds);
+        Limit = SE->getNoopOrZeroExtend(Limit, I64Ty);
+
+        DEBUG(dbgs() << "Checking access to " << *Pointer << " of length " <<
+              *Length << "\n");
+        if (OffsetP == Limit)
+          return true;
+
+        if (SLen == Limit) {
+          if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(OffsetP)) {
+            if (SC->isZero())
+              return true;
+          }
+          errs() << "SLen == Limit: " << *SLen << "\n";
+          errs() << " while checking access to " << *Pointer << " of length "
+            << *Length << " at " << *I << "\n";
+          return false;//TODO: insert abort
+        }
+
+        const SCEV *MaxL = SE->getUMaxExpr(SLen, Limit);
+        if (MaxL != Limit) {
+          DEBUG(dbgs() << "MaxL != Limit: " << *MaxL << ", " << *Limit << "\n");
+          return insertCheck(SLen, Limit, I);
+        }
+
+        //TODO: nullpointer check
+        const SCEV *Max = SE->getUMaxExpr(OffsetP, Limit);
+        if (Max == Limit)
+          return true;
+        DEBUG(dbgs() << "Max != Limit: " << *Max << ", " << *Limit << "\n");
+        //TODO: insert check
+        return insertCheck(OffsetP, Limit, I);
+    }
+
+    bool validateAccess(Value *Pointer, unsigned size, Instruction *I)
+    {
+      return validateAccess(Pointer,
+                            ConstantInt::get(Type::getInt32Ty(Pointer->getContext()),
+                                             size), I);
+    }
+
+  };
+  char PtrVerifier::ID;
+
+}
+
+llvm::Pass *createClamBCRTChecks()
+{
+  return new PtrVerifier();
+}

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list