[PATCH] D152269: [StaticAnalyzer] Fix false negative on NilArgChecker when creating literal object

tripleCC via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 6 18:21:07 PDT 2023


tripleCC updated this revision to Diff 529116.
tripleCC added a comment.

[StaticAnalyzer] add might be null test case for NilArgChecker


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152269/new/

https://reviews.llvm.org/D152269

Files:
  clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
  clang/test/Analysis/NSContainers.m


Index: clang/test/Analysis/NSContainers.m
===================================================================
--- clang/test/Analysis/NSContainers.m
+++ clang/test/Analysis/NSContainers.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1  -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s
+// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection,nullability -verify -Wno-objc-root-class %s
 
 void clang_analyzer_eval(int);
 
@@ -323,3 +323,19 @@
   // that 'obj' can be nil in this context.
   dict[obj] = getStringFromString(obj); // no-warning
 }
+
+Foo * _Nonnull getNonnullFoo();
+Foo * _Nullable getNullableFoo();
+Foo * getMightBeNullFoo();
+
+void testCreateDictionaryLiteralWithNullableArg() {
+  (void)@{@"abc" : getMightBeNullFoo()}; // no warning
+  (void)@{@"abc" : getNonnullFoo()}; // no warning
+  (void)@{@"abc" : getNullableFoo()}; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}}
+}
+
+void testCreateArrayLiteralWithNullableArg() {
+  (void)@[getMightBeNullFoo()]; // no warning
+  (void)@[getNonnullFoo()]; // no warning
+  (void)@[getNullableFoo()]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -97,7 +97,8 @@
 namespace {
   class NilArgChecker : public Checker<check::PreObjCMessage,
                                        check::PostStmt<ObjCDictionaryLiteral>,
-                                       check::PostStmt<ObjCArrayLiteral> > {
+                                       check::PostStmt<ObjCArrayLiteral>,
+                                       EventDispatcher<ImplicitNullDerefEvent>> {
     mutable std::unique_ptr<APIMisuse> BT;
 
     mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
@@ -141,11 +142,31 @@
                                   CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
-
     if (ExplodedNode *N = C.generateErrorNode()) {
       generateBugReport(N, Msg, E->getSourceRange(), E, C);
+      return;
     }
   }
+
+  auto ArgSVal = C.getSVal(E).getAs<DefinedOrUnknownSVal>();
+  if (!ArgSVal)
+    return;
+
+  ProgramStateRef StNonNull, StNull;
+  std::tie(StNonNull, StNull) = State->assume(*ArgSVal);
+
+  if (StNull) {
+    if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) {
+      ImplicitNullDerefEvent event = {*ArgSVal, false, N, &C.getBugReporter(),
+                                      /*IsDirectDereference=*/false};
+      dispatchEvent(event);
+    }
+  }
+
+  if (StNonNull)
+    State = StNonNull;
+
+  C.addTransition(State);
 }
 
 void NilArgChecker::warnIfNilArg(CheckerContext &C,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D152269.529116.patch
Type: text/x-patch
Size: 3154 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230607/84915869/attachment.bin>


More information about the cfe-commits mailing list