r178890 - [analyzer] Split new/delete checker into use-after-free and leaks parts.

Jordan Rose jordan_rose at apple.com
Fri Apr 5 10:55:00 PDT 2013


Author: jrose
Date: Fri Apr  5 12:55:00 2013
New Revision: 178890

URL: http://llvm.org/viewvc/llvm-project?rev=178890&view=rev
Log:
[analyzer] Split new/delete checker into use-after-free and leaks parts.

This splits the leak-checking part of alpha.cplusplus.NewDelete into a
separate user-level checker, alpha.cplusplus.NewDeleteLeaks. All the
difficult false positives we've seen with the new/delete checker have been
spurious leak warnings; the use-after-free warnings and mismatched
deallocator warnings, while rare, have always been valid.

<rdar://problem/6194569>

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
    cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp
    cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
    cfe/trunk/test/Analysis/NewDelete-checker-test.cpp
    cfe/trunk/test/Analysis/NewDelete-custom.cpp
    cfe/trunk/test/Analysis/NewDelete-intersections.mm
    cfe/trunk/test/Analysis/NewDelete-variadic.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Fri Apr  5 12:55:00 2013
@@ -176,7 +176,11 @@ def VirtualCallChecker : Checker<"Virtua
   DescFile<"VirtualCallChecker.cpp">;
 
 def NewDeleteChecker : Checker<"NewDelete">,
-  HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by new/delete.">, 
+  HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
+  DescFile<"MallocChecker.cpp">;
+
+def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
+  HelpText<"Check for memory leaks. Traces memory managed by new/delete.">, 
   DescFile<"MallocChecker.cpp">;
 
 } // end: "alpha.cplusplus"

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Fri Apr  5 12:55:00 2013
@@ -164,6 +164,7 @@ public:
     DefaultBool CMallocPessimistic;
     DefaultBool CMallocOptimistic;
     DefaultBool CNewDeleteChecker;
+    DefaultBool CNewDeleteLeaksChecker;
     DefaultBool CMismatchedDeallocatorChecker;
   };
 
@@ -1536,12 +1537,21 @@ void MallocChecker::reportLeak(SymbolRef
                                CheckerContext &C) const {
 
   if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 
-      !Filter.CNewDeleteChecker)
+      !Filter.CNewDeleteLeaksChecker)
     return;
 
-  if (!isTrackedFamily(C, Sym))
+  const RefState *RS = C.getState()->get<RegionState>(Sym);
+  assert(RS && "cannot leak an untracked symbol");
+  AllocationFamily Family = RS->getAllocationFamily();
+  if (!isTrackedFamily(Family))
     return;
 
+  // Special case for new and new[]; these are controlled by a separate checker
+  // flag so that they can be selectively disabled.
+  if (Family == AF_CXXNew || Family == AF_CXXNewArray)
+    if (!Filter.CNewDeleteLeaksChecker)
+      return;
+
   assert(N);
   if (!BT_Leak) {
     BT_Leak.reset(new BugType("Memory leak", "Memory Error"));
@@ -2115,4 +2125,5 @@ void ento::register##name(CheckerManager
 REGISTER_CHECKER(MallocPessimistic)
 REGISTER_CHECKER(MallocOptimistic)
 REGISTER_CHECKER(NewDeleteChecker)
+REGISTER_CHECKER(NewDeleteLeaksChecker)
 REGISTER_CHECKER(MismatchedDeallocatorChecker)

Modified: cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator%2BNewDelete.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp (original)
+++ cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp Fri Apr  5 12:55:00 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
 
 typedef __typeof(sizeof(int)) size_t;
 void *malloc(size_t);
@@ -52,7 +53,10 @@ void testNewDoubleFree() {
 
 void testNewLeak() {
   int *p = new int;
-} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
+}
+#ifdef LEAKS
+// expected-warning at -2 {{Memory is never released; potential leak of memory pointed to by 'p'}}
+#endif
 
 void testNewUseAfterFree() {
   int *p = (int *)operator new(0);

Modified: cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BNewDelete_intersections.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp (original)
+++ cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp Fri Apr  5 12:55:00 2013
@@ -1,11 +1,12 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -verify %s
 
 typedef __typeof(sizeof(int)) size_t;
 void *malloc(size_t);
 void free(void *);
 
 //-------------------------------------------------------------------
-// Check that unix.Malloc + alpha.cplusplus.NewDelete does not enable
+// Check that unix.Malloc + cplusplus.NewDelete does not enable
 // warnings produced by unix.MismatchedDeallocator.
 //-------------------------------------------------------------------
 void testMismatchedDeallocator() {

Modified: cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete%2BMismatchedDeallocator_intersections.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp (original)
+++ cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp Fri Apr  5 12:55:00 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.MismatchedDeallocator -DLEAKS -std=c++11 -verify %s
 // expected-no-diagnostics
 
 typedef __typeof(sizeof(int)) size_t;

Modified: cfe/trunk/test/Analysis/NewDelete-checker-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NewDelete-checker-test.cpp (original)
+++ cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Fri Apr  5 12:55:00 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
 #include "Inputs/system-header-simulator-cxx.h"
 
 typedef __typeof__(sizeof(int)) size_t;
@@ -12,28 +13,46 @@ int *global;
 //----- Standard non-placement operators
 void testGlobalOpNew() {
   void *p = operator new(0);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testGlobalOpNewArray() {
   void *p = operator new[](0);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testGlobalNewExpr() {
   int *p = new int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testGlobalNewExprArray() {
   int *p = new int[0];
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 //----- Standard nothrow placement operators
 void testGlobalNoThrowPlacementOpNewBeforeOverload() {
   void *p = operator new(0, std::nothrow);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testGlobalNoThrowPlacementExprNewBeforeOverload() {
   int *p = new(std::nothrow) int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 
 //----- Standard pointer placement operators

Modified: cfe/trunk/test/Analysis/NewDelete-custom.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-custom.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NewDelete-custom.cpp (original)
+++ cfe/trunk/test/Analysis/NewDelete-custom.cpp Fri Apr  5 12:55:00 2013
@@ -1,6 +1,12 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS -fblocks -verify %s
 #include "Inputs/system-header-simulator-cxx.h"
 
+#ifndef LEAKS
+// expected-no-diagnostics
+#endif
+
+
 void *allocator(std::size_t size);
 
 void *operator new[](std::size_t size) throw() { return allocator(size); }
@@ -19,7 +25,10 @@ void testNewMethod() {
   C *p2 = new C; // no warn
 
   C *c3 = ::new C;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testOpNewArray() {
   void *p = operator new[](0); // call is inlined, no warn
@@ -27,7 +36,11 @@ void testOpNewArray() {
 
 void testNewExprArray() {
   int *p = new int[0];
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
+
 
 //----- Custom non-placement operators
 void testOpNew() {
@@ -36,16 +49,26 @@ void testOpNew() {
 
 void testNewExpr() {
   int *p = new int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
+
 
 //----- Custom NoThrow placement operators
 void testOpNewNoThrow() {
   void *p = operator new(0, std::nothrow);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 void testNewExprNoThrow() {
   int *p = new(std::nothrow) int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2{{Memory is never released; potential leak}}
+#endif
 
 //----- Custom placement operators
 void testOpNewPlacement() {

Modified: cfe/trunk/test/Analysis/NewDelete-intersections.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-intersections.mm?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NewDelete-intersections.mm (original)
+++ cfe/trunk/test/Analysis/NewDelete-intersections.mm Fri Apr  5 12:55:00 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -verify %s
 #include "Inputs/system-header-simulator-cxx.h"
 #include "Inputs/system-header-simulator-objc.h"
 
@@ -39,16 +40,25 @@ void testDeleteMalloced() {
 void testFreeOpNew() {
   void *p = operator new(0);
   free(p);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2 {{Memory is never released; potential leak}}
+#endif
 
 void testFreeNewExpr() {
   int *p = new int;
   free(p);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning at -2 {{Memory is never released; potential leak}}
+#endif
 
 void testObjcFreeNewed() {
   int *p = new int;
-  NSData *nsdata = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{Memory is never released; potential leak}}
+  NSData *nsdata = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1];
+#ifdef LEAKS
+  // expected-warning at -2 {{Memory is never released; potential leak}}
+#endif
 }
 
 void testFreeAfterDelete() {

Modified: cfe/trunk/test/Analysis/NewDelete-variadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-variadic.cpp?rev=178890&r1=178889&r2=178890&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NewDelete-variadic.cpp (original)
+++ cfe/trunk/test/Analysis/NewDelete-variadic.cpp Fri Apr  5 12:55:00 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s
 // expected-no-diagnostics
 
 namespace std {





More information about the cfe-commits mailing list