@@ -28,23 +28,20 @@ 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" ; }
4537
46- bool ChecksEnabled[CK_NumCheckKinds] = {false };
47- CheckerNameRef CheckNames[CK_NumCheckKinds];
38+ CheckerFrontend StackAddrEscape, StackAddrAsyncEscape;
39+ const BugType StackLeak{&StackAddrEscape,
40+ " Stack address leaks outside of stack frame" };
41+ const BugType ReturnStack{&StackAddrEscape,
42+ " Return of address to stack-allocated memory" };
43+ const BugType CapturedStackAsync{
44+ &StackAddrAsyncEscape, " Address of stack-allocated memory is captured" };
4845
4946 void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
5047 void checkPreStmt (const ReturnStmt *RS, CheckerContext &C) const ;
@@ -170,10 +167,6 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
170167 ExplodedNode *N = C.generateNonFatalErrorNode ();
171168 if (!N)
172169 return ;
173- if (!BT_returnstack)
174- BT_returnstack = std::make_unique<BugType>(
175- CheckNames[CK_StackAddrEscapeChecker],
176- " Return of address to stack-allocated memory" );
177170
178171 // Generate a report for this bug.
179172 SmallString<128 > buf;
@@ -184,7 +177,7 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C,
184177 EmitReturnedAsPartOfError (os, C.getSVal (RetE), R);
185178
186179 auto report =
187- std::make_unique<PathSensitiveBugReport>(*BT_returnstack , os.str (), N);
180+ std::make_unique<PathSensitiveBugReport>(ReturnStack , os.str (), N);
188181 report->addRange (RetE->getSourceRange ());
189182 if (range.isValid ())
190183 report->addRange (range);
@@ -215,16 +208,12 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
215208 ExplodedNode *N = C.generateNonFatalErrorNode ();
216209 if (!N)
217210 continue ;
218- if (!BT_capturedstackasync)
219- BT_capturedstackasync = std::make_unique<BugType>(
220- CheckNames[CK_StackAddrAsyncEscapeChecker],
221- " Address of stack-allocated memory is captured" );
222211 SmallString<128 > Buf;
223212 llvm::raw_svector_ostream Out (Buf);
224213 SourceRange Range = genName (Out, Region, C.getASTContext ());
225214 Out << " is captured by an asynchronously-executed block" ;
226- auto Report = std::make_unique<PathSensitiveBugReport>(
227- *BT_capturedstackasync, Out.str (), N);
215+ auto Report = std::make_unique<PathSensitiveBugReport>(CapturedStackAsync,
216+ Out.str (), N);
228217 if (Range.isValid ())
229218 Report->addRange (Range);
230219 C.emitReport (std::move (Report));
@@ -233,7 +222,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
233222
234223void StackAddrEscapeChecker::checkPreCall (const CallEvent &Call,
235224 CheckerContext &C) const {
236- if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker] )
225+ if (!StackAddrAsyncEscape. isEnabled () )
237226 return ;
238227 if (!Call.isGlobalCFunction (" dispatch_after" ) &&
239228 !Call.isGlobalCFunction (" dispatch_async" ))
@@ -357,7 +346,7 @@ FindEscapingStackRegions(CheckerContext &C, const Expr *RetE, SVal RetVal) {
357346
358347void StackAddrEscapeChecker::checkPreStmt (const ReturnStmt *RS,
359348 CheckerContext &C) const {
360- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
349+ if (!StackAddrEscape. isEnabled () )
361350 return ;
362351
363352 const Expr *RetE = RS->getRetValue ();
@@ -456,7 +445,7 @@ static bool isInvalidatedSymbolRegion(const MemRegion *Region) {
456445
457446void StackAddrEscapeChecker::checkEndFunction (const ReturnStmt *RS,
458447 CheckerContext &Ctx) const {
459- if (!ChecksEnabled[CK_StackAddrEscapeChecker] )
448+ if (!StackAddrEscape. isEnabled () )
460449 return ;
461450
462451 ExplodedNode *Node = Ctx.getPredecessor ();
@@ -581,11 +570,6 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
581570 if (!N)
582571 return ;
583572
584- if (!BT_stackleak)
585- BT_stackleak =
586- std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
587- " Stack address leaks outside of stack frame" );
588-
589573 for (const auto &P : Cb.V) {
590574 const MemRegion *Referrer = P.first ->getBaseRegion ();
591575 const MemRegion *Referred = P.second ;
@@ -604,7 +588,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
604588 Out << " is still referred to by a temporary object on the stack"
605589 << CommonSuffix;
606590 auto Report =
607- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
591+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
608592 if (Range.isValid ())
609593 Report->addRange (Range);
610594 Ctx.emitReport (std::move (Report));
@@ -618,31 +602,22 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
618602
619603 Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
620604 auto Report =
621- std::make_unique<PathSensitiveBugReport>(*BT_stackleak , Out.str (), N);
605+ std::make_unique<PathSensitiveBugReport>(StackLeak , Out.str (), N);
622606 if (Range.isValid ())
623607 Report->addRange (Range);
624608
625609 Ctx.emitReport (std::move (Report));
626610 }
627611}
628612
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 (); \
613+ #define REGISTER_CHECKER (NAME ) \
614+ void ento::register ##NAME##Checker(CheckerManager &Mgr) { \
615+ Mgr.getChecker <StackAddrEscapeChecker>()->NAME .enable (Mgr); \
643616 } \
644617 \
645- bool ento::shouldRegister##name (const CheckerManager &mgr) { return true ; }
618+ bool ento::shouldRegister##NAME##Checker (const CheckerManager &) { \
619+ return true ; \
620+ }
646621
647- REGISTER_CHECKER (StackAddrEscapeChecker )
648- REGISTER_CHECKER (StackAddrAsyncEscapeChecker )
622+ REGISTER_CHECKER (StackAddrEscape )
623+ REGISTER_CHECKER (StackAddrAsyncEscape )
0 commit comments