Skip to content

Commit 2b49bb2

Browse files
NagyDonatkrishna2803
authored andcommitted
[analyzer] Conversion to CheckerFamily: StackAddrEscapeChecker (llvm#151136)
This commit converts the class StackAddrEscapeChecker to the checker family framework and slightly simplifies the implementation. This commit is almost NFC, the only technically "functional" change is that it removes the hidden modeling checker `core.StackAddrEscapeBase` which was only relevant as an implementation detail of the old checker registration procedure.
1 parent 51e8aa7 commit 2b49bb2

File tree

4 files changed

+38
-66
lines changed

4 files changed

+38
-66
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,11 @@ def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
233233
HelpText<"Check for undefined results of binary operators">,
234234
Documentation<HasDocumentation>;
235235

236-
def StackAddrEscapeBase : Checker<"StackAddrEscapeBase">,
237-
HelpText<"Generate information about stack address escapes.">,
238-
Documentation<NotDocumented>,
239-
Hidden;
240-
241-
def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
242-
HelpText<"Check that addresses to stack memory do not escape the function">,
243-
Dependencies<[StackAddrEscapeBase]>,
244-
Documentation<HasDocumentation>;
236+
def StackAddrEscapeChecker
237+
: Checker<"StackAddressEscape">,
238+
HelpText<
239+
"Check that addresses to stack memory do not escape the function">,
240+
Documentation<HasDocumentation>;
245241

246242
def DynamicTypePropagation : Checker<"DynamicTypePropagation">,
247243
HelpText<"Generate dynamic type information">,
@@ -295,10 +291,11 @@ def DynamicTypeChecker
295291
Dependencies<[DynamicTypePropagation]>,
296292
Documentation<HasDocumentation>;
297293

298-
def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
299-
HelpText<"Check that addresses to stack memory do not escape the function">,
300-
Dependencies<[StackAddrEscapeBase]>,
301-
Documentation<HasDocumentation>;
294+
def StackAddrAsyncEscapeChecker
295+
: Checker<"StackAddressAsyncEscape">,
296+
HelpText<
297+
"Check that addresses to stack memory do not escape the function">,
298+
Documentation<HasDocumentation>;
302299

303300
def PthreadLockBase : Checker<"PthreadLockBase">,
304301
HelpText<"Helper registering multiple checks.">,

clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,22 @@ using namespace ento;
2828

2929
namespace {
3030
class 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

3935
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;
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

234225
void 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

358349
void 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

457448
void 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)

clang/test/Analysis/analyzer-enabled-checkers.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
// CHECK-NEXT: core.NonNullParamChecker
2121
// CHECK-NEXT: core.NonnilStringConstants
2222
// CHECK-NEXT: core.NullDereference
23-
// CHECK-NEXT: core.StackAddrEscapeBase
2423
// CHECK-NEXT: core.StackAddressEscape
2524
// CHECK-NEXT: core.UndefinedBinaryOperatorResult
2625
// CHECK-NEXT: core.VLASize

clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
// CHECK-NEXT: core.NonNullParamChecker
2929
// CHECK-NEXT: core.NonnilStringConstants
3030
// CHECK-NEXT: core.NullDereference
31-
// CHECK-NEXT: core.StackAddrEscapeBase
3231
// CHECK-NEXT: core.StackAddressEscape
3332
// CHECK-NEXT: core.UndefinedBinaryOperatorResult
3433
// CHECK-NEXT: core.VLASize

0 commit comments

Comments
 (0)