[cfe-commits] r150446 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c

Anna Zaks ganna at apple.com
Mon Feb 13 16:26:13 PST 2012


Author: zaks
Date: Mon Feb 13 18:26:13 2012
New Revision: 150446

URL: http://llvm.org/viewvc/llvm-project?rev=150446&view=rev
Log:
[analyzer] Malloc Checker: realloc: add dependency between the symbols
in realloc map. 

If there is no dependency, the reallocated ptr will get garbage
collected before we know that realloc failed, which would lead us to
missing a memory leak warning.

Also added new test cases, which we can handle now.
Plus minor cleanups.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/test/Analysis/malloc.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=150446&r1=150445&r2=150446&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Mon Feb 13 18:26:13 2012
@@ -409,17 +409,12 @@
   if (!isa<Loc>(location))
     return 0;
 
-  // FIXME: Technically using 'Assume' here can result in a path
-  //  bifurcation.  In such cases we need to return two states, not just one.
+  // The explicit NULL case, no operation is performed.
   ProgramStateRef notNullState, nullState;
   llvm::tie(notNullState, nullState) = state->assume(location);
-
-  // The explicit NULL case, no operation is performed.
   if (nullState && !notNullState)
     return 0;
 
-  assert(notNullState);
-
   // Unknown values could easily be okay
   // Undefined values are handled elsewhere
   if (ArgVal.isUnknownOrUndef())
@@ -490,8 +485,8 @@
 
   // Normal free.
   if (Hold)
-    return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE));
-  return notNullState->set<RegionState>(Sym, RefState::getReleased(CE));
+    return state->set<RegionState>(Sym, RefState::getRelinquished(CE));
+  return state->set<RegionState>(Sym, RefState::getReleased(CE));
 }
 
 bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
@@ -685,6 +680,7 @@
       // If size was equal to 0, either NULL or a pointer suitable to be passed
       // to free() is returned.
       stateFree = stateFree->set<ReallocPairs>(ToPtr, FromPtr);
+      C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
       C.addTransition(stateFree);
       return;
     }
@@ -697,6 +693,7 @@
     if (!stateRealloc)
       return;
     stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr, FromPtr);
+    C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
     C.addTransition(stateRealloc);
     return;
   }
@@ -918,7 +915,7 @@
         if (RS->isReleased())
           state = state->set<RegionState>(I.getData(),
                              RefState::getAllocateUnchecked(RS->getStmt()));
-        if (RS->isAllocated())
+        else if (RS->isAllocated())
           state = state->set<RegionState>(I.getData(),
                              RefState::getReleased(RS->getStmt()));
       }

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=150446&r1=150445&r2=150446&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Mon Feb 13 18:26:13 2012
@@ -109,6 +109,47 @@
   free(r);
 }
 
+void reallocRadar6337483_1() {
+    char *buf = malloc(100);
+    buf = (char*)realloc(buf, 0x1000000);
+    if (!buf) {
+        return;// expected-warning {{Allocated memory never released.}}
+    }
+    free(buf);
+}
+
+void reallocRadar6337483_2() {
+    char *buf = malloc(100);
+    char *buf2 = (char*)realloc(buf, 0x1000000);
+    if (!buf2) { // expected-warning {{Allocated memory never released.}}
+      ;
+    } else {
+      free(buf2);
+    }
+}
+
+void reallocRadar6337483_3() {
+    char * buf = malloc(100);
+    char * tmp;
+    tmp = (char*)realloc(buf, 0x1000000);
+    if (!tmp) {
+        free(buf);
+        return;
+    }
+    buf = tmp;
+    free(buf);
+}
+
+void reallocRadar6337483_4() {
+    char *buf = malloc(100);
+    char *buf2 = (char*)realloc(buf, 0x1000000);
+    if (!buf2) {
+      return;  // expected-warning {{Allocated memory never released.}}
+    } else {
+      free(buf2);
+    }
+}
+
 // This case tests that storing malloc'ed memory to a static variable which is
 // then returned is not leaked.  In the absence of known contracts for functions
 // or inter-procedural analysis, this is a conservative answer.





More information about the cfe-commits mailing list