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

Anna Zaks ganna at apple.com
Wed Sep 12 15:57:34 PDT 2012


Author: zaks
Date: Wed Sep 12 17:57:34 2012
New Revision: 163749

URL: http://llvm.org/viewvc/llvm-project?rev=163749&view=rev
Log:
[analyzer] Fix another false positive in malloc realloc logic.

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=163749&r1=163748&r2=163749&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Sep 12 17:57:34 2012
@@ -70,24 +70,31 @@
   }
 };
 
+enum ReallocPairKind {
+  RPToBeFreedAfterFailure,
+  // The symbol has been freed when reallocation failed.
+  RPIsFreeOnFailure,
+  // The symbol does not need to be freed after reallocation fails.
+  RPDoNotTrackAfterFailure
+};
+
 /// \class ReallocPair
 /// \brief Stores information about the symbol being reallocated by a call to
 /// 'realloc' to allow modeling failed reallocation later in the path.
 struct ReallocPair {
   // \brief The symbol which realloc reallocated.
   SymbolRef ReallocatedSym;
-  // \brief The flag is true if the symbol does not need to be freed after
-  // reallocation fails.
-  bool IsFreeOnFailure;
+  ReallocPairKind Kind;
 
-  ReallocPair(SymbolRef S, bool F) : ReallocatedSym(S), IsFreeOnFailure(F) {}
+  ReallocPair(SymbolRef S, ReallocPairKind K) :
+    ReallocatedSym(S), Kind(K) {}
   void Profile(llvm::FoldingSetNodeID &ID) const {
-    ID.AddInteger(IsFreeOnFailure);
+    ID.AddInteger(Kind);
     ID.AddPointer(ReallocatedSym);
   }
   bool operator==(const ReallocPair &X) const {
     return ReallocatedSym == X.ReallocatedSym &&
-           IsFreeOnFailure == X.IsFreeOnFailure;
+           Kind == X.Kind;
   }
 };
 
@@ -926,10 +933,16 @@
     if (!stateRealloc)
       return 0;
 
+    ReallocPairKind Kind = RPToBeFreedAfterFailure;
+    if (FreesOnFail)
+      Kind = RPIsFreeOnFailure;
+    else if (!ReleasedAllocated)
+      Kind = RPDoNotTrackAfterFailure;
+
     // Record the info about the reallocated symbol so that we could properly
     // process failed reallocation.
     stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
-                     ReallocPair(FromPtr, FreesOnFail || !ReleasedAllocated));
+                                                   ReallocPair(FromPtr, Kind));
     // The reallocated symbol should stay alive for as long as the new symbol.
     C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
     return stateRealloc;
@@ -1285,15 +1298,21 @@
   ReallocMap RP = state->get<ReallocPairs>();
   for (ReallocMap::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
     // If the symbol is assumed to be NULL, remove it from consideration.
-    if (state->getConstraintManager().isNull(state, I.getKey()).isTrue()) {
-      SymbolRef ReallocSym = I.getData().ReallocatedSym;
-      if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
-        if (RS->isReleased() && ! I.getData().IsFreeOnFailure)
+    if (!state->getConstraintManager().isNull(state, I.getKey()).isTrue())
+      continue;
+    SymbolRef ReallocSym = I.getData().ReallocatedSym;
+    if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
+      if (RS->isReleased()) {
+        if (I.getData().Kind == RPToBeFreedAfterFailure)
           state = state->set<RegionState>(ReallocSym,
-                             RefState::getAllocated(RS->getStmt()));
+              RefState::getAllocated(RS->getStmt()));
+        else if (I.getData().Kind == RPDoNotTrackAfterFailure)
+          state = state->remove<RegionState>(ReallocSym);
+        else
+          assert(I.getData().Kind == RPIsFreeOnFailure);
       }
-      state = state->remove<ReallocPairs>(I.getKey());
     }
+    state = state->remove<ReallocPairs>(I.getKey());
   }
 
   return state;

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=163749&r1=163748&r2=163749&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Wed Sep 12 17:57:34 2012
@@ -1020,6 +1020,16 @@
   return 0;
 }
 
+// Test realloc with no visible malloc.
+void *test(void *ptr) {
+  void *newPtr = realloc(ptr, 4);
+  if (newPtr == 0) {
+    if (ptr)
+      free(ptr); // no-warning
+  }
+  return newPtr;
+}
+
 // ----------------------------------------------------------------------------
 // False negatives.
 





More information about the cfe-commits mailing list