balazske created this revision. Herald added subscribers: cfe-commits, ASDenysPetrov, martong, Charusso, gamesh411, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun. Herald added a reviewer: Szelethus. Herald added a project: clang.
Report undefined pointer dereference in similar way as null pointer dereference. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D84520 Files: clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp clang/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist clang/test/Analysis/misc-ps-region-store.m clang/test/Analysis/null-deref-offsets.c clang/test/Analysis/null-deref-path-notes.c clang/test/Analysis/null-deref-path-notes.cpp clang/test/Analysis/null-deref-path-notes.m clang/test/Analysis/null-deref-ps.c clang/test/Analysis/silence-checkers-and-packages-core-div-by-zero.cpp
Index: clang/test/Analysis/silence-checkers-and-packages-core-div-by-zero.cpp =================================================================== --- clang/test/Analysis/silence-checkers-and-packages-core-div-by-zero.cpp +++ clang/test/Analysis/silence-checkers-and-packages-core-div-by-zero.cpp @@ -14,5 +14,5 @@ return; int x = p[0]; - // expected-warning@-1 {{Array access (from variable 'p') results in a null pointer dereference}} + // expected-warning@-1 {{Array access (from variable 'p') results in a dereference of a null pointer}} } Index: clang/test/Analysis/null-deref-ps.c =================================================================== --- clang/test/Analysis/null-deref-ps.c +++ clang/test/Analysis/null-deref-ps.c @@ -34,7 +34,7 @@ if (x) return x[i - 1]; - return x[i+1]; // expected-warning{{Array access (from variable 'x') results in a null pointer dereference}} + return x[i+1]; // expected-warning{{Array access (from variable 'x') results in a dereference of a null pointer}} } int f3_b(char* x) { @@ -44,7 +44,7 @@ if (x) return x[i - 1]; - return x[i+1]++; // expected-warning{{Array access (from variable 'x') results in a null pointer dereference}} + return x[i+1]++; // expected-warning{{Array access (from variable 'x') results in a dereference of a null pointer}} } int f4(int *p) { Index: clang/test/Analysis/null-deref-path-notes.m =================================================================== --- clang/test/Analysis/null-deref-path-notes.m +++ clang/test/Analysis/null-deref-path-notes.m @@ -58,8 +58,8 @@ @public int *p; } - (void)useArray { - p[1] = 2; // expected-warning{{Array access (via ivar 'p') results in a null pointer dereference}} - // expected-note@-1{{Array access (via ivar 'p') results in a null pointer dereference}} + p[1] = 2; // expected-warning{{Array access (via ivar 'p') results in a dereference of a null pointer}} + // expected-note@-1{{Array access (via ivar 'p') results in a dereference of a null pointer}} } @end Index: clang/test/Analysis/null-deref-path-notes.cpp =================================================================== --- clang/test/Analysis/null-deref-path-notes.cpp +++ clang/test/Analysis/null-deref-path-notes.cpp @@ -15,8 +15,8 @@ // Properly track the null pointer in the array field back to the default // constructor of 'h'. void c::f(B &g, int &i) { - e(g.d[9], i); // expected-warning{{Array access (via field 'd') results in a null pointer dereference}} - // expected-note@-1{{Array access (via field 'd') results in a null pointer dereference}} + e(g.d[9], i); // expected-warning{{Array access (via field 'd') results in a dereference of a null pointer}} + // expected-note@-1{{Array access (via field 'd') results in a dereference of a null pointer}} B h, a; // expected-note{{Value assigned to 'h.d'}} a.d == __null; // expected-note{{Assuming the condition is true}} a.d != h.d; // expected-note{{Assuming 'a.d' is equal to 'h.d'}} Index: clang/test/Analysis/null-deref-path-notes.c =================================================================== --- clang/test/Analysis/null-deref-path-notes.c +++ clang/test/Analysis/null-deref-path-notes.c @@ -4,8 +4,8 @@ // of the null pointer for path notes. void pr34373() { int *a = 0; // expected-note{{'a' initialized to a null pointer value}} - (a + 0)[0]; // expected-warning{{Array access results in a null pointer dereference}} - // expected-note@-1{{Array access results in a null pointer dereference}} + (a + 0)[0]; // expected-warning{{Array access results in a dereference of a null pointer}} + // expected-note@-1{{Array access results in a dereference of a null pointer}} } typedef __typeof(sizeof(int)) size_t; Index: clang/test/Analysis/null-deref-offsets.c =================================================================== --- clang/test/Analysis/null-deref-offsets.c +++ clang/test/Analysis/null-deref-offsets.c @@ -33,5 +33,5 @@ if (coin) s->y = 5; // expected-warning{{Access to field 'y' results in a dereference of a null pointer (loaded from variable 's')}} else - s->z[1] = 6; // expected-warning{{Array access (via field 'z') results in a null pointer dereference}} + s->z[1] = 6; // expected-warning{{Array access (via field 'z') results in a dereference of a null pointer}} } Index: clang/test/Analysis/misc-ps-region-store.m =================================================================== --- clang/test/Analysis/misc-ps-region-store.m +++ clang/test/Analysis/misc-ps-region-store.m @@ -1157,7 +1157,7 @@ struct list_pr8141 * pr8141 (void) { struct list_pr8141 *items; - for (;; items = ({ do { } while (0); items->tail; })) // expected-warning{{Dereference of undefined pointer value}} + for (;; items = ({ do { } while (0); items->tail; })) // expected-warning{{dereference of an undefined pointer value}} { } } Index: clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist =================================================================== --- clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist +++ clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist @@ -9738,12 +9738,12 @@ </array> <key>depth</key><integer>0</integer> <key>extended_message</key> - <string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> <key>message</key> - <string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> </dict> </array> - <key>description</key><string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <key>description</key><string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> <key>category</key><string>Memory error</string> <key>type</key><string>Dereference of null pointer</string> <key>check_name</key><string>core.NullDereference</string> Index: clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist =================================================================== --- clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist +++ clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist @@ -9738,12 +9738,12 @@ </array> <key>depth</key><integer>0</integer> <key>extended_message</key> - <string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> <key>message</key> - <string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> </dict> </array> - <key>description</key><string>Array access (from variable 'kindC') results in a null pointer dereference</string> + <key>description</key><string>Array access (from variable 'kindC') results in a dereference of a null pointer</string> <key>category</key><string>Memory error</string> <key>type</key><string>Dereference of null pointer</string> <key>check_name</key><string>core.NullDereference</string> Index: clang/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist =================================================================== --- clang/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist +++ clang/test/Analysis/Inputs/expected-plists/null-deref-path-notes.m.plist @@ -986,12 +986,12 @@ </array> <key>depth</key><integer>1</integer> <key>extended_message</key> - <string>Array access (via ivar 'p') results in a null pointer dereference</string> + <string>Array access (via ivar 'p') results in a dereference of a null pointer</string> <key>message</key> - <string>Array access (via ivar 'p') results in a null pointer dereference</string> + <string>Array access (via ivar 'p') results in a dereference of a null pointer</string> </dict> </array> - <key>description</key><string>Array access (via ivar 'p') results in a null pointer dereference</string> + <key>description</key><string>Array access (via ivar 'p') results in a dereference of a null pointer</string> <key>category</key><string>Memory error</string> <key>type</key><string>Dereference of null pointer</string> <key>check_name</key><string>core.NullDereference</string> Index: clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -30,11 +30,14 @@ : public Checker< check::Location, check::Bind, EventDispatcher<ImplicitNullDerefEvent> > { + enum DerefKind { NullPointer, UndefinedPointerValue }; + BugType BT_Null{this, "Dereference of null pointer", categories::MemoryError}; BugType BT_Undef{this, "Dereference of undefined pointer value", categories::MemoryError}; - void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C) const; + void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S, + CheckerContext &C) const; public: void checkLocation(SVal location, bool isLoad, const Stmt* S, @@ -117,8 +120,21 @@ return false; } -void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S, - CheckerContext &C) const { +void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State, + const Stmt *S, CheckerContext &C) const { + const BugType *BT = nullptr; + llvm::StringRef DerefKindStr; + switch (K) { + case DerefKind::NullPointer: + BT = &BT_Null; + DerefKindStr = "dereference of a null pointer"; + break; + case DerefKind::UndefinedPointerValue: + BT = &BT_Undef; + DerefKindStr = "dereference of an undefined pointer value"; + break; + }; + // Generate an error node. ExplodedNode *N = C.generateErrorNode(State); if (!N) @@ -135,7 +151,7 @@ const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S); AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(), State.get(), N->getLocationContext()); - os << " results in a null pointer dereference"; + os << " results in a " << DerefKindStr; break; } case Stmt::OMPArraySectionExprClass: { @@ -143,11 +159,11 @@ const OMPArraySectionExpr *AE = cast<OMPArraySectionExpr>(S); AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(), State.get(), N->getLocationContext()); - os << " results in a null pointer dereference"; + os << " results in a " << DerefKindStr; break; } case Stmt::UnaryOperatorClass: { - os << "Dereference of null pointer"; + os << BT->getDescription(); const UnaryOperator *U = cast<UnaryOperator>(S); AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(), State.get(), N->getLocationContext(), true); @@ -156,8 +172,8 @@ case Stmt::MemberExprClass: { const MemberExpr *M = cast<MemberExpr>(S); if (M->isArrow() || isDeclRefExprToReference(M->getBase())) { - os << "Access to field '" << M->getMemberNameInfo() - << "' results in a dereference of a null pointer"; + os << "Access to field '" << M->getMemberNameInfo() << "' results in a " + << DerefKindStr; AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(), State.get(), N->getLocationContext(), true); } @@ -165,8 +181,8 @@ } case Stmt::ObjCIvarRefExprClass: { const ObjCIvarRefExpr *IV = cast<ObjCIvarRefExpr>(S); - os << "Access to instance variable '" << *IV->getDecl() - << "' results in a dereference of a null pointer"; + os << "Access to instance variable '" << *IV->getDecl() << "' results in a " + << DerefKindStr; AddDerefSource(os, Ranges, IV->getBase()->IgnoreParenCasts(), State.get(), N->getLocationContext(), true); break; @@ -176,7 +192,7 @@ } auto report = std::make_unique<PathSensitiveBugReport>( - BT_Null, buf.empty() ? BT_Null.getDescription() : StringRef(buf), N); + *BT, buf.empty() ? BT->getDescription() : StringRef(buf), N); bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report); @@ -191,12 +207,9 @@ CheckerContext &C) const { // Check for dereference of an undefined value. if (l.isUndef()) { - if (ExplodedNode *N = C.generateErrorNode()) { - auto report = std::make_unique<PathSensitiveBugReport>( - BT_Undef, BT_Undef.getDescription(), N); - bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report); - C.emitReport(std::move(report)); - } + const Expr *DerefExpr = getDereferenceExpr(S); + if (!suppressReport(DerefExpr)) + reportBug(DerefKind::UndefinedPointerValue, C.getState(), DerefExpr, C); return; } @@ -218,7 +231,7 @@ if (!notNullState) { const Expr *expr = getDereferenceExpr(S); if (!suppressReport(expr)) { - reportBug(nullState, expr, C); + reportBug(DerefKind::NullPointer, nullState, expr, C); return; } } @@ -260,7 +273,7 @@ if (!StNonNull) { const Expr *expr = getDereferenceExpr(S, /*IsBind=*/true); if (!suppressReport(expr)) { - reportBug(StNull, expr, C); + reportBug(DerefKind::NullPointer, StNull, expr, C); return; } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits