@@ -28,23 +28,22 @@ using namespace ento;
2828
2929namespace {
3030class StackAddrEscapeChecker
31- : public Checker <check::PreCall, check::PreStmt<ReturnStmt>,
32- check::EndFunction> {
31+ : public CheckerFamily <check::PreCall, check::PreStmt<ReturnStmt>,
32+ check::EndFunction> {
3333 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;
3834
3935public:
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;
4540
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" };
4847
4948 void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
5049 void checkPreStmt (const ReturnStmt *RS, CheckerContext &C) const ;
@@ -170,10 +169,6 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
170169 ExplodedNode *N = C.generateNonFatalErrorNode ();
171170 if (!N)
172171 return ;
173- if (!BT_returnstack)
174- BT_returnstack = std::make_unique<BugType>(
175- CheckNames[CK_StackAddrEscapeChecker],
176- " Return of address to stack-allocated memory" );
177172
178173 // Generate a report for this bug.
179174 SmallString<128 > buf;
@@ -184,7 +179,7 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
184179 EmitReturnedAsPartOfError (os, C.getSVal (RetE), R);
185180
186181 auto report =
187- std::make_unique<PathSensitiveBugReport>(*BT_returnstack , os.str (), N);
182+ std::make_unique<PathSensitiveBugReport>(ReturnStack , os.str (), N);
188183 report->addRange (RetE->getSourceRange ());
189184 if (range.isValid ())
190185 report->addRange (range);
@@ -215,16 +210,12 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
215210 ExplodedNode *N = C.generateNonFatalErrorNode ();
216211 if (!N)
217212 continue ;
218- if (!BT_capturedstackasync)
219- BT_capturedstackasync = std::make_unique<BugType>(
220- CheckNames[CK_StackAddrAsyncEscapeChecker],
221- " Address of stack-allocated memory is captured" );
222213 SmallString<128 > Buf;
223214 llvm::raw_svector_ostream Out (Buf);
224215 SourceRange Range = genName (Out, Region, C.getASTContext ());
225216 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);
228219 if (Range.isValid ())
229220 Report->addRange (Range);
230221 C.emitReport (std::move (Report));
@@ -233,7 +224,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
233224
234225void StackAddrEscapeChecker::checkPreCall (const CallEvent &Call,
235226 CheckerContext &C) const {
236- if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker] )
227+ if (!StackAddrAsyncEscape. isEnabled () )
237228 return ;
238229 if (!Call.isGlobalCFunction (" dispatch_after" ) &&
239230 !Call.isGlobalCFunction (" dispatch_async" ))
@@ -357,7 +348,7 @@ FindEscapingStackRegions(CheckerContext &C, const Expr *RetE, SVal RetVal) {
357348
358349void StackAddrEscapeChecker::checkPreStmt (const ReturnStmt *RS,
359350 CheckerContext &C) const {
360- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
351+ if (!StackAddrEscape. isEnabled () )
361352 return ;
362353
363354 const Expr *RetE = RS->getRetValue ();
@@ -456,7 +447,7 @@ static bool isInvalidatedSymbolRegion(const MemRegion *Region) {
456447
457448void StackAddrEscapeChecker::checkEndFunction (const ReturnStmt *RS,
458449 CheckerContext &Ctx) const {
459- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
450+ if (!StackAddrEscape. isEnabled () )
460451 return ;
461452
462453 ExplodedNode *Node = Ctx.getPredecessor ();
@@ -581,11 +572,6 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
581572 if (!N)
582573 return ;
583574
584- if (!BT_stackleak)
585- BT_stackleak =
586- std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
587- " Stack address leaks outside of stack frame" );
588-
589575 for (const auto &P : Cb.V) {
590576 const MemRegion *Referrer = P.first ->getBaseRegion ();
591577 const MemRegion *Referred = P.second ;
@@ -604,7 +590,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
604590 Out << " is still referred to by a temporary object on the stack"
605591 << CommonSuffix;
606592 auto Report =
607- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
593+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
608594 if (Range.isValid ())
609595 Report->addRange (Range);
610596 Ctx.emitReport (std::move (Report));
@@ -618,31 +604,22 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
618604
619605 Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
620606 auto Report =
621- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
607+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
622608 if (Range.isValid ())
623609 Report->addRange (Range);
624610
625611 Ctx.emitReport (std::move (Report));
626612 }
627613}
628614
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); \
643618 } \
644619 \
645- bool ento::shouldRegister##name (const CheckerManager &mgr) { return true ; }
620+ bool ento::shouldRegister##NAME##Checker (const CheckerManager &) { \
621+ return true ; \
622+ }
646623
647- REGISTER_CHECKER (StackAddrEscapeChecker )
648- REGISTER_CHECKER (StackAddrAsyncEscapeChecker )
624+ REGISTER_CHECKER (StackAddrEscape )
625+ REGISTER_CHECKER (StackAddrAsyncEscape )
0 commit comments