-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[clang][analyzer] Split NullDereferenceChecker into modeling and reporting #122139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,12 +33,6 @@ class DereferenceChecker | |
| EventDispatcher<ImplicitNullDerefEvent> > { | ||
| enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel }; | ||
|
|
||
| BugType BT_Null{this, "Dereference of null pointer", categories::LogicError}; | ||
| BugType BT_Undef{this, "Dereference of undefined pointer value", | ||
| categories::LogicError}; | ||
| BugType BT_Label{this, "Dereference of the address of a label", | ||
| categories::LogicError}; | ||
|
|
||
| void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S, | ||
| CheckerContext &C) const; | ||
|
|
||
|
|
@@ -56,6 +50,12 @@ class DereferenceChecker | |
| bool loadedFrom = false); | ||
|
|
||
| bool SuppressAddressSpaces = false; | ||
|
|
||
| bool CheckNullDereference = false; | ||
|
|
||
| std::unique_ptr<BugType> BT_Null; | ||
| std::unique_ptr<BugType> BT_Undef; | ||
| std::unique_ptr<BugType> BT_Label; | ||
| }; | ||
| } // end anonymous namespace | ||
|
|
||
|
|
@@ -155,22 +155,27 @@ static bool isDeclRefExprToReference(const Expr *E) { | |
|
|
||
| void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State, | ||
| const Stmt *S, CheckerContext &C) const { | ||
| if (!CheckNullDereference) { | ||
| C.addSink(); | ||
steakhal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return; | ||
| } | ||
|
|
||
| const BugType *BT = nullptr; | ||
| llvm::StringRef DerefStr1; | ||
| llvm::StringRef DerefStr2; | ||
| switch (K) { | ||
| case DerefKind::NullPointer: | ||
| BT = &BT_Null; | ||
| BT = BT_Null.get(); | ||
| DerefStr1 = " results in a null pointer dereference"; | ||
| DerefStr2 = " results in a dereference of a null pointer"; | ||
| break; | ||
| case DerefKind::UndefinedPointerValue: | ||
| BT = &BT_Undef; | ||
| BT = BT_Undef.get(); | ||
| DerefStr1 = " results in an undefined pointer dereference"; | ||
| DerefStr2 = " results in a dereference of an undefined pointer value"; | ||
| break; | ||
| case DerefKind::AddressOfLabel: | ||
| BT = &BT_Label; | ||
| BT = BT_Label.get(); | ||
| DerefStr1 = " results in an undefined pointer dereference"; | ||
| DerefStr2 = " results in a dereference of an address of a label"; | ||
| break; | ||
|
|
@@ -351,12 +356,30 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, | |
| C.addTransition(State, this); | ||
| } | ||
|
|
||
| void ento::registerDereferenceChecker(CheckerManager &mgr) { | ||
| auto *Chk = mgr.registerChecker<DereferenceChecker>(); | ||
| Chk->SuppressAddressSpaces = mgr.getAnalyzerOptions().getCheckerBooleanOption( | ||
| mgr.getCurrentCheckerName(), "SuppressAddressSpaces"); | ||
| void ento::registerDereferenceModeling(CheckerManager &Mgr) { | ||
| Mgr.registerChecker<DereferenceChecker>(); | ||
| } | ||
|
|
||
| bool ento::shouldRegisterDereferenceModeling(const CheckerManager &Mgr) { | ||
steakhal marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return true; | ||
| } | ||
|
|
||
| void ento::registerNullDereferenceChecker(CheckerManager &Mgr) { | ||
| auto *Chk = Mgr.getChecker<DereferenceChecker>(); | ||
| Chk->CheckNullDereference = true; | ||
| Chk->SuppressAddressSpaces = Mgr.getAnalyzerOptions().getCheckerBooleanOption( | ||
| Mgr.getCurrentCheckerName(), "SuppressAddressSpaces"); | ||
| Chk->BT_Null.reset(new BugType(Mgr.getCurrentCheckerName(), | ||
| "Dereference of null pointer", | ||
| categories::LogicError)); | ||
| Chk->BT_Undef.reset(new BugType(Mgr.getCurrentCheckerName(), | ||
| "Dereference of undefined pointer value", | ||
| categories::LogicError)); | ||
| Chk->BT_Label.reset(new BugType(Mgr.getCurrentCheckerName(), | ||
| "Dereference of the address of a label", | ||
|
Comment on lines
+372
to
+379
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a pity that this commit reintroduces this dynamic initialization boilerplate. We should really introduce a clear framework for supporting bug types in a checker class that implements multiple sub-checkers... (This is just a general long-term complaint, your change is probably the best possible short-term solution...) |
||
| categories::LogicError)); | ||
| } | ||
|
|
||
| bool ento::shouldRegisterDereferenceChecker(const CheckerManager &mgr) { | ||
| bool ento::shouldRegisterNullDereferenceChecker(const CheckerManager &Mgr) { | ||
steakhal marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return true; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is
HasDocumentationcompatible withHidden? My understanding was thatHiddencheckers are purely implementation details and they don't have their separate documentation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably
NotDocumentedis better, I updated it. The code was copied from another example in the file, probablyCallAndMessageModelingwhere stillHasDocumentationis used (but it has no documentation).