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

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

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

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

@ -13,9 +13,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/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
@ -23,33 +24,22 @@ using namespace clang;
using namespace ento;
namespace {
class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> {
BuiltinBug *BT_stackleak;
BuiltinBug *BT_returnstack;
class StackAddrLeakChecker : public CheckerV2< check::PreStmt<ReturnStmt>,
check::EndPath > {
mutable llvm::OwningPtr<BuiltinBug> BT_stackleak;
mutable llvm::OwningPtr<BuiltinBug> BT_returnstack;
public:
StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {}
static void *getTag() {
static int x;
return &x;
}
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
private:
void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
void EmitStackError(CheckerContext &C, const MemRegion *R,
const Expr *RetE) const;
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,
const MemRegion *R,
SourceManager &SM) {
@ -94,14 +84,15 @@ SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
}
void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
const Expr *RetE) {
const Expr *RetE) const {
ExplodedNode *N = C.generateSink();
if (!N)
return;
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.
llvm::SmallString<512> buf;
@ -116,8 +107,8 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
C.EmitReport(report);
}
void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
const ReturnStmt *RS) {
void StackAddrLeakChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const {
const Expr *RetE = RS->getRetValue();
if (!RetE)
@ -135,8 +126,8 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
}
}
void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
ExprEngine &Eng) {
void StackAddrLeakChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
ExprEngine &Eng) const {
const GRState *state = B.getState();
@ -185,11 +176,11 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
return;
if (!BT_stackleak)
BT_stackleak =
BT_stackleak.reset(
new BuiltinBug("Stack address stored into global variable",
"Stack address was saved into a global variable. "
"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) {
// Generate a report for this bug.
@ -208,3 +199,7 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
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);
}
/// \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.
/// Only one checker will evaluate the call.
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
@ -310,6 +320,10 @@ void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
EndAnalysisCheckers.push_back(checkfn);
}
void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
EndPathCheckers.push_back(checkfn);
}
void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
EvalCallCheckers.push_back(checkfn);
}