summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-01-19 02:18:15 +0000
committerAnna Zaks <ganna@apple.com>2013-01-19 02:18:15 +0000
commit7d9ce5312441d81a4c154f2823a153974b3e213f (patch)
treeed45caa154045cca9055da4b068f3f3526c25811
parent7ab15fafe3e28557cc0688c85cbbc3f7e86d3456 (diff)
downloadbcm5719-llvm-7d9ce5312441d81a4c154f2823a153974b3e213f.tar.gz
bcm5719-llvm-7d9ce5312441d81a4c154f2823a153974b3e213f.zip
[analyzer] Suppress warnings coming out of macros defined in sys/queue.h
Suppress the warning by just not emitting the report. The sink node would get generated, which is fine since we did reach a bad state. Motivation Due to the way code is structured in some of these macros, we do not reason correctly about it and report false positives. Specifically, the following loop reports a use-after-free. Because of the way the code is structured inside of the macro, the analyzer assumes that the list can have cycles, so you end up with use-after-free in the loop, that is safely deleting elements of the list. (The user does not have a way to teach the analyzer about shape of data structures.) SLIST_FOREACH_SAFE(item, &ctx->example_list, example_le, tmpitem) { if (item->index == 3) { // if you remove each time, no complaints assert((&ctx->example_list)->slh_first == item); SLIST_REMOVE(&ctx->example_list, item, example_s, example_le); free(item); } } llvm-svn: 172883
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h5
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp25
-rw-r--r--clang/test/Analysis/diagnostics/false-positive-suppression.c23
-rw-r--r--clang/test/Analysis/diagnostics/include/sys/queue.h5
4 files changed, 58 insertions, 0 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 7a87e47f74c..74579b7b4cb 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -457,6 +457,11 @@ public:
void Register(BugType *BT);
+ /// \brief Suppress reports that might lead to known false positives.
+ ///
+ /// Currently this suppresses reports based on locations of bugs.
+ bool suppressReport(BugReport *R);
+
/// \brief Add the given report to the set of reports tracked by BugReporter.
///
/// The reports are usually generated by the checkers. Further, they are
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 8e6bc69cc4a..d64aa39febe 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2137,7 +2137,32 @@ void BugReporter::Register(BugType *BT) {
BugTypes = F.add(BugTypes, BT);
}
+bool BugReporter::suppressReport(BugReport *R) {
+ const Stmt *S = R->getStmt();
+ if (!S)
+ return false;
+
+ // Here we suppress false positives coming from system macros. This list is
+ // based on known issues.
+
+ // Skip reports within the sys/queue.h macros as we do not have the ability to
+ // reason about data structure shapes.
+ SourceManager &SM = getSourceManager();
+ SourceLocation Loc = S->getLocStart();
+ while (Loc.isMacroID()) {
+ if (SM.isInSystemMacro(Loc) &&
+ (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h")))
+ return true;
+ Loc = SM.getSpellingLoc(Loc);
+ }
+
+ return false;
+}
+
void BugReporter::emitReport(BugReport* R) {
+ if (suppressReport(R))
+ return;
+
// Compute the bug report's hash to determine its equivalence class.
llvm::FoldingSetNodeID ID;
R->Profile(ID);
diff --git a/clang/test/Analysis/diagnostics/false-positive-suppression.c b/clang/test/Analysis/diagnostics/false-positive-suppression.c
new file mode 100644
index 00000000000..420a5733800
--- /dev/null
+++ b/clang/test/Analysis/diagnostics/false-positive-suppression.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s
+// expected-no-diagnostics
+
+#include "include/sys/queue.h"
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+int radar12491259() {
+ int *p = malloc(12);
+ FREE_POINTER(p);
+ FREE_POINTER(p); // no-warning: we are suppressing errors coming from sys/queue macros.
+ return 0;
+}
+
+#define MYMACRO(p) FREE_POINTER(p)
+
+int radar12491259_inside_macro() {
+ int *p = malloc(12);
+ MYMACRO(p);
+ MYMACRO(p); // no-warning: we are suppressing errors coming from sys/queue macros.
+ return 0;
+}
diff --git a/clang/test/Analysis/diagnostics/include/sys/queue.h b/clang/test/Analysis/diagnostics/include/sys/queue.h
new file mode 100644
index 00000000000..e5698ed443b
--- /dev/null
+++ b/clang/test/Analysis/diagnostics/include/sys/queue.h
@@ -0,0 +1,5 @@
+#pragma clang system_header
+
+void free(void *);
+#define FREE_POINTER(x) free(x)
+
OpenPOWER on IntegriCloud