[cfe-commits] r150086 - /cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp

Anna Zaks ganna at apple.com
Wed Feb 8 12:13:28 PST 2012


Author: zaks
Date: Wed Feb  8 14:13:28 2012
New Revision: 150086

URL: http://llvm.org/viewvc/llvm-project?rev=150086&view=rev
Log:
[analyzer] MallocChecker: convert from using evalCall to
post visit of CallExpr.

In general, we should avoid using evalCall as it leads to interference
with other checkers.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=150086&r1=150085&r2=150086&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Feb  8 14:13:28 2012
@@ -66,10 +66,10 @@
 
 class RegionState {};
 
-class MallocChecker : public Checker<eval::Call,
-                                     check::DeadSymbols,
+class MallocChecker : public Checker<check::DeadSymbols,
                                      check::EndPath,
                                      check::PreStmt<ReturnStmt>,
+                                     check::PostStmt<CallExpr>,
                                      check::Location,
                                      check::Bind,
                                      eval::Assume>
@@ -83,8 +83,9 @@
 
 public:
   MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
+  void initIdentifierInfo(CheckerContext &C) const;
 
-  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
   void checkEndPath(CheckerContext &C) const;
   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
@@ -138,11 +139,7 @@
 }
 }
 
-bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
-  const FunctionDecl *FD = C.getCalleeDecl(CE);
-  if (!FD)
-    return false;
-
+void MallocChecker::initIdentifierInfo(CheckerContext &C) const {
   ASTContext &Ctx = C.getASTContext();
   if (!II_malloc)
     II_malloc = &Ctx.Idents.get("malloc");
@@ -152,30 +149,35 @@
     II_realloc = &Ctx.Idents.get("realloc");
   if (!II_calloc)
     II_calloc = &Ctx.Idents.get("calloc");
+}
+
+void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
+  const FunctionDecl *FD = C.getCalleeDecl(CE);
+  if (!FD)
+    return;
+  initIdentifierInfo(C);
 
   if (FD->getIdentifier() == II_malloc) {
     MallocMem(C, CE);
-    return true;
-  }
-
-  if (FD->getIdentifier() == II_free) {
-    FreeMem(C, CE);
-    return true;
+    return;
   }
-
   if (FD->getIdentifier() == II_realloc) {
     ReallocMem(C, CE);
-    return true;
+    return;
   }
 
   if (FD->getIdentifier() == II_calloc) {
     CallocMem(C, CE);
-    return true;
+    return;
+  }
+
+  if (FD->getIdentifier() == II_free) {
+    FreeMem(C, CE);
+    return;
   }
 
   // Check all the attributes, if there are any.
   // There can be multiple of these attributes.
-  bool rv = false;
   if (FD->hasAttrs()) {
     for (specific_attr_iterator<OwnershipAttr>
                   i = FD->specific_attr_begin<OwnershipAttr>(),
@@ -184,19 +186,16 @@
       switch ((*i)->getOwnKind()) {
       case OwnershipAttr::Returns: {
         MallocMemReturnsAttr(C, CE, *i);
-        rv = true;
         break;
       }
       case OwnershipAttr::Takes:
       case OwnershipAttr::Holds: {
         FreeMemAttr(C, CE, *i);
-        rv = true;
         break;
       }
       }
     }
   }
-  return rv;
 }
 
 void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
@@ -222,17 +221,14 @@
   C.addTransition(state);
 }
 
-ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,  
+ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
                                            const CallExpr *CE,
                                            SVal Size, SVal Init,
                                            ProgramStateRef state) {
-  unsigned Count = C.getCurrentBlockCount();
   SValBuilder &svalBuilder = C.getSValBuilder();
 
-  // Set the return value.
-  SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE,
-                                                 CE->getType(), Count);
-  state = state->BindExpr(CE, C.getLocationContext(), retVal);
+  // Get the return value.
+  SVal retVal = state->getSVal(CE, C.getLocationContext());
 
   // Fill the region with the initialization value.
   state = state->bindDefault(retVal, Init);
@@ -288,7 +284,7 @@
 
   // Check for null dereferences.
   if (!isa<Loc>(location))
-    return state;
+    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.
@@ -297,14 +293,14 @@
 
   // The explicit NULL case, no operation is performed.
   if (nullState && !notNullState)
-    return nullState;
+    return 0;
 
   assert(notNullState);
 
   // Unknown values could easily be okay
   // Undefined values are handled elsewhere
   if (ArgVal.isUnknownOrUndef())
-    return notNullState;
+    return 0;
 
   const MemRegion *R = ArgVal.getAsRegion();
   
@@ -312,7 +308,7 @@
   // Non-region locations (labels and fixed addresses) also shouldn't be freed.
   if (!R) {
     ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
-    return NULL;
+    return 0;
   }
   
   R = R->StripCasts();
@@ -320,11 +316,12 @@
   // Blocks might show up as heap data, but should not be free()d
   if (isa<BlockDataRegion>(R)) {
     ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
-    return NULL;
+    return 0;
   }
   
   const MemSpaceRegion *MS = R->getMemorySpace();
   
+  // TODO: Pessimize this. should be behinds a flag!
   // Parameters, locals, statics, and globals shouldn't be freed.
   if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
     // FIXME: at the time this code was written, malloc() regions were
@@ -336,14 +333,14 @@
     // False negatives are better than false positives.
     
     ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
-    return NULL;
+    return 0;
   }
   
   const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
   // Various cases could lead to non-symbol values here.
   // For now, ignore them.
   if (!SR)
-    return notNullState;
+    return 0;
 
   SymbolRef Sym = SR->getSymbol();
   const RefState *RS = state->get<RegionState>(Sym);
@@ -352,7 +349,7 @@
   // called on a pointer that does not get its pointee directly from malloc(). 
   // Full support of this requires inter-procedural analysis.
   if (!RS)
-    return notNullState;
+    return 0;
 
   // Check double free.
   if (RS->isReleased()) {
@@ -366,7 +363,7 @@
                                    BT_DoubleFree->getDescription(), N);
       C.EmitReport(R);
     }
-    return NULL;
+    return 0;
   }
 
   // Normal free.





More information about the cfe-commits mailing list