clang 24.0.0git
ReportDanglingPtrDeref.cpp
Go to the documentation of this file.
1#include "LifetimeModeling.h"
7
8using namespace clang;
9using namespace ento;
10
11namespace {
12class DanglingPtrDeref : public Checker<check::Location> {
13public:
14 void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
15 CheckerContext &C) const;
16 void reportUseAfterScope(const MemRegion *Region, ExplodedNode *N,
17 CheckerContext &C) const;
18 const BugType BugMsg{this, "ReportDanglingPtrDeref", "LifetimeBound"};
19};
20
21class DanglingPtrDerefBRVisitor : public BugReporterVisitor {
22 const MemRegion *SourceRegion;
23
24public:
25 explicit DanglingPtrDerefBRVisitor(const MemRegion *Source)
26 : SourceRegion(Source) {}
27
28 void Profile(llvm::FoldingSetNodeID &ID) const override {
29 ID.AddPointer(SourceRegion);
30 }
31
32 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
33 BugReporterContext &BRC,
34 PathSensitiveBugReport &BR) override;
35};
36
37} // namespace
38
39void DanglingPtrDeref::checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
40 CheckerContext &C) const {
41 ProgramStateRef State = C.getState();
42
43 if (const MemRegion *LocRegion = Loc.getAsRegion()) {
44 if (lifetime_modeling::isDeallocated(State, LocRegion)) {
45 if (ExplodedNode *N = C.generateNonFatalErrorNode(State))
46 reportUseAfterScope(LocRegion, N, C);
47 }
48 }
49}
50
51void DanglingPtrDeref::reportUseAfterScope(const MemRegion *Region,
52 ExplodedNode *N,
53 CheckerContext &C) const {
54 auto BR = std::make_unique<PathSensitiveBugReport>(
55 BugMsg,
56 (llvm::Twine("Use of '") + Region->getString() +
57 "' after its lifetime ended."),
58 N);
59 BR->addVisitor<DanglingPtrDerefBRVisitor>(Region);
60 C.emitReport(std::move(BR));
61}
62
64DanglingPtrDerefBRVisitor::VisitNode(const ExplodedNode *N,
65 BugReporterContext &BRC,
66 PathSensitiveBugReport &BR) {
68 const ExplodedNode *Pred = N->getFirstPred();
69 if (!Pred)
70 return nullptr;
71
72 if (!isDeallocated(N->getState(), SourceRegion) ||
73 isDeallocated(Pred->getState(), SourceRegion))
74 return nullptr;
75
76 const Stmt *S = N->getStmtForDiagnostics();
77 if (!S)
78 return nullptr;
79
80 PathDiagnosticLocation Pos = PathDiagnosticLocation::createEnd(
81 S, BRC.getSourceManager(), N->getStackFrame());
82 return std::make_shared<PathDiagnosticEventPiece>(
83 Pos,
84 (llvm::Twine("'") + SourceRegion->getString() + "' is destroyed here")
85 .str(),
86 true);
87}
88
89void ento::registerDanglingPtrDeref(CheckerManager &Mgr) {
90 Mgr.registerChecker<DanglingPtrDeref>();
91}
92
93bool ento::shouldRegisterDanglingPtrDeref(const CheckerManager &Mgr) {
94 return true;
95}
Stmt - This represents one statement.
Definition Stmt.h:86
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.
Definition Checker.h:565
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
std::string getString() const
Get a string representation of a region for debug use.
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const StackFrameOrAnalysisDeclContext SFAC)
Create a location for the end of the statement.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:57
const MemRegion * getAsRegion() const
Definition SVals.cpp:119
bool isDeallocated(ProgramStateRef State, const MemRegion *Region)
Returns true if the underlying MemRegion is deallocated.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.