23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
29 class StackAddrEscapeChecker :
public Checker< check::PreStmt<ReturnStmt>,
30 check::EndFunction > {
31 mutable std::unique_ptr<BuiltinBug> BT_stackleak;
32 mutable std::unique_ptr<BuiltinBug> BT_returnstack;
39 const Expr *RetE)
const;
56 os <<
"stack memory associated with a compound literal "
59 <<
" returned to caller";
60 range = CL->getSourceRange();
62 else if (
const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
63 const Expr *ARE = AR->getExpr();
65 range = ARE->getSourceRange();
66 os <<
"stack memory allocated by call to alloca() on line "
70 const BlockDecl *BD = BR->getCodeRegion()->getDecl();
73 os <<
"stack-allocated block declared on line "
76 else if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
77 os <<
"stack memory associated with local variable '"
78 << VR->getString() <<
'\'';
79 range = VR->getDecl()->getSourceRange();
82 QualType Ty = TOR->getValueType().getLocalUnqualifiedType();
83 os <<
"stack memory associated with temporary object of type '";
86 range = TOR->getExpr()->getSourceRange();
89 llvm_unreachable(
"Invalid region in ReturnStackAddressChecker.");
96 const Expr *RetE)
const {
103 BT_returnstack.reset(
104 new BuiltinBug(
this,
"Return of address to stack-allocated memory"));
108 llvm::raw_svector_ostream os(buf);
110 os <<
" returned to caller";
111 auto report = llvm::make_unique<BugReport>(*BT_returnstack, os.str(), N);
112 report->addRange(RetE->getSourceRange());
114 report->addRange(range);
119 void StackAddrEscapeChecker::checkPreStmt(
const ReturnStmt *RS,
143 if (MemFrame != CurFrame)
148 isa<BlockDataRegion>(R))
155 RetE = Cleanup->getSubExpr();
159 EmitStackError(C, R, RetE);
162 void StackAddrEscapeChecker::checkEndFunction(
CheckerContext &Ctx)
const {
176 CurSFC(CC.getLocationContext()->getCurrentStackFrame())
192 isa<BlockDataRegion>(vR))
199 if (SSR->getStackFrame() == CurSFC)
200 V.push_back(std::make_pair(region, vR));
208 state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
220 new BuiltinBug(
this,
"Stack address stored into global variable",
221 "Stack address was saved into a global variable. "
222 "This is dangerous because the address will become "
223 "invalid after returning from the function"));
225 for (
unsigned i = 0, e = cb.V.size(); i != e; ++i) {
228 llvm::raw_svector_ostream os(buf);
230 os <<
" is still referred to by the global variable '";
231 const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
233 <<
"' upon returning to the caller. This will be a dangling reference";
234 auto report = llvm::make_unique<BugReport>(*BT_stackleak, os.str(), N);
236 report->addRange(range);
MemRegion - The root abstract class for all memory regions.
Defines the SourceManager interface.
bool isRecordType() const
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
const MemRegion * getBaseRegion() const
Defines the clang::Expr interface and subclasses for C++ expressions.
const MemSpaceRegion * getMemorySpace() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const VarDecl * getDecl() const
const LangOptions & getLangOpts() const
const StackFrameContext * getStackFrame() const
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
const ProgramStateRef & getState() const
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine()) const
const clang::PrintingPolicy & getPrintingPolicy() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocStart() const LLVM_READONLY
CHECKER * registerChecker()
Used to register checkers.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
const StackFrameContext * getCurrentStackFrame() const
ASTContext & getASTContext()
const MemRegion * getAsRegion() const
const Expr * getRetValue() const
SourceManager & getSourceManager()
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
A trivial tuple used to represent a source range.
This class handles loading and caching of source files into memory.
Expr * IgnoreParens() LLVM_READONLY
const LocationContext * getLocationContext() const