[cfe-commits] r126324 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/CheckerManager.h include/clang/StaticAnalyzer/Core/CheckerV2.h lib/StaticAnalyzer/Checkers/ChrootChecker.cpp lib/StaticAnalyzer/Checkers/ExprEngine.cpp lib/StaticAnalyzer/Core/CheckerManager.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Feb 23 11:38:39 PST 2011


Author: akirtzidis
Date: Wed Feb 23 13:38:39 2011
New Revision: 126324

URL: http://llvm.org/viewvc/llvm-project?rev=126324&view=rev
Log:
[analyzer] Migrate ChrootChecker to CheckerV2.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=126324&r1=126323&r2=126324&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Wed Feb 23 13:38:39 2011
@@ -23,6 +23,7 @@
 namespace clang {
   class Decl;
   class Stmt;
+  class CallExpr;
 
 namespace ento {
   class ExprEngine;
@@ -31,10 +32,17 @@
   class CheckerContext;
   class ObjCMessage;
   class SVal;
+  class ExplodedNode;
   class ExplodedNodeSet;
   class ExplodedGraph;
   class GRState;
 
+class GraphExpander {
+public:
+  virtual ~GraphExpander();
+  virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
+};
+
 struct VoidCheckerFnParm {};
 template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm,
           typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm>
@@ -177,6 +185,12 @@
   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
                                  ExprEngine &Eng);
 
+  /// \brief Run checkers for evaluating a call.
+  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
+                              const ExplodedNodeSet &Src,
+                              const CallExpr *CE, ExprEngine &Eng,
+                              GraphExpander *defaultEval = 0);
+
   // FIXME: Temporary until checker running is moved completely into
   // CheckerManager.
   void registerCheckersToEngine(ExprEngine &eng);
@@ -220,6 +234,19 @@
 
   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
 
+  class EvalCallFunc {
+    typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
+    Func Fn;
+  public:
+    void *Checker;
+    EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+    bool operator()(const CallExpr *CE, CheckerContext &C) {
+      return Fn(Checker, CE, C);
+    } 
+  };
+
+  void _registerForEvalCall(EvalCallFunc checkfn);
+
 //===----------------------------------------------------------------------===//
 // Implementation details.
 //===----------------------------------------------------------------------===//
@@ -287,6 +314,8 @@
   std::vector<CheckLocationFunc> LocationCheckers;
 
   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
+
+  std::vector<EvalCallFunc> EvalCallCheckers;
 };
 
 } // end ento namespace

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h?rev=126324&r1=126323&r2=126324&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h Wed Feb 23 13:38:39 2011
@@ -162,6 +162,24 @@
 
 } // end check namespace
 
+namespace eval {
+
+class Call {
+  template <typename CHECKER>
+  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
+    return ((const CHECKER *)checker)->evalCall(CE, C);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForEvalCall(
+                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
+  }
+};
+
+} // end eval namespace
+
 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp?rev=126324&r1=126323&r2=126324&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp Wed Feb 23 13:38:39 2011
@@ -12,9 +12,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -37,38 +38,30 @@
 //         ROOT_CHANGED<--chdir(..)--      JAIL_ENTERED<--chdir(..)--
 //                                  |                               |
 //                      bug<--foo()--          JAIL_ENTERED<--foo()--
-class ChrootChecker : public CheckerVisitor<ChrootChecker> {
-  IdentifierInfo *II_chroot, *II_chdir;
+class ChrootChecker : public CheckerV2<eval::Call, check::PreStmt<CallExpr> > {
+  mutable IdentifierInfo *II_chroot, *II_chdir;
   // This bug refers to possibly break out of a chroot() jail.
-  BuiltinBug *BT_BreakJail;
+  mutable llvm::OwningPtr<BuiltinBug> BT_BreakJail;
 
 public:
-  ChrootChecker() : II_chroot(0), II_chdir(0), BT_BreakJail(0) {}
+  ChrootChecker() : II_chroot(0), II_chdir(0) {}
   
   static void *getTag() {
     static int x;
     return &x;
   }
   
-  virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
-  virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
 private:
-  void Chroot(CheckerContext &C, const CallExpr *CE);
-  void Chdir(CheckerContext &C, const CallExpr *CE);
+  void Chroot(CheckerContext &C, const CallExpr *CE) const;
+  void Chdir(CheckerContext &C, const CallExpr *CE) const;
 };
 
 } // end anonymous namespace
 
-static void RegisterChrootChecker(ExprEngine &Eng) {
-  Eng.registerCheck(new ChrootChecker());
-}
-
-void ento::registerChrootChecker(CheckerManager &mgr) {
-  mgr.addCheckerRegisterFunction(RegisterChrootChecker);
-}
-
-bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
   const GRState *state = C.getState();
   const Expr *Callee = CE->getCallee();
   SVal L = state->getSVal(Callee);
@@ -94,7 +87,7 @@
   return false;
 }
 
-void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
   const GRState *state = C.getState();
   GRStateManager &Mgr = state->getStateManager();
   
@@ -104,7 +97,7 @@
   C.addTransition(state);
 }
 
-void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
   const GRState *state = C.getState();
   GRStateManager &Mgr = state->getStateManager();
 
@@ -131,7 +124,7 @@
 }
 
 // Check the jail state before any function call except chroot and chdir().
-void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
   const GRState *state = C.getState();
   const Expr *Callee = CE->getCallee();
   SVal L = state->getSVal(Callee);
@@ -155,9 +148,9 @@
     if (isRootChanged((intptr_t) *k))
       if (ExplodedNode *N = C.generateNode()) {
         if (!BT_BreakJail)
-          BT_BreakJail = new BuiltinBug("Break out of jail",
+          BT_BreakJail.reset(new BuiltinBug("Break out of jail",
                                         "No call of chdir(\"/\") immediately "
-                                        "after chroot");
+                                        "after chroot"));
         BugReport *R = new BugReport(*BT_BreakJail, 
                                      BT_BreakJail->getDescription(), N);
         C.EmitReport(R);
@@ -165,3 +158,7 @@
   
   return;
 }
+
+void ento::registerChrootChecker(CheckerManager &mgr) {
+  mgr.registerChecker<ChrootChecker>();
+}

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=126324&r1=126323&r2=126324&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Wed Feb 23 13:38:39 2011
@@ -238,11 +238,25 @@
       DstTmp.clear();
   }
 
-  if (evaluated)
+  if (evaluated) {
     Dst.insert(DstTmp);
-  else
-    Dst.insert(Pred);
+    return evaluated;
+  }
 
+  class DefaultEval : public GraphExpander {
+    bool &Evaluated;
+  public:
+    DefaultEval(bool &evaluated) : Evaluated(evaluated) { }
+    virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+      Evaluated = false;
+      Dst.insert(Pred);
+    }
+  };
+
+  evaluated = true;
+  DefaultEval defaultEval(evaluated);
+  getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this,
+                                             &defaultEval);
   return evaluated;
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=126324&r1=126323&r2=126324&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Wed Feb 23 13:38:39 2011
@@ -66,7 +66,9 @@
                                      ExplodedNodeSet &Dst,
                                      ExplodedNodeSet &Src) {
 
-  if (checkCtx.Checkers.empty()) {
+  typename CHECK_CTX::CheckersTy::const_iterator
+      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
+  if (I == E) {
     Dst.insert(Src);
     return;
   }
@@ -74,8 +76,7 @@
   ExplodedNodeSet Tmp;
   ExplodedNodeSet *PrevSet = &Src;
 
-  for (typename CHECK_CTX::CheckersTy::const_iterator
-         I= checkCtx.Checkers.begin(), E= checkCtx.Checkers.end(); I!=E; ++I) {
+  for (; I != E; ++I) {
     ExplodedNodeSet *CurrSet = 0;
     if (I+1 == E)
       CurrSet = &Dst;
@@ -101,6 +102,9 @@
     const Stmt *S;
     ExprEngine &Eng;
 
+    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
     CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
                      const Stmt *s, ExprEngine &eng)
       : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
@@ -135,6 +139,9 @@
     const ObjCMessage &Msg;
     ExprEngine &Eng;
 
+    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
     CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
                             const ObjCMessage &msg, ExprEngine &eng)
       : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
@@ -173,6 +180,9 @@
     const GRState *State;
     ExprEngine &Eng;
 
+    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
     CheckLocationContext(const CheckersTy &checkers,
                          SVal loc, bool isLoad, const Stmt *s,
                          const GRState *state, ExprEngine &eng)
@@ -207,6 +217,50 @@
     EndAnalysisCheckers[i](G, BR, Eng);
 }
 
+/// \brief Run checkers for evaluating a call.
+/// Only one checker will evaluate the call.
+void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
+                                            const ExplodedNodeSet &Src,
+                                            const CallExpr *CE,
+                                            ExprEngine &Eng,
+                                            GraphExpander *defaultEval) {
+  if (EvalCallCheckers.empty() && defaultEval == 0) {
+    Dst.insert(Src);
+    return;
+  }
+
+  for (ExplodedNodeSet::iterator
+         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
+
+    ExplodedNode *Pred = *NI;
+    bool anyEvaluated = false;
+    for (std::vector<EvalCallFunc>::iterator
+           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
+         EI != EE; ++EI) {
+      ExplodedNodeSet checkDst;
+      CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
+                       ProgramPoint::PostStmtKind, 0, CE);
+      bool evaluated = (*EI)(CE, C);
+      assert(!(evaluated && anyEvaluated)
+             && "There are more than one checkers evaluating the call");
+      if (evaluated) {
+        anyEvaluated = true;
+        Dst.insert(checkDst);
+#ifdef NDEBUG
+        break; // on release don't check that no other checker also evals.
+#endif
+      }
+    }
+    
+    if (!anyEvaluated) {
+      if (defaultEval)
+        defaultEval->expandGraph(Dst, Pred);
+      else
+        Dst.insert(Pred);
+    }
+  }
+}
+
 void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
   for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
     Funcs[i](eng);
@@ -256,6 +310,10 @@
   EndAnalysisCheckers.push_back(checkfn);
 }
 
+void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
+  EvalCallCheckers.push_back(checkfn);
+}
+
 //===----------------------------------------------------------------------===//
 // Implementation details.
 //===----------------------------------------------------------------------===//
@@ -290,3 +348,6 @@
 
 // Anchor for the vtable.
 CheckerProvider::~CheckerProvider() { }
+
+// Anchor for the vtable.
+GraphExpander::~GraphExpander() { }





More information about the cfe-commits mailing list