10class UseAfterLifetimeEnd :
public Checker<check::EndFunction> {
12 void reportDanglingSource(
const MemRegion *Source, SVal Val, ExplodedNode *N,
13 CheckerContext &
C)
const;
14 void checkEndFunction(
const ReturnStmt *RS, CheckerContext &
C)
const;
15 const BugType BugMsg{
this,
"UseAfterLifetimeEnd",
"LifetimeBound"};
20 const MemRegion *SourceRegion;
23 explicit UseAfterLifetimeEndBRVisitor(SVal Val,
const MemRegion *Source)
24 : BoundVal(Val), SourceRegion(Source) {}
26 void Profile(llvm::FoldingSetNodeID &ID)
const override {
30 SourceRegion->Profile(ID);
34 BugReporterContext &BRC,
35 PathSensitiveBugReport &BR)
override;
37 BugReporterContext &BRC,
38 PathSensitiveBugReport &BR)
override;
40 BugReporterContext &BRC,
41 StringRef Message)
const;
49 const CallExpr *
Expr = dyn_cast_or_null<CallExpr>(RetExpr);
60 if (!PVD->hasAttr<LifetimeBoundAttr>())
62 unsigned Idx = PVD->getFunctionScopeIndex();
64 if (Idx >=
Expr->getNumArgs())
68 if (R && R->getBaseRegion() == BaseReg)
69 return Expr->getArg(Idx);
74void UseAfterLifetimeEnd::checkEndFunction(
const ReturnStmt *RS,
86 SVal RetVal =
C.getSVal(RetExpr);
88 std::vector<const MemRegion *> RetValRegion =
90 if (RetValRegion.empty())
94 C.generateNonFatalErrorNode(State,
C.getPredecessor())) {
95 for (
const MemRegion *R : RetValRegion)
96 reportDanglingSource(R, RetVal, N,
C);
101 if (
const auto *VR = dyn_cast_or_null<VarRegion>(Source)) {
102 const VarDecl *VD = VR->getDecl();
108void UseAfterLifetimeEnd::reportDanglingSource(
const MemRegion *Source,
109 SVal RetVal, ExplodedNode *N,
110 CheckerContext &
C)
const {
111 auto BR = std::make_unique<PathSensitiveBugReport>(
113 (llvm::Twine(
"Returning value bound to ") +
120 BR->addVisitor<UseAfterLifetimeEndBRVisitor>(RetVal, Source);
122 C.emitReport(std::move(BR));
126 const ExplodedNode *N, BugReporterContext &BRC, StringRef Message)
const {
131 const Expr *RetExpr = dyn_cast_or_null<Expr>(S);
134 PathDiagnosticLocation Pos;
139 auto Note = std::make_shared<PathDiagnosticEventPiece>(Pos, Message,
true);
141 Note->addRange(Range);
147UseAfterLifetimeEndBRVisitor::VisitNode(
const ExplodedNode *N,
148 BugReporterContext &BRC,
149 PathSensitiveBugReport &BR) {
158 auto Piece = createSourcePiece(
160 (llvm::Twine(
"Value's lifetime bound to the lifetime of ") +
167UseAfterLifetimeEndBRVisitor::getEndPath(
const ExplodedNode *N,
168 BugReporterContext &BRC,
169 PathSensitiveBugReport &BR) {
170 auto Piece = createSourcePiece(
172 (llvm::Twine(
"Lifetime of ") +
178void ento::registerUseAfterLifetimeEnd(CheckerManager &Mgr) {
182bool ento::shouldRegisterUseAfterLifetimeEnd(
const CheckerManager &Mgr) {
static SourceRange getRegionDeclRange(const MemRegion *Source)
static const Expr * getLifetimeBoundArg(const Expr *RetExpr, const MemRegion *Region, const ExplodedNode *N)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getLocation() const
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
ArrayRef< ParmVarDecl * > parameters() const
Represents a parameter to a function.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
A trivial tuple used to represent a source range.
Represents a variable declaration or definition.
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
const ProgramStateRef & getState() const
SVal getSVal(const Expr *E) const
Get the value of an arbitrary expression at this node.
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
const MemRegion * getAsRegion() const
void trackStoredValue(SVal V, const MemRegion *R, PathSensitiveBugReport &Report, TrackingOptions Opts={}, const StackFrame *Origin=nullptr)
Track how the value got stored into the given region and where it came from.
std::string getRegionName(const MemRegion *Reg)
Returns the descriptive name of the memory region or a placeholder if a descriptive name cannot be co...
bool isBoundToLifetimeSource(ProgramStateRef State, SVal Val)
Returns true if Val is a key in the LifetimeBoundMap.
std::vector< const MemRegion * > getDanglingRegionsAfterReturn(SVal Source, ProgramStateRef State, CheckerContext &C)
Returns the set of lifetime sources bound to Source that are dangling stack regions.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
Top level wrappers for InstallAPI frontend operations.