aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-02-25 22:00:43 +0000
committerTed Kremenek <kremenek@apple.com>2011-02-25 22:00:43 +0000
commitf5d2ef4a61e70eb2bcc3f4872e7095cf19d20163 (patch)
treea065272c1e3bd22b12d223b6d0008f04e913cf94 /lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
parentba90e8a12e6e8889035ed57fb49b40b9cd4ef990 (diff)
Tidy up help text in Checkers.td, and rename StackAddrLeakChecker to StackAddrEscapeChecker.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126522 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp205
1 files changed, 0 insertions, 205 deletions
diff --git a/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
deleted file mode 100644
index e342fe6dfb..0000000000
--- a/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-//=== StackAddrLeakChecker.cpp ------------------------------------*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines stack address leak checker, which checks if an invalid
-// stack address is stored into a global or heap location. See CERT DCL30-C.
-//
-//===----------------------------------------------------------------------===//
-
-#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/GRState.h"
-#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/SmallString.h"
-using namespace clang;
-using namespace ento;
-
-namespace {
-class StackAddrLeakChecker : public CheckerV2< check::PreStmt<ReturnStmt>,
- check::EndPath > {
- mutable llvm::OwningPtr<BuiltinBug> BT_stackleak;
- mutable llvm::OwningPtr<BuiltinBug> BT_returnstack;
-
-public:
- 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) const;
- static SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
- SourceManager &SM);
-};
-}
-
-SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
- const MemRegion *R,
- SourceManager &SM) {
- // Get the base region, stripping away fields and elements.
- R = R->getBaseRegion();
- SourceRange range;
- os << "Address of ";
-
- // Check if the region is a compound literal.
- if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
- const CompoundLiteralExpr* CL = CR->getLiteralExpr();
- os << "stack memory associated with a compound literal "
- "declared on line "
- << SM.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 << "stack memory allocated by call to alloca() on line "
- << SM.getInstantiationLineNumber(L);
- }
- else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
- const BlockDecl *BD = BR->getCodeRegion()->getDecl();
- SourceLocation L = BD->getLocStart();
- range = BD->getSourceRange();
- os << "stack-allocated block declared on line "
- << SM.getInstantiationLineNumber(L);
- }
- else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
- os << "stack memory associated with local variable '"
- << VR->getString() << '\'';
- range = VR->getDecl()->getSourceRange();
- }
- else {
- assert(false && "Invalid region in ReturnStackAddressChecker.");
- }
-
- return range;
-}
-
-void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
- const Expr *RetE) const {
- ExplodedNode *N = C.generateSink();
-
- if (!N)
- return;
-
- if (!BT_returnstack)
- BT_returnstack.reset(
- 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 = GenName(os, R, C.getSourceManager());
- os << " returned to caller";
- RangedBugReport *report = new RangedBugReport(*BT_returnstack, os.str(), N);
- report->addRange(RetE->getSourceRange());
- if (range.isValid())
- report->addRange(range);
-
- C.EmitReport(report);
-}
-
-void StackAddrLeakChecker::checkPreStmt(const ReturnStmt *RS,
- CheckerContext &C) const {
-
- 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::checkEndPath(EndOfFunctionNodeBuilder &B,
- ExprEngine &Eng) const {
-
- const GRState *state = B.getState();
-
- // Iterate over all bindings to global variables and see if it contains
- // a memory region in the stack space.
- class CallBack : public StoreManager::BindingsHandler {
- private:
- const StackFrameContext *CurSFC;
- public:
- llvm::SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V;
-
- CallBack(const LocationContext *LCtx)
- : CurSFC(LCtx->getCurrentStackFrame()) {}
-
- bool HandleBinding(StoreManager &SMgr, Store store,
- const MemRegion *region, SVal val) {
-
- if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
- return true;
-
- const MemRegion *vR = val.getAsRegion();
- if (!vR)
- return true;
-
- if (const StackSpaceRegion *SSR =
- dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
- // If the global variable holds a location in the current stack frame,
- // record the binding to emit a warning.
- if (SSR->getStackFrame() == CurSFC)
- V.push_back(std::make_pair(region, vR));
- }
-
- return true;
- }
- };
-
- CallBack cb(B.getPredecessor()->getLocationContext());
- state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
-
- if (cb.V.empty())
- return;
-
- // Generate an error node.
- ExplodedNode *N = B.generateNode(state);
- if (!N)
- return;
-
- if (!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"));
-
- for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
- // Generate a report for this bug.
- llvm::SmallString<512> buf;
- llvm::raw_svector_ostream os(buf);
- SourceRange range = GenName(os, cb.V[i].second,
- Eng.getContext().getSourceManager());
- os << " is still referred to by the global variable '";
- const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
- os << VR->getDecl()->getNameAsString()
- << "' upon returning to the caller. This will be a dangling reference";
- RangedBugReport *report = new RangedBugReport(*BT_stackleak, os.str(), N);
- if (range.isValid())
- report->addRange(range);
-
- Eng.getBugReporter().EmitReport(report);
- }
-}
-
-void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
- mgr.registerChecker<StackAddrLeakChecker>();
-}