Skip to content

Commit 2ca9d38

Browse files
committed
[analyzer] Conversion to CheckerFamily: StackAddrEscapeChecker
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 1a3e857 commit 2ca9d38

File tree

4 files changed

+36
-66
lines changed

4 files changed

+36
-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: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,20 @@ 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"; }
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

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

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

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

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)