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

Anna Zaks ganna at apple.com
Wed Feb 8 22:25:52 PST 2012


Author: zaks
Date: Thu Feb  9 00:25:51 2012
New Revision: 150156

URL: http://llvm.org/viewvc/llvm-project?rev=150156&view=rev
Log:
[analyzer] Add custom path diagnostic to the Malloc Checker.

Very simple so far - we just highlight every allocation and release
site.

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=150156&r1=150155&r2=150156&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Feb  9 00:25:51 2012
@@ -138,6 +138,40 @@
   static bool SummarizeValue(raw_ostream &os, SVal V);
   static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
   void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const;
+
+  /// The bug visitor which allows us to print extra diagnostics along the
+  /// BugReport path. For example, showing the allocation site of the leaked
+  /// region.
+  class MallocBugVisitor : public BugReporterVisitor {
+  protected:
+    // The allocated region symbol tracked by the main analysis.
+    SymbolRef Sym;
+
+  public:
+    MallocBugVisitor(SymbolRef S) : Sym(S) {}
+    virtual ~MallocBugVisitor() {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      static int X = 0;
+      ID.AddPointer(&X);
+      ID.AddPointer(Sym);
+    }
+
+    inline bool isAllocated(const RefState *S, const RefState *SPrev) {
+      // Did not track -> allocated. Other state (released) -> allocated.
+      return ((S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
+    }
+
+    inline bool isReleased(const RefState *S, const RefState *SPrev) {
+      // Did not track -> released. Other state (allocated) -> released.
+      return ((S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
+    }
+
+    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                   const ExplodedNode *PrevN,
+                                   BugReporterContext &BRC,
+                                   BugReport &BR);
+  };
 };
 } // end anonymous namespace
 
@@ -388,9 +422,9 @@
         BT_DoubleFree.reset(
           new BuiltinBug("Double free",
                          "Try to free a memory block that has been released"));
-      // FIXME: should find where it's freed last time.
       BugReport *R = new BugReport(*BT_DoubleFree, 
                                    BT_DoubleFree->getDescription(), N);
+      R->addVisitor(new MallocBugVisitor(Sym));
       C.EmitReport(R);
     }
     return 0;
@@ -633,12 +667,14 @@
 
   // FIXME: This does not handle when we have multiple leaks at a single
   // place.
+  // TODO: We don't have symbol info in the diagnostics here!
   if (N && generateReport) {
     if (!BT_Leak)
       BT_Leak.reset(new BuiltinBug("Memory leak",
               "Allocated memory never released. Potential memory leak."));
     // FIXME: where it is allocated.
     BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+    //Report->addVisitor(new MallocBugVisitor(Sym));
     C.EmitReport(R);
   }
 }
@@ -656,6 +692,7 @@
           BT_Leak.reset(new BuiltinBug("Memory leak",
                     "Allocated memory never released. Potential memory leak."));
         BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+        R->addVisitor(new MallocBugVisitor(I->first));
         Ctx.EmitReport(R);
       }
     }
@@ -718,6 +755,7 @@
       BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),N);
       if (S)
         R->addRange(S->getSourceRange());
+      R->addVisitor(new MallocBugVisitor(Sym));
       C.EmitReport(R);
       return true;
     }
@@ -792,6 +830,44 @@
   }
 }
 
+PathDiagnosticPiece *
+MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
+                                           const ExplodedNode *PrevN,
+                                           BugReporterContext &BRC,
+                                           BugReport &BR) {
+  const RefState *RS = N->getState()->get<RegionState>(Sym);
+  const RefState *RSPrev = PrevN->getState()->get<RegionState>(Sym);
+  if (!RS && !RSPrev)
+    return 0;
+
+  // We expect the interesting locations be StmtPoints corresponding to call
+  // expressions. We do not support indirect function calls as of now.
+  const CallExpr *CE = 0;
+  if (isa<StmtPoint>(N->getLocation()))
+    CE = dyn_cast<CallExpr>(cast<StmtPoint>(N->getLocation()).getStmt());
+  if (!CE)
+    return 0;
+  const FunctionDecl *funDecl = CE->getDirectCallee();
+  if (!funDecl)
+    return 0;
+  StringRef funName = funDecl->getName();
+
+  // Find out if this is an interesting point and what is the kind.
+  const char *Msg = 0;
+  if (isAllocated(RS, RSPrev))
+    Msg = "Memory is allocated here";
+  else if (isReleased(RS, RSPrev))
+    Msg = "Memory is released here";
+  if (!Msg)
+    return 0;
+
+  // Generate the extra diagnostic.
+  PathDiagnosticLocation Pos(CE, BRC.getSourceManager(),
+                             N->getLocationContext());
+  return new PathDiagnosticEventPiece(Pos, Msg);
+}
+
+
 #define REGISTER_CHECKER(name) \
 void ento::register##name(CheckerManager &mgr) {\
   mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=150156&r1=150155&r2=150156&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Thu Feb  9 00:25:51 2012
@@ -240,6 +240,14 @@
   myfooint(*p); //expected-warning{{Use dynamically allocated memory after it is freed}}
 }
 
+void mallocFailedOrNot() {
+  int *p = malloc(12);
+  if (!p)
+    free(p);
+  else
+    free(p);
+}
+
 int *Gl;
 struct GlStTy {
   int *x;





More information about the cfe-commits mailing list