Skip to content

Commit 854cbbf

Browse files
authored
[clang][analyzer] Split NullDereferenceChecker into modeling and reporting (#122139)
The checker currently reports beneath the null dereference dereferences of undefined value and of label addresses. If we want to add more kinds of invalid dereferences (or split the existing functionality) it is more useful to make it separate checkers. To make this possible the existing checker is split into a DereferenceModeling part and a NullDereference checker that actually only switches on the check of null dereference. This is similar architecture as in MallocChecker and CStringChecker. The change is almost NFC but a new (modeling) checker is added. If the NullDereference checker is turned off the found invalid dereferences will still stop the analysis without emitted warning (this is different compared to the old behavior).
1 parent 4e32271 commit 854cbbf

File tree

4 files changed

+47
-16
lines changed

4 files changed

+47
-16
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ def CallAndMessageChecker : Checker<"CallAndMessage">,
206206
Documentation<HasDocumentation>,
207207
Dependencies<[CallAndMessageModeling]>;
208208

209-
def DereferenceChecker : Checker<"NullDereference">,
209+
def DereferenceModeling : Checker<"DereferenceModeling">,
210+
HelpText<"General support for dereference related checkers">,
211+
Documentation<NotDocumented>,
212+
Hidden;
213+
214+
def NullDereferenceChecker : Checker<"NullDereference">,
210215
HelpText<"Check for dereferences of null pointers">,
211216
CheckerOptions<[
212217
CmdLineOption<Boolean,
@@ -215,7 +220,8 @@ def DereferenceChecker : Checker<"NullDereference">,
215220
"true",
216221
Released>
217222
]>,
218-
Documentation<HasDocumentation>;
223+
Documentation<HasDocumentation>,
224+
Dependencies<[DereferenceModeling]>;
219225

220226
def NonNullParamChecker : Checker<"NonNullParamChecker">,
221227
HelpText<"Check for null pointers passed as arguments to a function whose "

clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ class DereferenceChecker
3333
EventDispatcher<ImplicitNullDerefEvent> > {
3434
enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel };
3535

36-
BugType BT_Null{this, "Dereference of null pointer", categories::LogicError};
37-
BugType BT_Undef{this, "Dereference of undefined pointer value",
38-
categories::LogicError};
39-
BugType BT_Label{this, "Dereference of the address of a label",
40-
categories::LogicError};
41-
4236
void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S,
4337
CheckerContext &C) const;
4438

@@ -56,6 +50,12 @@ class DereferenceChecker
5650
bool loadedFrom = false);
5751

5852
bool SuppressAddressSpaces = false;
53+
54+
bool CheckNullDereference = false;
55+
56+
std::unique_ptr<BugType> BT_Null;
57+
std::unique_ptr<BugType> BT_Undef;
58+
std::unique_ptr<BugType> BT_Label;
5959
};
6060
} // end anonymous namespace
6161

@@ -155,22 +155,27 @@ static bool isDeclRefExprToReference(const Expr *E) {
155155

156156
void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State,
157157
const Stmt *S, CheckerContext &C) const {
158+
if (!CheckNullDereference) {
159+
C.addSink();
160+
return;
161+
}
162+
158163
const BugType *BT = nullptr;
159164
llvm::StringRef DerefStr1;
160165
llvm::StringRef DerefStr2;
161166
switch (K) {
162167
case DerefKind::NullPointer:
163-
BT = &BT_Null;
168+
BT = BT_Null.get();
164169
DerefStr1 = " results in a null pointer dereference";
165170
DerefStr2 = " results in a dereference of a null pointer";
166171
break;
167172
case DerefKind::UndefinedPointerValue:
168-
BT = &BT_Undef;
173+
BT = BT_Undef.get();
169174
DerefStr1 = " results in an undefined pointer dereference";
170175
DerefStr2 = " results in a dereference of an undefined pointer value";
171176
break;
172177
case DerefKind::AddressOfLabel:
173-
BT = &BT_Label;
178+
BT = BT_Label.get();
174179
DerefStr1 = " results in an undefined pointer dereference";
175180
DerefStr2 = " results in a dereference of an address of a label";
176181
break;
@@ -351,12 +356,30 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
351356
C.addTransition(State, this);
352357
}
353358

354-
void ento::registerDereferenceChecker(CheckerManager &mgr) {
355-
auto *Chk = mgr.registerChecker<DereferenceChecker>();
356-
Chk->SuppressAddressSpaces = mgr.getAnalyzerOptions().getCheckerBooleanOption(
357-
mgr.getCurrentCheckerName(), "SuppressAddressSpaces");
359+
void ento::registerDereferenceModeling(CheckerManager &Mgr) {
360+
Mgr.registerChecker<DereferenceChecker>();
361+
}
362+
363+
bool ento::shouldRegisterDereferenceModeling(const CheckerManager &) {
364+
return true;
365+
}
366+
367+
void ento::registerNullDereferenceChecker(CheckerManager &Mgr) {
368+
auto *Chk = Mgr.getChecker<DereferenceChecker>();
369+
Chk->CheckNullDereference = true;
370+
Chk->SuppressAddressSpaces = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
371+
Mgr.getCurrentCheckerName(), "SuppressAddressSpaces");
372+
Chk->BT_Null.reset(new BugType(Mgr.getCurrentCheckerName(),
373+
"Dereference of null pointer",
374+
categories::LogicError));
375+
Chk->BT_Undef.reset(new BugType(Mgr.getCurrentCheckerName(),
376+
"Dereference of undefined pointer value",
377+
categories::LogicError));
378+
Chk->BT_Label.reset(new BugType(Mgr.getCurrentCheckerName(),
379+
"Dereference of the address of a label",
380+
categories::LogicError));
358381
}
359382

360-
bool ento::shouldRegisterDereferenceChecker(const CheckerManager &mgr) {
383+
bool ento::shouldRegisterNullDereferenceChecker(const CheckerManager &) {
361384
return true;
362385
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// CHECK-NEXT: core.BitwiseShift
1515
// CHECK-NEXT: core.CallAndMessageModeling
1616
// CHECK-NEXT: core.CallAndMessage
17+
// CHECK-NEXT: core.DereferenceModeling
1718
// CHECK-NEXT: core.DivideZero
1819
// CHECK-NEXT: core.DynamicTypePropagation
1920
// CHECK-NEXT: core.NonNullParamChecker

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// CHECK-NEXT: core.BitwiseShift
2323
// CHECK-NEXT: core.CallAndMessageModeling
2424
// CHECK-NEXT: core.CallAndMessage
25+
// CHECK-NEXT: core.DereferenceModeling
2526
// CHECK-NEXT: core.DivideZero
2627
// CHECK-NEXT: core.DynamicTypePropagation
2728
// CHECK-NEXT: core.NonNullParamChecker

0 commit comments

Comments
 (0)