diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-23 19:38:39 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-23 19:38:39 +0000 |
commit | e1bfb7ae0dd0762c88e1fd94746e973c37f2e04e (patch) | |
tree | 4409bfc07098e23f4f755fa40fdd501771b88964 /lib/StaticAnalyzer | |
parent | 2ea40c0db7d6e281fad49f8c34335ef04c5b9b84 (diff) |
[analyzer] Migrate ChrootChecker to CheckerV2.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126324 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ChrootChecker.cpp | 43 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ExprEngine.cpp | 20 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 67 |
3 files changed, 101 insertions, 29 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index 36e76d0d3c..b6eef6d150 100644 --- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -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 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; } // 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 @@ bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { 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 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) { 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 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) { } // 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 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { 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 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { return; } + +void ento::registerChrootChecker(CheckerManager &mgr) { + mgr.registerChecker<ChrootChecker>(); +} diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index 01aad7a4be..283f930d4a 100644 --- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp @@ -238,11 +238,25 @@ bool ExprEngine::CheckerEvalCall(const CallExpr *CE, 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; } diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index 0ff29757a6..ba52c4014d 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -66,7 +66,9 @@ static void runPathSensitiveCheckers(CHECK_CTX checkCtx, 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 @@ static void runPathSensitiveCheckers(CHECK_CTX checkCtx, 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 @@ namespace { 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 @@ namespace { 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 @@ namespace { 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 @@ void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 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 @@ void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { EndAnalysisCheckers.push_back(checkfn); } +void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { + EvalCallCheckers.push_back(checkfn); +} + //===----------------------------------------------------------------------===// // Implementation details. //===----------------------------------------------------------------------===// @@ -290,3 +348,6 @@ CheckerManager::~CheckerManager() { // Anchor for the vtable. CheckerProvider::~CheckerProvider() { } + +// Anchor for the vtable. +GraphExpander::~GraphExpander() { } |