[analyzer] Migrate StackAddrLeakChecker to CheckerV2.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126333 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Argyrios Kyrtzidis 2011-02-23 21:04:54 +00:00
Родитель f178ac8b68
Коммит af5800a1e2
5 изменённых файлов: 64 добавлений и 30 удалений

Просмотреть файл

@ -36,6 +36,7 @@ namespace ento {
class ExplodedNodeSet; class ExplodedNodeSet;
class ExplodedGraph; class ExplodedGraph;
class GRState; class GRState;
class EndOfFunctionNodeBuilder;
class GraphExpander { class GraphExpander {
public: public:
@ -186,6 +187,9 @@ public:
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng); ExprEngine &Eng);
/// \brief Run checkers for end of path.
void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
/// \brief Run checkers for evaluating a call. /// \brief Run checkers for evaluating a call.
void runCheckersForEvalCall(ExplodedNodeSet &Dst, void runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src, const ExplodedNodeSet &Src,
@ -221,6 +225,7 @@ public:
CheckLocationFunc; CheckLocationFunc;
typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &> typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
CheckEndAnalysisFunc; CheckEndAnalysisFunc;
typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
typedef bool (*HandlesStmtFunc)(const Stmt *D); typedef bool (*HandlesStmtFunc)(const Stmt *D);
void _registerForPreStmt(CheckStmtFunc checkfn, void _registerForPreStmt(CheckStmtFunc checkfn,
@ -235,6 +240,8 @@ public:
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
void _registerForEndPath(CheckEndPathFunc checkfn);
class EvalCallFunc { class EvalCallFunc {
typedef bool (*Func)(void *, const CallExpr *, CheckerContext &); typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
Func Fn; Func Fn;
@ -316,6 +323,8 @@ private:
std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
std::vector<CheckEndPathFunc> EndPathCheckers;
std::vector<EvalCallFunc> EvalCallCheckers; std::vector<EvalCallFunc> EvalCallCheckers;
}; };

Просмотреть файл

@ -160,6 +160,21 @@ public:
} }
}; };
class EndPath {
template <typename CHECKER>
static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) {
((const CHECKER *)checker)->checkEndPath(B, Eng);
}
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
mgr._registerForEndPath(
CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
}
};
} // end check namespace } // end check namespace
namespace eval { namespace eval {

Просмотреть файл

@ -1443,6 +1443,7 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag); EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag);
checker->evalEndPath(B, tag, *this); checker->evalEndPath(B, tag, *this);
} }
getCheckerManager().runCheckersForEndPath(builder, *this);
} }
/// ProcessSwitch - Called by CoreEngine. Used to generate successor /// ProcessSwitch - Called by CoreEngine. Used to generate successor

Просмотреть файл

@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "ClangSACheckers.h" #include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.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/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
@ -23,33 +24,22 @@ using namespace clang;
using namespace ento; using namespace ento;
namespace { namespace {
class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> { class StackAddrLeakChecker : public CheckerV2< check::PreStmt<ReturnStmt>,
BuiltinBug *BT_stackleak; check::EndPath > {
BuiltinBug *BT_returnstack; mutable llvm::OwningPtr<BuiltinBug> BT_stackleak;
mutable llvm::OwningPtr<BuiltinBug> BT_returnstack;
public: public:
StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {} void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
static void *getTag() { void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
static int x;
return &x;
}
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
private: private:
void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE); void EmitStackError(CheckerContext &C, const MemRegion *R,
SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R, const Expr *RetE) const;
SourceManager &SM); static SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
SourceManager &SM);
}; };
} }
static void RegisterStackAddrLeakChecker(ExprEngine &Eng) {
Eng.registerCheck(new StackAddrLeakChecker());
}
void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
mgr.addCheckerRegisterFunction(RegisterStackAddrLeakChecker);
}
SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os, SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
const MemRegion *R, const MemRegion *R,
SourceManager &SM) { SourceManager &SM) {
@ -94,14 +84,15 @@ SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
} }
void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R, void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
const Expr *RetE) { const Expr *RetE) const {
ExplodedNode *N = C.generateSink(); ExplodedNode *N = C.generateSink();
if (!N) if (!N)
return; return;
if (!BT_returnstack) if (!BT_returnstack)
BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory"); BT_returnstack.reset(
new BuiltinBug("Return of address to stack-allocated memory"));
// Generate a report for this bug. // Generate a report for this bug.
llvm::SmallString<512> buf; llvm::SmallString<512> buf;
@ -116,8 +107,8 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
C.EmitReport(report); C.EmitReport(report);
} }
void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C, void StackAddrLeakChecker::checkPreStmt(const ReturnStmt *RS,
const ReturnStmt *RS) { CheckerContext &C) const {
const Expr *RetE = RS->getRetValue(); const Expr *RetE = RS->getRetValue();
if (!RetE) if (!RetE)
@ -135,8 +126,8 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
} }
} }
void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, void StackAddrLeakChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) { ExprEngine &Eng) const {
const GRState *state = B.getState(); const GRState *state = B.getState();
@ -185,11 +176,11 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
return; return;
if (!BT_stackleak) if (!BT_stackleak)
BT_stackleak = BT_stackleak.reset(
new BuiltinBug("Stack address stored into global variable", new BuiltinBug("Stack address stored into global variable",
"Stack address was saved into a global variable. " "Stack address was saved into a global variable. "
"This is dangerous because the address will become " "This is dangerous because the address will become "
"invalid after returning from the function"); "invalid after returning from the function"));
for (unsigned i = 0, e = cb.V.size(); i != e; ++i) { for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
// Generate a report for this bug. // Generate a report for this bug.
@ -208,3 +199,7 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
Eng.getBugReporter().EmitReport(report); Eng.getBugReporter().EmitReport(report);
} }
} }
void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
mgr.registerChecker<StackAddrLeakChecker>();
}

Просмотреть файл

@ -217,6 +217,16 @@ void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
EndAnalysisCheckers[i](G, BR, Eng); EndAnalysisCheckers[i](G, BR, Eng);
} }
/// \brief Run checkers for end of path.
void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) {
for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
CheckEndPathFunc fn = EndPathCheckers[i];
EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
fn(specialB, Eng);
}
}
/// \brief Run checkers for evaluating a call. /// \brief Run checkers for evaluating a call.
/// Only one checker will evaluate the call. /// Only one checker will evaluate the call.
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
@ -310,6 +320,10 @@ void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
EndAnalysisCheckers.push_back(checkfn); EndAnalysisCheckers.push_back(checkfn);
} }
void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
EndPathCheckers.push_back(checkfn);
}
void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
EvalCallCheckers.push_back(checkfn); EvalCallCheckers.push_back(checkfn);
} }