r320455 - [analyzer] StackAddrEscape: For now, disable the new async escape checks.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 11 18:59:09 PST 2017


Author: dergachev
Date: Mon Dec 11 18:59:09 2017
New Revision: 320455

URL: http://llvm.org/viewvc/llvm-project?rev=320455&view=rev
Log:
[analyzer] StackAddrEscape: For now, disable the new async escape checks.

The new check introduced in r318705 is useful, but suffers from a particular
class of false positives, namely, it does not account for
dispatch_barrier_sync() API which allows one to ensure that the asyncronously
executed block that captures a pointer to a local variable does not actually
outlive that variable.

The new check is split into a separate checker, under the name of
alpha.core.StackAddressAsyncEscape, which is likely to get enabled by default
again once these positives are fixed. The rest of the StackAddressEscapeChecker
is still enabled by default.

Differential Revision: https://reviews.llvm.org/D41042

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
    cfe/trunk/test/Analysis/stack-capture-leak-arc.mm
    cfe/trunk/test/Analysis/stack-capture-leak-no-arc.mm

Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=320455&r1=320454&r2=320455&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Dec 11 18:59:09 2017
@@ -188,6 +188,10 @@ def DynamicTypeChecker : Checker<"Dynami
   HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
   DescFile<"DynamicTypeChecker.cpp">;
 
+def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
+  HelpText<"Check that addresses to stack memory do not escape the function">,
+  DescFile<"StackAddrEscapeChecker.cpp">;
+
 } // end "alpha.core"
 
 let ParentPackage = Nullability in {

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp?rev=320455&r1=320454&r2=320455&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp Mon Dec 11 18:59:09 2017
@@ -37,6 +37,14 @@ class StackAddrEscapeChecker
   mutable std::unique_ptr<BuiltinBug> BT_capturedstackret;
 
 public:
+  enum CheckKind {
+    CK_StackAddrEscapeChecker,
+    CK_StackAddrAsyncEscapeChecker,
+    CK_NumCheckKinds
+  };
+
+  DefaultBool ChecksEnabled[CK_NumCheckKinds];
+
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
   void checkEndFunction(CheckerContext &Ctx) const;
@@ -225,6 +233,8 @@ void StackAddrEscapeChecker::checkReturn
 
 void StackAddrEscapeChecker::checkPreCall(const CallEvent &Call,
                                           CheckerContext &C) const {
+  if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker])
+    return;
   if (!Call.isGlobalCFunction("dispatch_after") &&
       !Call.isGlobalCFunction("dispatch_async"))
     return;
@@ -237,6 +247,8 @@ void StackAddrEscapeChecker::checkPreCal
 
 void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
                                           CheckerContext &C) const {
+  if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+    return;
 
   const Expr *RetE = RS->getRetValue();
   if (!RetE)
@@ -277,6 +289,9 @@ void StackAddrEscapeChecker::checkPreStm
 }
 
 void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
+  if (!ChecksEnabled[CK_StackAddrEscapeChecker])
+    return;
+
   ProgramStateRef State = Ctx.getState();
 
   // Iterate over all bindings to global variables and see if it contains
@@ -346,6 +361,12 @@ void StackAddrEscapeChecker::checkEndFun
   }
 }
 
-void ento::registerStackAddrEscapeChecker(CheckerManager &Mgr) {
-  Mgr.registerChecker<StackAddrEscapeChecker>();
-}
+#define REGISTER_CHECKER(name) \
+  void ento::register##name(CheckerManager &Mgr) { \
+    StackAddrEscapeChecker *Chk = \
+        Mgr.registerChecker<StackAddrEscapeChecker>(); \
+    Chk->ChecksEnabled[StackAddrEscapeChecker::CK_##name] = true; \
+  }
+
+REGISTER_CHECKER(StackAddrEscapeChecker)
+REGISTER_CHECKER(StackAddrAsyncEscapeChecker)

Modified: cfe/trunk/test/Analysis/stack-capture-leak-arc.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-capture-leak-arc.mm?rev=320455&r1=320454&r2=320455&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/stack-capture-leak-arc.mm (original)
+++ cfe/trunk/test/Analysis/stack-capture-leak-arc.mm Mon Dec 11 18:59:09 2017
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -fobjc-arc -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core.StackAddressAsyncEscape -fblocks -fobjc-arc -verify %s
 
 typedef struct dispatch_queue_s *dispatch_queue_t;
 typedef void (^dispatch_block_t)(void);
@@ -7,6 +7,7 @@ typedef long dispatch_once_t;
 void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
 typedef long dispatch_time_t;
 void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
+void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
 
 extern dispatch_queue_t queue;
 extern dispatch_once_t *predicate;
@@ -173,3 +174,16 @@ void test_no_leaks_on_semaphore_pattern(
   // Wait for the asynchronous work to finish
   dispatch_semaphore_wait(semaphore, 1000);
 }
+
+void test_dispatch_barrier_sync() {
+  int buf[16];
+  for (int n = 0; n < 16; ++n) {
+    int *ptr = &buf[n];
+    // FIXME: Should not warn. The dispatch_barrier_sync() call ensures
+    // that the block does not outlive 'buf'.
+    dispatch_async(queue, ^{ // expected-warning{{Address of stack memory associated with local variable 'buf' is captured by an asynchronously-executed block}}
+      (void)ptr;
+    });
+  }
+  dispatch_barrier_sync(queue, ^{});
+}

Modified: cfe/trunk/test/Analysis/stack-capture-leak-no-arc.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-capture-leak-no-arc.mm?rev=320455&r1=320454&r2=320455&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/stack-capture-leak-no-arc.mm (original)
+++ cfe/trunk/test/Analysis/stack-capture-leak-no-arc.mm Mon Dec 11 18:59:09 2017
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -verify %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core.StackAddressAsyncEscape -fblocks -verify %s
 
 typedef struct dispatch_queue_s *dispatch_queue_t;
 typedef void (^dispatch_block_t)(void);




More information about the cfe-commits mailing list