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();
161 if (
auto *ICE = dyn_cast<ImplicitCastExpr>(RetE)) {
162 if (isa<BlockDataRegion>(R) &&
163 ICE->getCastKind() == CK_CopyAndAutoreleaseBlockObject) {
168 EmitStackError(C, R, RetE);
171 void StackAddrEscapeChecker::checkEndFunction(
CheckerContext &Ctx)
const {
185 CurSFC(CC.getLocationContext()->getCurrentStackFrame())
201 isa<BlockDataRegion>(vR))
208 if (SSR->getStackFrame() == CurSFC)
209 V.push_back(std::make_pair(region, vR));
217 state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
229 new BuiltinBug(
this,
"Stack address stored into global variable",
230 "Stack address was saved into a global variable. "
231 "This is dangerous because the address will become "
232 "invalid after returning from the function"));
234 for (
unsigned i = 0, e = cb.V.size(); i != e; ++i) {
237 llvm::raw_svector_ostream os(buf);
239 os <<
" is still referred to by the ";
240 if (isa<StaticGlobalSpaceRegion>(cb.V[i].first->getMemorySpace()))
245 const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
247 <<
"' upon returning to the caller. This will be a dangling reference";
248 auto report = llvm::make_unique<BugReport>(*BT_stackleak, os.str(), N);
250 report->addRange(range);
CompoundLiteralRegion - A memory region representing a compound literal.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Defines the SourceManager interface.
bool isRecordType() const
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
AllocaRegion - A region that represents an untyped blob of bytes created by a call to 'alloca'...
CompoundLiteralExpr - [C99 6.5.2.5].
const MemRegion * getBaseRegion() const
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
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 ...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
const VarDecl * getDecl() const
BlockDataRegion - A region that represents a block instance.
const LangOptions & getLangOpts() const
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
const StackFrameContext * getStackFrame() const
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Expr - This represents one expression.
const ProgramStateRef & getState() const
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
const clang::PrintingPolicy & getPrintingPolicy() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
SourceLocation getLocStart() const LLVM_READONLY
CHECKER * registerChecker()
Used to register checkers.
Encodes a location in the source.
const StackFrameContext * getCurrentStackFrame() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
ASTContext & getASTContext()
const MemRegion * getAsRegion() const
const Expr * getRetValue() const
SourceManager & getSourceManager()
SourceRange getSourceRange() const override LLVM_READONLY
A trivial tuple used to represent a source range.
This class handles loading and caching of source files into memory.
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.
const LocationContext * getLocationContext() const