@@ -28,23 +28,22 @@ using namespace ento;
28
28
29
29
namespace {
30
30
class StackAddrEscapeChecker
31
- : public Checker <check::PreCall, check::PreStmt<ReturnStmt>,
32
- check::EndFunction> {
31
+ : public CheckerFamily <check::PreCall, check::PreStmt<ReturnStmt>,
32
+ check::EndFunction> {
33
33
mutable IdentifierInfo *dispatch_semaphore_tII = nullptr ;
34
- mutable std::unique_ptr<BugType> BT_stackleak;
35
- mutable std::unique_ptr<BugType> BT_returnstack;
36
- mutable std::unique_ptr<BugType> BT_capturedstackasync;
37
- mutable std::unique_ptr<BugType> BT_capturedstackret;
38
34
39
35
public:
40
- enum CheckKind {
41
- CK_StackAddrEscapeChecker,
42
- CK_StackAddrAsyncEscapeChecker,
43
- CK_NumCheckKinds
44
- };
36
+ StringRef getDebugTag () const override { return " StackAddrEscapeChecker" ; }
37
+
38
+ CheckerFrontend StackAddrEscape;
39
+ CheckerFrontend StackAddrAsyncEscape;
45
40
46
- bool ChecksEnabled[CK_NumCheckKinds] = {false };
47
- CheckerNameRef CheckNames[CK_NumCheckKinds];
41
+ const BugType StackLeak{&StackAddrEscape,
42
+ " Stack address leaks outside of stack frame" };
43
+ const BugType ReturnStack{&StackAddrEscape,
44
+ " Return of address to stack-allocated memory" };
45
+ const BugType CapturedStackAsync{
46
+ &StackAddrAsyncEscape, " Address of stack-allocated memory is captured" };
48
47
49
48
void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
50
49
void checkPreStmt (const ReturnStmt *RS, CheckerContext &C) const ;
@@ -170,10 +169,6 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
170
169
ExplodedNode *N = C.generateNonFatalErrorNode ();
171
170
if (!N)
172
171
return ;
173
- if (!BT_returnstack)
174
- BT_returnstack = std::make_unique<BugType>(
175
- CheckNames[CK_StackAddrEscapeChecker],
176
- " Return of address to stack-allocated memory" );
177
172
178
173
// Generate a report for this bug.
179
174
SmallString<128 > buf;
@@ -184,7 +179,7 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
184
179
EmitReturnedAsPartOfError (os, C.getSVal (RetE), R);
185
180
186
181
auto report =
187
- std::make_unique<PathSensitiveBugReport>(*BT_returnstack , os.str (), N);
182
+ std::make_unique<PathSensitiveBugReport>(ReturnStack , os.str (), N);
188
183
report->addRange (RetE->getSourceRange ());
189
184
if (range.isValid ())
190
185
report->addRange (range);
@@ -215,16 +210,12 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
215
210
ExplodedNode *N = C.generateNonFatalErrorNode ();
216
211
if (!N)
217
212
continue ;
218
- if (!BT_capturedstackasync)
219
- BT_capturedstackasync = std::make_unique<BugType>(
220
- CheckNames[CK_StackAddrAsyncEscapeChecker],
221
- " Address of stack-allocated memory is captured" );
222
213
SmallString<128 > Buf;
223
214
llvm::raw_svector_ostream Out (Buf);
224
215
SourceRange Range = genName (Out, Region, C.getASTContext ());
225
216
Out << " is captured by an asynchronously-executed block" ;
226
- auto Report = std::make_unique<PathSensitiveBugReport>(
227
- *BT_capturedstackasync, Out.str (), N);
217
+ auto Report = std::make_unique<PathSensitiveBugReport>(CapturedStackAsync,
218
+ Out.str (), N);
228
219
if (Range.isValid ())
229
220
Report->addRange (Range);
230
221
C.emitReport (std::move (Report));
@@ -233,7 +224,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
233
224
234
225
void StackAddrEscapeChecker::checkPreCall (const CallEvent &Call,
235
226
CheckerContext &C) const {
236
- if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker] )
227
+ if (!StackAddrAsyncEscape. isEnabled () )
237
228
return ;
238
229
if (!Call.isGlobalCFunction (" dispatch_after" ) &&
239
230
!Call.isGlobalCFunction (" dispatch_async" ))
@@ -357,7 +348,7 @@ FindEscapingStackRegions(CheckerContext &C, const Expr *RetE, SVal RetVal) {
357
348
358
349
void StackAddrEscapeChecker::checkPreStmt (const ReturnStmt *RS,
359
350
CheckerContext &C) const {
360
- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
351
+ if (!StackAddrEscape. isEnabled () )
361
352
return ;
362
353
363
354
const Expr *RetE = RS->getRetValue ();
@@ -456,7 +447,7 @@ static bool isInvalidatedSymbolRegion(const MemRegion *Region) {
456
447
457
448
void StackAddrEscapeChecker::checkEndFunction (const ReturnStmt *RS,
458
449
CheckerContext &Ctx) const {
459
- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
450
+ if (!StackAddrEscape. isEnabled () )
460
451
return ;
461
452
462
453
ExplodedNode *Node = Ctx.getPredecessor ();
@@ -581,11 +572,6 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
581
572
if (!N)
582
573
return ;
583
574
584
- if (!BT_stackleak)
585
- BT_stackleak =
586
- std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
587
- " Stack address leaks outside of stack frame" );
588
-
589
575
for (const auto &P : Cb.V) {
590
576
const MemRegion *Referrer = P.first ->getBaseRegion ();
591
577
const MemRegion *Referred = P.second ;
@@ -604,7 +590,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
604
590
Out << " is still referred to by a temporary object on the stack"
605
591
<< CommonSuffix;
606
592
auto Report =
607
- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
593
+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
608
594
if (Range.isValid ())
609
595
Report->addRange (Range);
610
596
Ctx.emitReport (std::move (Report));
@@ -618,31 +604,22 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
618
604
619
605
Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
620
606
auto Report =
621
- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
607
+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
622
608
if (Range.isValid ())
623
609
Report->addRange (Range);
624
610
625
611
Ctx.emitReport (std::move (Report));
626
612
}
627
613
}
628
614
629
- void ento::registerStackAddrEscapeBase (CheckerManager &mgr) {
630
- mgr.registerChecker <StackAddrEscapeChecker>();
631
- }
632
-
633
- bool ento::shouldRegisterStackAddrEscapeBase (const CheckerManager &mgr) {
634
- return true ;
635
- }
636
-
637
- #define REGISTER_CHECKER (name ) \
638
- void ento::register ##name (CheckerManager &Mgr) { \
639
- StackAddrEscapeChecker *Chk = Mgr.getChecker <StackAddrEscapeChecker>(); \
640
- Chk->ChecksEnabled [StackAddrEscapeChecker::CK_##name] = true ; \
641
- Chk->CheckNames [StackAddrEscapeChecker::CK_##name] = \
642
- Mgr.getCurrentCheckerName (); \
615
+ #define REGISTER_CHECKER (NAME ) \
616
+ void ento::register ##NAME##Checker(CheckerManager &Mgr) { \
617
+ Mgr.getChecker <StackAddrEscapeChecker>()->NAME .enable (Mgr); \
643
618
} \
644
619
\
645
- bool ento::shouldRegister##name (const CheckerManager &mgr) { return true ; }
620
+ bool ento::shouldRegister##NAME##Checker (const CheckerManager &) { \
621
+ return true ; \
622
+ }
646
623
647
- REGISTER_CHECKER (StackAddrEscapeChecker )
648
- REGISTER_CHECKER (StackAddrAsyncEscapeChecker )
624
+ REGISTER_CHECKER (StackAddrEscape )
625
+ REGISTER_CHECKER (StackAddrAsyncEscape )
0 commit comments