r290341 - [analyzer] Improve suppress-on-sink behavior in incomplete analyses.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 22 06:48:53 PST 2016
Author: dergachev
Date: Thu Dec 22 08:48:52 2016
New Revision: 290341
URL: http://llvm.org/viewvc/llvm-project?rev=290341&view=rev
Log:
[analyzer] Improve suppress-on-sink behavior in incomplete analyses.
Warnings with suppress-on-sink are discarded during FlushReports when
BugReporter notices that all paths in ExplodedGraph that pass through the
warning eventually run into a sink node.
However, suppress-on-sink fails to filter out false positives when the analysis
terminates too early - by running into analyzer limits, such as block count
limits or graph size limits - and the interruption hits the narrow window
between throwing the leak report and reaching the no-return function call. In
such case the report is there, however suppression-on-sink doesn't work, because
the sink node was never constructed in the incomplete ExplodedGraph.
This patch implements a very partial solution: also suppress reports thrown
against a statement-node that corresponds to a statement that belongs to a
no-return block of the CFG.
rdar://problem/28832541
Differential Revision: https://reviews.llvm.org/D28023
Added:
cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=290341&r1=290340&r2=290341&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Dec 22 08:48:52 2016
@@ -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 @@ struct FRIEC_WLItem {
};
}
+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 @@ FindReportInEquivalenceClass(BugReportEq
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;
Added: cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c?rev=290341&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c (added)
+++ cfe/trunk/test/Analysis/max-nodes-suppress-on-sink.c Thu Dec 22 08:48:52 2016
@@ -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);
+}
More information about the cfe-commits
mailing list