]> granicus.if.org Git - clang/commitdiff
[analyzer] Leaks should be uniqued by the allocation point in the
authorAnna Zaks <ganna@apple.com>
Mon, 27 Feb 2012 23:40:55 +0000 (23:40 +0000)
committerAnna Zaks <ganna@apple.com>
Mon, 27 Feb 2012 23:40:55 +0000 (23:40 +0000)
closest function context.

This prevents us from uniqueing all leaks from the same allocation
helper. radar://10932226

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151592 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/MallocChecker.cpp
test/Analysis/malloc-interprocedural.c

index 9fe34f552529cf3013a51bc112b28cf960fa8c8a..f7f199e26c347105250df5e13de8d43ec7300294 100644 (file)
@@ -775,6 +775,7 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
 const Stmt *
 MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
                                  CheckerContext &C) const {
+  const LocationContext *LeakContext = N->getLocationContext();
   // Walk the ExplodedGraph backwards and find the first node that referred to
   // the tracked symbol.
   const ExplodedNode *AllocNode = N;
@@ -782,12 +783,18 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
   while (N) {
     if (!N->getState()->get<RegionState>(Sym))
       break;
-    AllocNode = N;
+    // Allocation node, is the last node in the current context in which the
+    // symbol was tracked.
+    if (N->getLocationContext() == LeakContext)
+      AllocNode = N;
     N = N->pred_empty() ? NULL : *(N->pred_begin());
   }
 
   ProgramPoint P = AllocNode->getLocation();
-  return cast<clang::PostStmt>(P).getStmt();
+  if (!isa<StmtPoint>(P))
+    return 0;
+
+  return cast<StmtPoint>(P).getStmt();
 }
 
 void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
@@ -806,10 +813,10 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
   // Most bug reports are cached at the location where they occurred.
   // With leaks, we want to unique them by the location where they were
   // allocated, and only report a single path.
-  const Stmt *AllocStmt = getAllocationSite(N, Sym, C);
-  PathDiagnosticLocation LocUsedForUniqueing =
-    PathDiagnosticLocation::createBegin(AllocStmt, C.getSourceManager(),
-                                        N->getLocationContext());
+  PathDiagnosticLocation LocUsedForUniqueing;
+  if (const Stmt *AllocStmt = getAllocationSite(N, Sym, C))
+    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
+                            C.getSourceManager(), N->getLocationContext());
 
   BugReport *R = new BugReport(*BT_Leak,
     "Memory is never released; potential memory leak", N, LocUsedForUniqueing);
index e67c14be426d8df504c87fb4fd7f46d21365ce70..374c4a310d10276656096cfe524bf11c5cd20370 100644 (file)
@@ -38,8 +38,10 @@ static void test11() {
   my_free1(data);
 }
 
-static void test2() {
-  void * data = my_malloc2(1, 4);
+static void testUniqueingByallocationSiteInTopLevelFunction() {
+  void *data = my_malloc2(1, 4);
+  data = 0;
+  int x = 5;// expected-warning {{Memory is never released; potential memory leak}}
   data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential memory leak}}
 }
 
@@ -94,4 +96,3 @@ int uafAndCallsFooWithEmptyReturn() {
   fooWithEmptyReturn(12);
   return *x; // expected-warning {{Use of memory after it is freed}}
 }
-