]> granicus.if.org Git - clang/commitdiff
[analyzer] Tighten up the realloc() failure path note generation...make sure we get...
authorJordy Rose <jediknil@belkadan.com>
Sat, 24 Mar 2012 03:15:09 +0000 (03:15 +0000)
committerJordy Rose <jediknil@belkadan.com>
Sat, 24 Mar 2012 03:15:09 +0000 (03:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153370 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/MallocChecker.cpp

index f5218746befc4429eb48996f2ddb6b3356821028..5eca9178ad9143326c9710d114c47063660094e1 100644 (file)
@@ -201,16 +201,22 @@ private:
   protected:
     enum NotificationMode {
       Normal,
-      Complete,
       ReallocationFailed
     };
 
     // The allocated region symbol tracked by the main analysis.
     SymbolRef Sym;
-    NotificationMode Mode;
 
-  public:
-    MallocBugVisitor(SymbolRef S) : Sym(S), Mode(Normal) {}
+     // The mode we are in, i.e. what kind of diagnostics will be emitted.
+     NotificationMode Mode;
+
+     // A symbol from when the primary region should have been reallocated.
+     SymbolRef FailedReallocSymbol;
+
+   public:
+     MallocBugVisitor(SymbolRef S)
+       : Sym(S), Mode(Normal), FailedReallocSymbol(0) {}
+
     virtual ~MallocBugVisitor() {}
 
     void Profile(llvm::FoldingSetNodeID &ID) const {
@@ -1390,30 +1396,33 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
       StackHint = new StackHintGeneratorForReallocationFailed(Sym,
                                                        "Reallocation failed");
 
-      if (SymbolRef sym = findFailedReallocSymbol(state, statePrev))
+      if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
+        // Is it possible to fail two reallocs WITHOUT testing in between?
+        assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
+          "We only support one failed realloc at a time.");
         BR.markInteresting(sym);
+        FailedReallocSymbol = sym;
+      }
     }
 
   // We are in a special mode if a reallocation failed later in the path.
   } else if (Mode == ReallocationFailed) {
-    // Generate a special diagnostic for the first realloc we find.
-    if (!isAllocated(RS, RSPrev, S) && !isReleased(RS, RSPrev, S))
-      return 0;
+    assert(FailedReallocSymbol && "No symbol to look for.");
 
-    // Check that the name of the function is realloc.
-    const CallExpr *CE = dyn_cast<CallExpr>(S);
-    if (!CE)
-      return 0;
-    const FunctionDecl *funDecl = CE->getDirectCallee();
-    if (!funDecl)
-      return 0;
-    StringRef FunName = funDecl->getName();
-    if (!(FunName.equals("realloc") || FunName.equals("reallocf")))
-      return 0;
-    Msg = "Attempt to reallocate memory";
-    StackHint = new StackHintGeneratorForSymbol(Sym,
-                                                "Returned reallocated memory");
-    Mode = Normal;
+    // Is this is the first appearance of the reallocated symbol?
+    if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
+      // If we ever hit this assert, that means BugReporter has decided to skip
+      // node pairs or visit them out of order.
+      assert(state->get<RegionState>(FailedReallocSymbol) &&
+        "Missed the reallocation point");
+
+      // We're at the reallocation point.
+      Msg = "Attempt to reallocate memory";
+      StackHint = new StackHintGeneratorForSymbol(Sym,
+                                                 "Returned reallocated memory");
+      FailedReallocSymbol = NULL;
+      Mode = Normal;
+    }
   }
 
   if (!Msg)