r228737 - [analyzer] Pass actual state to alloc/dealloc handling functions.

Anton Yartsev anton.yartsev at gmail.com
Tue Feb 10 12:13:08 PST 2015


Author: ayartsev
Date: Tue Feb 10 14:13:08 2015
New Revision: 228737

URL: http://llvm.org/viewvc/llvm-project?rev=228737&view=rev
Log:
[analyzer] Pass actual state to alloc/dealloc handling functions.

The state obtained from CheckerContext::getState() may be outdated by the time the alloc/dealloc handling function is called (e.g. the state was modified but the transition was not performed). State argument was added to all alloc/dealloc handling functions in order to get the latest state and to allow sequential calls to those functions.

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=228737&r1=228736&r2=228737&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue Feb 10 14:13:08 2015
@@ -254,20 +254,16 @@ private:
   ///@}
   ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
                                        const CallExpr *CE,
-                                       const OwnershipAttr* Att) const;
+                                       const OwnershipAttr* Att,
+                                       ProgramStateRef State) const;
   static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                                     const Expr *SizeEx, SVal Init,
-                                     ProgramStateRef State,
-                                     AllocationFamily Family = AF_Malloc) {
-    return MallocMemAux(C, CE,
-                        State->getSVal(SizeEx, C.getLocationContext()),
-                        Init, State, Family);
-  }
-
+                                      const Expr *SizeEx, SVal Init,
+                                      ProgramStateRef State,
+                                      AllocationFamily Family = AF_Malloc);
   static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                                     SVal SizeEx, SVal Init,
-                                     ProgramStateRef State,
-                                     AllocationFamily Family = AF_Malloc);
+                                      SVal SizeEx, SVal Init,
+                                      ProgramStateRef State,
+                                      AllocationFamily Family = AF_Malloc);
 
   // Check if this malloc() for special flags. At present that means M_ZERO or
   // __GFP_ZERO (in which case, treat it like calloc).
@@ -281,7 +277,8 @@ private:
                        AllocationFamily Family = AF_Malloc);
 
   ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
-                              const OwnershipAttr* Att) const;
+                              const OwnershipAttr* Att,
+                              ProgramStateRef State) const;
   ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
                              ProgramStateRef state, unsigned Num,
                              bool Hold,
@@ -295,8 +292,10 @@ private:
                              bool ReturnsNullOnFailure = false) const;
 
   ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
-                             bool FreesMemOnFailure) const;
-  static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
+                             bool FreesMemOnFailure, 
+                             ProgramStateRef State) const;
+  static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
+                                   ProgramStateRef State);
   
   ///\brief Check if the memory associated with this symbol was released.
   bool isReleased(SymbolRef Sym, CheckerContext &C) const;
@@ -732,11 +731,11 @@ void MallocChecker::checkPostStmt(const
         return;
       State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
     } else if (FunI == II_realloc) {
-      State = ReallocMem(C, CE, false);
+      State = ReallocMem(C, CE, false, State);
     } else if (FunI == II_reallocf) {
-      State = ReallocMem(C, CE, true);
+      State = ReallocMem(C, CE, true, State);
     } else if (FunI == II_calloc) {
-      State = CallocMem(C, CE);
+      State = CallocMem(C, CE, State);
     } else if (FunI == II_free) {
       State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
     } else if (FunI == II_strdup) {
@@ -778,11 +777,11 @@ void MallocChecker::checkPostStmt(const
       for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
         switch (I->getOwnKind()) {
         case OwnershipAttr::Returns:
-          State = MallocMemReturnsAttr(C, CE, I);
+          State = MallocMemReturnsAttr(C, CE, I, State);
           break;
         case OwnershipAttr::Takes:
         case OwnershipAttr::Holds:
-          State = FreeMemAttr(C, CE, I);
+          State = FreeMemAttr(C, CE, I, State);
           break;
         }
       }
@@ -919,15 +918,31 @@ void MallocChecker::checkPostObjCMessage
 
 ProgramStateRef
 MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
-                                    const OwnershipAttr *Att) const {
+                                    const OwnershipAttr *Att, 
+                                    ProgramStateRef State) const {
+  if (!State)
+    return nullptr;
+
   if (Att->getModule() != II_malloc)
     return nullptr;
 
   OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
   if (I != E) {
-    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State);
   }
-  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
+  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
+}
+
+ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
+                                            const CallExpr *CE,
+                                            const Expr *SizeEx, SVal Init,
+                                            ProgramStateRef State,
+                                            AllocationFamily Family) {
+  if (!State)
+    return nullptr;
+
+  return MallocMemAux(C, CE, State->getSVal(SizeEx, C.getLocationContext()),
+                      Init, State, Family);
 }
 
 ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
@@ -935,6 +950,8 @@ ProgramStateRef MallocChecker::MallocMem
                                            SVal Size, SVal Init,
                                            ProgramStateRef State,
                                            AllocationFamily Family) {
+  if (!State)
+    return nullptr;
 
   // We expect the malloc functions to return a pointer.
   if (!Loc::isLocType(CE->getType()))
@@ -976,6 +993,9 @@ ProgramStateRef MallocChecker::MallocUpd
                                                     const Expr *E,
                                                     ProgramStateRef State,
                                                     AllocationFamily Family) {
+  if (!State)
+    return nullptr;
+
   // Get the return value.
   SVal retVal = State->getSVal(E, C.getLocationContext());
 
@@ -992,11 +1012,14 @@ ProgramStateRef MallocChecker::MallocUpd
 
 ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
                                            const CallExpr *CE,
-                                           const OwnershipAttr *Att) const {
+                                           const OwnershipAttr *Att, 
+                                           ProgramStateRef State) const {
+  if (!State)
+    return nullptr;
+
   if (Att->getModule() != II_malloc)
     return nullptr;
 
-  ProgramStateRef State = C.getState();
   bool ReleasedAllocated = false;
 
   for (const auto &Arg : Att->args()) {
@@ -1011,15 +1034,18 @@ ProgramStateRef MallocChecker::FreeMemAt
 
 ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
                                           const CallExpr *CE,
-                                          ProgramStateRef state,
+                                          ProgramStateRef State,
                                           unsigned Num,
                                           bool Hold,
                                           bool &ReleasedAllocated,
                                           bool ReturnsNullOnFailure) const {
+  if (!State)
+    return nullptr;
+
   if (CE->getNumArgs() < (Num + 1))
     return nullptr;
 
-  return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
+  return FreeMemAux(C, CE->getArg(Num), CE, State, Hold,
                     ReleasedAllocated, ReturnsNullOnFailure);
 }
 
@@ -1152,6 +1178,9 @@ ProgramStateRef MallocChecker::FreeMemAu
                                           bool &ReleasedAllocated,
                                           bool ReturnsNullOnFailure) const {
 
+  if (!State)
+    return nullptr;
+
   SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
   if (!ArgVal.getAs<DefinedOrUnknownSVal>())
     return nullptr;
@@ -1655,14 +1684,17 @@ void MallocChecker::ReportDoubleDelete(C
 
 ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
                                           const CallExpr *CE,
-                                          bool FreesOnFail) const {
+                                          bool FreesOnFail,
+                                          ProgramStateRef State) const {
+  if (!State)
+    return nullptr;
+
   if (CE->getNumArgs() < 2)
     return nullptr;
 
-  ProgramStateRef state = C.getState();
   const Expr *arg0Expr = CE->getArg(0);
   const LocationContext *LCtx = C.getLocationContext();
-  SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
+  SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
   if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
     return nullptr;
   DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
@@ -1670,7 +1702,7 @@ ProgramStateRef MallocChecker::ReallocMe
   SValBuilder &svalBuilder = C.getSValBuilder();
 
   DefinedOrUnknownSVal PtrEQ =
-    svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
+    svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
 
   // Get the size argument. If there is no size arg then give up.
   const Expr *Arg1 = CE->getArg(1);
@@ -1678,20 +1710,20 @@ ProgramStateRef MallocChecker::ReallocMe
     return nullptr;
 
   // Get the value of the size argument.
-  SVal Arg1ValG = state->getSVal(Arg1, LCtx);
+  SVal Arg1ValG = State->getSVal(Arg1, LCtx);
   if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
     return nullptr;
   DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
 
   // Compare the size argument to 0.
   DefinedOrUnknownSVal SizeZero =
-    svalBuilder.evalEQ(state, Arg1Val,
+    svalBuilder.evalEQ(State, Arg1Val,
                        svalBuilder.makeIntValWithPtrWidth(0, false));
 
   ProgramStateRef StatePtrIsNull, StatePtrNotNull;
-  std::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
+  std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
   ProgramStateRef StateSizeIsZero, StateSizeNotZero;
-  std::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
+  std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
   // We only assume exceptional states if they are definitely true; if the
   // state is under-constrained, assume regular realloc behavior.
   bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
@@ -1711,7 +1743,7 @@ ProgramStateRef MallocChecker::ReallocMe
   // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
   assert(!PrtIsNull);
   SymbolRef FromPtr = arg0Val.getAsSymbol();
-  SVal RetVal = state->getSVal(CE, LCtx);
+  SVal RetVal = State->getSVal(CE, LCtx);
   SymbolRef ToPtr = RetVal.getAsSymbol();
   if (!FromPtr || !ToPtr)
     return nullptr;
@@ -1731,7 +1763,7 @@ ProgramStateRef MallocChecker::ReallocMe
 
   // Default behavior.
   if (ProgramStateRef stateFree =
-        FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) {
+        FreeMemAux(C, CE, State, 0, false, ReleasedAllocated)) {
 
     ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
                                                 UnknownVal(), stateFree);
@@ -1755,20 +1787,23 @@ ProgramStateRef MallocChecker::ReallocMe
   return nullptr;
 }
 
-ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
+ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE, 
+                                         ProgramStateRef State) {
+  if (!State)
+    return nullptr;
+
   if (CE->getNumArgs() < 2)
     return nullptr;
 
-  ProgramStateRef state = C.getState();
   SValBuilder &svalBuilder = C.getSValBuilder();
   const LocationContext *LCtx = C.getLocationContext();
-  SVal count = state->getSVal(CE->getArg(0), LCtx);
-  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
-  SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
+  SVal count = State->getSVal(CE->getArg(0), LCtx);
+  SVal elementSize = State->getSVal(CE->getArg(1), LCtx);
+  SVal TotalSize = svalBuilder.evalBinOp(State, BO_Mul, count, elementSize,
                                         svalBuilder.getContext().getSizeType());  
   SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
 
-  return MallocMemAux(C, CE, TotalSize, zeroVal, state);
+  return MallocMemAux(C, CE, TotalSize, zeroVal, State);
 }
 
 LeakInfo





More information about the cfe-commits mailing list