aboutsummaryrefslogtreecommitdiff
path: root/lib/Checker/StackAddrLeakChecker.cpp
diff options
context:
space:
mode:
authorZhongxing Xu <xuzhongxing@gmail.com>2010-06-09 06:08:24 +0000
committerZhongxing Xu <xuzhongxing@gmail.com>2010-06-09 06:08:24 +0000
commit9b1468311d625ac8920adda5440ce8ffb1a5a5d2 (patch)
tree89879de444f1d8de268f03198edb0981ba2754ac /lib/Checker/StackAddrLeakChecker.cpp
parent2c46458d4cd96a3a33e8810e95e692d8e2e05ff3 (diff)
Merge StackAddrLeakChecker and ReturnStackAddressChecker.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105687 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker/StackAddrLeakChecker.cpp')
-rw-r--r--lib/Checker/StackAddrLeakChecker.cpp93
1 files changed, 88 insertions, 5 deletions
diff --git a/lib/Checker/StackAddrLeakChecker.cpp b/lib/Checker/StackAddrLeakChecker.cpp
index 8aa359e49e..5e6058ddc2 100644
--- a/lib/Checker/StackAddrLeakChecker.cpp
+++ b/lib/Checker/StackAddrLeakChecker.cpp
@@ -14,29 +14,112 @@
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
-#include "clang/Checker/PathSensitive/Checker.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRState.h"
-
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
namespace {
-class StackAddrLeakChecker : public Checker {
+class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> {
BuiltinBug *BT_stackleak;
+ BuiltinBug *BT_returnstack;
public:
- StackAddrLeakChecker() : BT_stackleak(0) {}
+ StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {}
static void *getTag() {
static int x;
return &x;
}
-
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
+private:
+ void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
};
}
void clang::RegisterStackAddrLeakChecker(GRExprEngine &Eng) {
Eng.registerCheck(new StackAddrLeakChecker());
}
+void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) {
+ ExplodedNode *N = C.GenerateSink();
+
+ if (!N)
+ return;
+
+ if (!BT_returnstack)
+ BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory");
+
+ // Generate a report for this bug.
+ llvm::SmallString<512> buf;
+ llvm::raw_svector_ostream os(buf);
+ SourceRange range;
+
+ // Get the base region, stripping away fields and elements.
+ R = R->getBaseRegion();
+
+ // Check if the region is a compound literal.
+ if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
+ const CompoundLiteralExpr* CL = CR->getLiteralExpr();
+ os << "Address of stack memory associated with a compound literal "
+ "declared on line "
+ << C.getSourceManager().getInstantiationLineNumber(CL->getLocStart())
+ << " returned to caller";
+ range = CL->getSourceRange();
+ }
+ else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
+ const Expr* ARE = AR->getExpr();
+ SourceLocation L = ARE->getLocStart();
+ range = ARE->getSourceRange();
+ os << "Address of stack memory allocated by call to alloca() on line "
+ << C.getSourceManager().getInstantiationLineNumber(L)
+ << " returned to caller";
+ }
+ else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
+ const BlockDecl *BD = BR->getCodeRegion()->getDecl();
+ SourceLocation L = BD->getLocStart();
+ range = BD->getSourceRange();
+ os << "Address of stack-allocated block declared on line "
+ << C.getSourceManager().getInstantiationLineNumber(L)
+ << " returned to caller";
+ }
+ else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << "Address of stack memory associated with local variable '"
+ << VR->getString() << "' returned";
+ range = VR->getDecl()->getSourceRange();
+ }
+ else {
+ assert(false && "Invalid region in ReturnStackAddressChecker.");
+ return;
+ }
+
+ RangedBugReport *report = new RangedBugReport(*BT_returnstack, os.str(), N);
+ report->addRange(RetE->getSourceRange());
+ if (range.isValid())
+ report->addRange(range);
+
+ C.EmitReport(report);
+}
+
+void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ SVal V = C.getState()->getSVal(RetE);
+ const MemRegion *R = V.getAsRegion();
+
+ if (!R || !R->hasStackStorage())
+ return;
+
+ if (R->hasStackStorage()) {
+ EmitStackError(C, R, RetE);
+ return;
+ }
+}
void StackAddrLeakChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {