зеркало из https://github.com/microsoft/clang-1.git
[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:
Родитель
f178ac8b68
Коммит
af5800a1e2
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче