[PATCH] D28023: [analyzer] Fix leak false positives before no-return functions caused by incomplete analyses.

Phabricator via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 22 06:59:27 PST 2016


This revision was automatically updated to reflect the committed changes.
Closed by commit rL290341: [analyzer] Improve suppress-on-sink behavior in incomplete analyses. (authored by dergachev).

Changed prior to commit:
  https://reviews.llvm.org/D28023?vs=82229&id=82339#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28023

Files:
  cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
  cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c


Index: cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c
===================================================================
--- cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c
+++ cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config max-nodes=12 -verify %s
+
+// Here we test how "suppress on sink" feature of certain bugtypes interacts
+// with reaching analysis limits.
+
+// If we report a warning of a bug-type with "suppress on sink" attribute set
+// (such as MallocChecker's memory leak warning), then failing to reach the
+// reason for the sink (eg. no-return function such as "exit()") due to analysis
+// limits (eg. max-nodes option), we may produce a false positive.
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+extern void exit(int) __attribute__ ((__noreturn__));
+
+void clang_analyzer_warnIfReached(void);
+
+void test_single_cfg_block_sink() {
+  void *p = malloc(1); // no-warning (wherever the leak warning may occur here)
+
+  // Due to max-nodes option in the run line, we should reach the first call
+  // but bail out before the second call.
+  // If the test on these two lines starts failing, see if modifying
+  // the max-nodes run-line helps.
+  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+  clang_analyzer_warnIfReached(); // no-warning
+
+  // Even though we do not reach this line, we should still suppress
+  // the leak report.
+  exit(0);
+}
Index: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
 #include "clang/Analysis/ProgramPoint.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -3285,6 +3286,19 @@
 };
 }
 
+static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
+  ProgramPoint P = N->getLocation();
+  if (auto BEP = P.getAs<BlockEntrance>())
+    return BEP->getBlock();
+
+  // Find the node's current statement in the CFG.
+  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
+    return N->getLocationContext()->getAnalysisDeclContext()
+                                  ->getCFGStmtMap()->getBlock(S);
+
+  return nullptr;
+}
+
 static BugReport *
 FindReportInEquivalenceClass(BugReportEquivClass& EQ,
                              SmallVectorImpl<BugReport*> &bugReports) {
@@ -3333,6 +3347,18 @@
       continue;
     }
 
+    // See if we are in a no-return CFG block. If so, treat this similarly
+    // to being post-dominated by a sink. This works better when the analysis
+    // is incomplete and we have never reached a no-return function
+    // we're post-dominated by.
+    // This is not quite enough to handle the incomplete analysis case.
+    // We may be post-dominated in subsequent blocks, or even
+    // inter-procedurally. However, it is not clear if more complicated
+    // cases are generally worth suppressing.
+    if (const CFGBlock *B = findBlockForNode(errorNode))
+      if (B->hasNoReturnElement())
+        continue;
+
     // At this point we know that 'N' is not a sink and it has at least one
     // successor.  Use a DFS worklist to find a non-sink end-of-path node.
     typedef FRIEC_WLItem WLItem;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28023.82339.patch
Type: text/x-patch
Size: 3569 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161222/62f2dbea/attachment-0001.bin>


More information about the cfe-commits mailing list