[cfe-commits] r170625 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/ include/clang/StaticAnalyzer/Core/PathSensitive/ lib/StaticAnalyzer/Checkers/ lib/StaticAnalyzer/Core/

Anna Zaks ganna at apple.com
Wed Dec 19 16:38:25 PST 2012


Author: zaks
Date: Wed Dec 19 18:38:25 2012
New Revision: 170625

URL: http://llvm.org/viewvc/llvm-project?rev=170625&view=rev
Log:
[analyzer] Add the pointer escaped callback.

Instead of using several callbacks to identify the pointer escape event,
checkers now can register for the checkPointerEscape.

Converted the Malloc checker to use the new callback.
SimpleStreamChecker will be converted next.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Wed Dec 19 18:38:25 2012
@@ -293,7 +293,7 @@
   static ProgramStateRef 
   _checkRegionChanges(void *checker,
                       ProgramStateRef state,
-                      const StoreManager::InvalidatedSymbols *invalidated,
+                      const InvalidatedSymbols *invalidated,
                       ArrayRef<const MemRegion *> Explicits,
                       ArrayRef<const MemRegion *> Regions,
                       const CallEvent *Call) {
@@ -317,6 +317,27 @@
   }
 };
 
+class PointerEscape {
+  template <typename CHECKER>
+  static ProgramStateRef
+  _checkPointerEscape(void *checker,
+                     ProgramStateRef State,
+                     const InvalidatedSymbols &Escaped,
+                     const CallEvent *Call) {
+    return ((const CHECKER *)checker)->checkPointerEscape(State, 
+                                                          Escaped, 
+                                                          Call);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForPointerEscape(
+          CheckerManager::CheckPointerEscapeFunc(checker,
+                                                _checkPointerEscape<CHECKER>));
+  }
+};
+
 template <typename EVENT>
 class Event {
   template <typename CHECKER>

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Wed Dec 19 18:38:25 2012
@@ -310,11 +310,27 @@
   ///   by a call.
   ProgramStateRef
   runCheckersForRegionChanges(ProgramStateRef state,
-                            const StoreManager::InvalidatedSymbols *invalidated,
+                              const InvalidatedSymbols *invalidated,
                               ArrayRef<const MemRegion *> ExplicitRegions,
                               ArrayRef<const MemRegion *> Regions,
                               const CallEvent *Call);
 
+  /// \brief Run checkers when pointers escape.
+  ///
+  /// This notifies the checkers about pointer escape, which occurs whenever
+  /// the analzyer cannot track the symbol any more. For example, as a
+  /// result of assigning a pointer into a global or when it's passed to a 
+  /// function call the analyzer cannot model.
+  /// 
+  /// \param State The state at the point of escape.
+  /// \param Escaped The list of escaped symbols.
+  /// \param Call The corresponding CallEvent, if the symbols escape as 
+  /// parameters to the given call.
+  /// \returns Checkers can modify the state by returning a new one.
+  ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State,
+                                             const InvalidatedSymbols &Escaped,
+                                             const CallEvent *Call);
+
   /// \brief Run checkers for handling assumptions on symbolic values.
   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
                                                SVal Cond, bool Assumption);
@@ -393,13 +409,18 @@
   typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
   
   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
-                                const StoreManager::InvalidatedSymbols *symbols,
+                                const InvalidatedSymbols *symbols,
                                 ArrayRef<const MemRegion *> ExplicitRegions,
                                 ArrayRef<const MemRegion *> Regions,
                                 const CallEvent *Call)>
       CheckRegionChangesFunc;
   
   typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
+
+  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
+                                     const InvalidatedSymbols &Escaped,
+                                     const CallEvent *Call)>
+      CheckPointerEscapeFunc;
   
   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
                                           const SVal &cond, bool assumption)>
@@ -441,6 +462,8 @@
   void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
                                  WantsRegionChangeUpdateFunc wantUpdateFn);
 
+  void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
+
   void _registerForEvalAssume(EvalAssumeFunc checkfn);
 
   void _registerForEvalCall(EvalCallFunc checkfn);
@@ -566,6 +589,8 @@
   };
   std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
 
+  std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
+
   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
 
   std::vector<EvalCallFunc> EvalCallCheckers;

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Wed Dec 19 18:38:25 2012
@@ -262,7 +262,7 @@
   ///  to the store. Used to update checkers that track region values.
   ProgramStateRef 
   processRegionChanges(ProgramStateRef state,
-                       const StoreManager::InvalidatedSymbols *invalidated,
+                       const InvalidatedSymbols *invalidated,
                        ArrayRef<const MemRegion *> ExplicitRegions,
                        ArrayRef<const MemRegion *> Regions,
                        const CallEvent *Call);
@@ -459,6 +459,16 @@
                 SVal location, SVal Val, bool atDeclInit = false,
                 const ProgramPoint *PP = 0);
 
+  ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
+                                              SVal Loc, SVal Val);
+
+  ProgramStateRef processPointerEscapedOnInvalidateRegions(
+                            ProgramStateRef State,
+                            const InvalidatedSymbols *Invalidated,
+                            ArrayRef<const MemRegion *> ExplicitRegions,
+                            ArrayRef<const MemRegion *> Regions,
+                            const CallEvent *Call);
+
 public:
   // FIXME: 'tag' should be removed, and a LocationContext should be used
   // instead.

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Wed Dec 19 18:38:25 2012
@@ -213,13 +213,25 @@
 
   ProgramStateRef killBinding(Loc LV) const;
 
-  /// invalidateRegions - Returns the state with bindings for the given regions
-  ///  cleared from the store. The regions are provided as a continuous array
-  ///  from Begin to End. Optionally invalidates global regions as well.
+  /// \brief Returns the state with bindings for the given regions
+  ///  cleared from the store.
+  ///
+  /// Optionally invalidates global regions as well.
+  ///
+  /// \param Regions the set of regions to be invalidated.
+  /// \param E the expression that caused the invalidation.
+  /// \param BlockCount the current basic block count.
+  /// \param ResultsInPointerEscape the flag is set to true when
+  /// the invalidation is due to escape of a symbol (representing a pointer).
+  /// For example, due to it being passed as an argument in a call.
+  /// \param IS the set of invalidated symbols.
+  /// \param If Call is non-null, the invalidated regions were directly
+  /// invalidated by the call - as parameters.
   ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions,
                                const Expr *E, unsigned BlockCount,
                                const LocationContext *LCtx,
-                               StoreManager::InvalidatedSymbols *IS = 0,
+                               bool ResultsInPointerEscape,
+                               InvalidatedSymbols *IS = 0,
                                const CallEvent *Call = 0) const;
 
   /// enterStackFrame - Returns the state for entry to the given stack frame,
@@ -395,7 +407,8 @@
   invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
                         const Expr *E, unsigned BlockCount,
                         const LocationContext *LCtx,
-                        StoreManager::InvalidatedSymbols &IS,
+                        bool ResultsInSymbolEscape,
+                        InvalidatedSymbols &IS,
                         const CallEvent *Call) const;
 };
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Wed Dec 19 18:38:25 2012
@@ -35,6 +35,8 @@
 class ProgramStateManager;
 class ScanReachableSymbols;
 
+typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+
 class StoreManager {
 protected:
   SValBuilder &svalBuilder;
@@ -168,7 +170,6 @@
   /// associated with the object is recycled.
   virtual void decrementReferenceCount(Store store) {}
 
-  typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
   typedef SmallVector<const MemRegion *, 8> InvalidatedRegions;
 
   /// invalidateRegions - Clears out the specified regions from the store,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Wed Dec 19 18:38:25 2012
@@ -104,7 +104,7 @@
   /// made to the store. Used to update checkers that track region values.
   virtual ProgramStateRef 
   processRegionChanges(ProgramStateRef state,
-                       const StoreManager::InvalidatedSymbols *invalidated,
+                       const InvalidatedSymbols *invalidated,
                        ArrayRef<const MemRegion *> ExplicitRegions,
                        ArrayRef<const MemRegion *> Regions,
                        const CallEvent *Call) = 0;
@@ -116,6 +116,16 @@
     return processRegionChanges(state, 0, MR, MR, 0);
   }
 
+  virtual ProgramStateRef
+  processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
+
+  virtual ProgramStateRef
+  processPointerEscapedOnInvalidateRegions(ProgramStateRef State,
+                           const InvalidatedSymbols *Invalidated,
+                           ArrayRef<const MemRegion *> ExplicitRegions,
+                           ArrayRef<const MemRegion *> Regions,
+                           const CallEvent *Call) = 0;
+
   /// printState - Called by ProgramStateManager to print checker-specific data.
   virtual void printState(raw_ostream &Out, ProgramStateRef State,
                           const char *NL, const char *Sep) = 0;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Wed Dec 19 18:38:25 2012
@@ -64,7 +64,7 @@
 
   ProgramStateRef 
     checkRegionChanges(ProgramStateRef state,
-                       const StoreManager::InvalidatedSymbols *,
+                       const InvalidatedSymbols *,
                        ArrayRef<const MemRegion *> ExplicitRegions,
                        ArrayRef<const MemRegion *> Regions,
                        const CallEvent *Call) const;
@@ -816,7 +816,8 @@
 
     // Invalidate this region.
     const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
-    return state->invalidateRegions(R, E, C.blockCount(), LCtx);
+    return state->invalidateRegions(R, E, C.blockCount(), LCtx,
+                                    /*ResultsInPointerEscape*/ false);
   }
 
   // If we have a non-region value by chance, just remove the binding.
@@ -1873,7 +1874,7 @@
 
 ProgramStateRef 
 CStringChecker::checkRegionChanges(ProgramStateRef state,
-                                   const StoreManager::InvalidatedSymbols *,
+                                   const InvalidatedSymbols *,
                                    ArrayRef<const MemRegion *> ExplicitRegions,
                                    ArrayRef<const MemRegion *> Regions,
                                    const CallEvent *Call) const {

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp Wed Dec 19 18:38:25 2012
@@ -51,6 +51,7 @@
                                        eval::Assume,
                                        check::LiveSymbols,
                                        check::RegionChanges,
+                                       check::PointerEscape,
                                        check::Event<ImplicitNullDerefEvent>,
                                        check::ASTDecl<FunctionDecl> > {
 public:
@@ -246,13 +247,31 @@
   /// check::RegionChanges
   ProgramStateRef 
     checkRegionChanges(ProgramStateRef State,
-                       const StoreManager::InvalidatedSymbols *Invalidated,
+                       const InvalidatedSymbols *Invalidated,
                        ArrayRef<const MemRegion *> ExplicitRegions,
                        ArrayRef<const MemRegion *> Regions,
                        const CallEvent *Call) const {
     return State;
   }
 
+  /// \brief Called when pointers escape.
+  ///
+  /// This notifies the checkers about pointer escape, which occurs whenever
+  /// the analzyer cannot track the symbol any more. For example, as a
+  /// result of assigning a pointer into a global or when it's passed to a 
+  /// function call the analyzer cannot model.
+  /// 
+  /// \param State The state at the point of escape.
+  /// \param Escaped The list of escaped symbols.
+  /// \param Call The corresponding CallEvent, if the symbols escape as 
+  /// parameters to the given call.
+  /// \returns Checkers can modify the state by returning a new state.
+  ProgramStateRef checkPointerEscape(ProgramStateRef State,
+                                     const InvalidatedSymbols &Escaped,
+                                     const CallEvent *Call) const {
+    return State;
+  }
+
   /// check::Event<ImplicitNullDerefEvent>
   void checkEvent(ImplicitNullDerefEvent Event) const {}
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Dec 19 18:38:25 2012
@@ -103,15 +103,14 @@
 typedef std::pair<const Stmt*, const MemRegion*> LeakInfo;
 
 class MallocChecker : public Checker<check::DeadSymbols,
+                                     check::PointerEscape,
                                      check::PreStmt<ReturnStmt>,
                                      check::PreStmt<CallExpr>,
                                      check::PostStmt<CallExpr>,
                                      check::PostStmt<BlockExpr>,
                                      check::PostObjCMessage,
                                      check::Location,
-                                     check::Bind,
-                                     eval::Assume,
-                                     check::RegionChanges>
+                                     eval::Assume>
 {
   mutable OwningPtr<BugType> BT_DoubleFree;
   mutable OwningPtr<BugType> BT_Leak;
@@ -143,17 +142,10 @@
                             bool Assumption) const;
   void checkLocation(SVal l, bool isLoad, const Stmt *S,
                      CheckerContext &C) const;
-  void checkBind(SVal location, SVal val, const Stmt*S,
-                 CheckerContext &C) const;
-  ProgramStateRef
-  checkRegionChanges(ProgramStateRef state,
-                     const StoreManager::InvalidatedSymbols *invalidated,
-                     ArrayRef<const MemRegion *> ExplicitRegions,
-                     ArrayRef<const MemRegion *> Regions,
-                     const CallEvent *Call) const;
-  bool wantsRegionChangeUpdate(ProgramStateRef state) const {
-    return true;
-  }
+
+  ProgramStateRef checkPointerEscape(ProgramStateRef State,
+                                    const InvalidatedSymbols &Escaped,
+                                    const CallEvent *Call) const;
 
   void printState(raw_ostream &Out, ProgramStateRef State,
                   const char *NL, const char *Sep) const;
@@ -1254,51 +1246,6 @@
     checkUseAfterFree(Sym, C, S);
 }
 
-//===----------------------------------------------------------------------===//
-// Check various ways a symbol can be invalidated.
-// TODO: This logic (the next 3 functions) is copied/similar to the
-// RetainRelease checker. We might want to factor this out.
-//===----------------------------------------------------------------------===//
-
-// Stop tracking symbols when a value escapes as a result of checkBind.
-// A value escapes in three possible cases:
-// (1) we are binding to something that is not a memory region.
-// (2) we are binding to a memregion that does not have stack storage
-// (3) we are binding to a memregion with stack storage that the store
-//     does not understand.
-void MallocChecker::checkBind(SVal loc, SVal val, const Stmt *S,
-                              CheckerContext &C) const {
-  // Are we storing to something that causes the value to "escape"?
-  bool escapes = true;
-  ProgramStateRef state = C.getState();
-
-  if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) {
-    escapes = !regionLoc->getRegion()->hasStackStorage();
-
-    if (!escapes) {
-      // To test (3), generate a new state with the binding added.  If it is
-      // the same state, then it escapes (since the store cannot represent
-      // the binding).
-      // Do this only if we know that the store is not supposed to generate the
-      // same state.
-      SVal StoredVal = state->getSVal(regionLoc->getRegion());
-      if (StoredVal != val)
-        escapes = (state == (state->bindLoc(*regionLoc, val)));
-    }
-  }
-
-  // If our store can represent the binding and we aren't storing to something
-  // that doesn't have local storage then just return and have the simulation
-  // state continue as is.
-  if (!escapes)
-      return;
-
-  // Otherwise, find all symbols referenced by 'val' that we are tracking
-  // and stop tracking them.
-  state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
-  C.addTransition(state);
-}
-
 // If a symbolic region is assumed to NULL (or another constant), stop tracking
 // it - assuming that allocation failed on this path.
 ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
@@ -1485,39 +1432,19 @@
   return true;
 }
 
-// If the symbol we are tracking is invalidated, but not explicitly (ex: the &p
-// escapes, when we are tracking p), do not track the symbol as we cannot reason
-// about it anymore.
-ProgramStateRef
-MallocChecker::checkRegionChanges(ProgramStateRef State,
-                            const StoreManager::InvalidatedSymbols *invalidated,
-                                    ArrayRef<const MemRegion *> ExplicitRegions,
-                                    ArrayRef<const MemRegion *> Regions,
-                                    const CallEvent *Call) const {
-  if (!invalidated || invalidated->empty())
+ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
+                                             const InvalidatedSymbols &Escaped,
+                                             const CallEvent *Call) const {
+  // If we know that the call does not free memory, keep tracking the top
+  // level arguments.       
+  if (Call && doesNotFreeMemory(Call, State))
     return State;
-  llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
 
-  // If it's a call which might free or reallocate memory, we assume that all
-  // regions (explicit and implicit) escaped.
-
-  // Otherwise, whitelist explicit pointers; we still can track them.
-  if (!Call || doesNotFreeMemory(Call, State)) {
-    for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
-        E = ExplicitRegions.end(); I != E; ++I) {
-      if (const SymbolicRegion *R = (*I)->StripCasts()->getAs<SymbolicRegion>())
-        WhitelistedSymbols.insert(R->getSymbol());
-    }
-  }
-
-  for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
-       E = invalidated->end(); I!=E; ++I) {
+  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+                                          E = Escaped.end();
+                                          I != E; ++I) {
     SymbolRef sym = *I;
-    if (WhitelistedSymbols.count(sym))
-      continue;
-    // The symbol escaped. Note, we assume that if the symbol is released,
-    // passing it out will result in a use after free. We also keep tracking
-    // relinquished symbols.
+
     if (const RefState *RS = State->get<RegionState>(sym)) {
       if (RS->isAllocated())
         State = State->remove<RegionState>(sym);

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Wed Dec 19 18:38:25 2012
@@ -2512,7 +2512,7 @@
 
   ProgramStateRef 
   checkRegionChanges(ProgramStateRef state,
-                     const StoreManager::InvalidatedSymbols *invalidated,
+                     const InvalidatedSymbols *invalidated,
                      ArrayRef<const MemRegion *> ExplicitRegions,
                      ArrayRef<const MemRegion *> Regions,
                      const CallEvent *Call) const;
@@ -3176,7 +3176,8 @@
       Binding = getRefBinding(state, Sym);
 
     // Invalidate the argument region.
-    state = state->invalidateRegions(ArgRegion, CE, C.blockCount(), LCtx);
+    state = state->invalidateRegions(ArgRegion, CE, C.blockCount(), LCtx,
+                                     /*ResultsInPointerEscape*/ false);
 
     // Restore the refcount status of the argument.
     if (Binding)
@@ -3443,7 +3444,7 @@
 
 ProgramStateRef 
 RetainCountChecker::checkRegionChanges(ProgramStateRef state,
-                            const StoreManager::InvalidatedSymbols *invalidated,
+                                    const InvalidatedSymbols *invalidated,
                                     ArrayRef<const MemRegion *> ExplicitRegions,
                                     ArrayRef<const MemRegion *> Regions,
                                     const CallEvent *Call) const {
@@ -3457,7 +3458,7 @@
       WhitelistedSymbols.insert(SR->getSymbol());
   }
 
-  for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+  for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
        E = invalidated->end(); I!=E; ++I) {
     SymbolRef sym = *I;
     if (WhitelistedSymbols.count(sym))

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp Wed Dec 19 18:38:25 2012
@@ -87,7 +87,7 @@
   /// Deal with symbol escape as a byproduct of a region change.
   ProgramStateRef
   checkRegionChanges(ProgramStateRef state,
-                     const StoreManager::InvalidatedSymbols *invalidated,
+                     const InvalidatedSymbols *invalidated,
                      ArrayRef<const MemRegion *> ExplicitRegions,
                      ArrayRef<const MemRegion *> Regions,
                      const CallEvent *Call) const;
@@ -304,7 +304,7 @@
 // we cannot reason about it anymore.
 ProgramStateRef
 SimpleStreamChecker::checkRegionChanges(ProgramStateRef State,
-    const StoreManager::InvalidatedSymbols *invalidated,
+    const InvalidatedSymbols *invalidated,
     ArrayRef<const MemRegion *> ExplicitRegions,
     ArrayRef<const MemRegion *> Regions,
     const CallEvent *Call) const {
@@ -324,7 +324,7 @@
     }
   }
 
-  for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+  for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
        E = invalidated->end(); I!=E; ++I) {
     SymbolRef sym = *I;
     if (WhitelistedSymbols.count(sym))

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Wed Dec 19 18:38:25 2012
@@ -199,6 +199,7 @@
   //  global variables.
   return Result->invalidateRegions(RegionsToInvalidate, getOriginExpr(),
                                    BlockCount, getLocationContext(),
+                                   /*ResultsInPointerEscape*/ true,
                                    /*Symbols=*/0, this);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Wed Dec 19 18:38:25 2012
@@ -469,10 +469,10 @@
 /// \brief Run checkers for region changes.
 ProgramStateRef 
 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
-                            const StoreManager::InvalidatedSymbols *invalidated,
+                                    const InvalidatedSymbols *invalidated,
                                     ArrayRef<const MemRegion *> ExplicitRegions,
-                                          ArrayRef<const MemRegion *> Regions,
-                                          const CallEvent *Call) {
+                                    ArrayRef<const MemRegion *> Regions,
+                                    const CallEvent *Call) {
   for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
     // If any checker declares the state infeasible (or if it starts that way),
     // bail out.
@@ -484,6 +484,21 @@
   return state;
 }
 
+/// \brief Run checkers to process symbol escape event.
+ProgramStateRef
+CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
+                                           const InvalidatedSymbols &Escaped,
+                                           const CallEvent *Call) {
+  for (unsigned i = 0, e = PointerEscapeCheckers.size(); i != e; ++i) {
+    // If any checker declares the state infeasible (or if it starts that way),
+    // bail out.
+    if (!State)
+      return NULL;
+    State = PointerEscapeCheckers[i](State, Escaped, Call);
+  }
+  return State;
+}
+
 /// \brief Run checkers for handling assumptions on symbolic values.
 ProgramStateRef 
 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
@@ -641,6 +656,10 @@
   RegionChangesCheckers.push_back(info);
 }
 
+void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
+  PointerEscapeCheckers.push_back(checkfn);
+}
+
 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
   EvalAssumeCheckers.push_back(checkfn);
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Dec 19 18:38:25 2012
@@ -199,7 +199,7 @@
 
 ProgramStateRef 
 ExprEngine::processRegionChanges(ProgramStateRef state,
-                            const StoreManager::InvalidatedSymbols *invalidated,
+                                 const InvalidatedSymbols *invalidated,
                                  ArrayRef<const MemRegion *> Explicits,
                                  ArrayRef<const MemRegion *> Regions,
                                  const CallEvent *Call) {
@@ -1588,6 +1588,111 @@
   }
 }
 
+namespace {
+class CollectReachableSymbolsCallback : public SymbolVisitor {
+  InvalidatedSymbols Symbols;
+public:
+  CollectReachableSymbolsCallback(ProgramStateRef State) {}
+  const InvalidatedSymbols &getSymbols() const { return Symbols; }
+
+  bool VisitSymbol(SymbolRef Sym) {
+    Symbols.insert(Sym);
+    return true;
+  }
+};
+} // end anonymous namespace
+
+/// Call PointerEscape callback when a value escapes as a result of bind.
+/// A value escapes in three possible cases:
+/// (1) we are binding to something that is not a memory region.
+/// (2) we are binding to a memregion that does not have stack storage
+/// (3) we are binding to a memregion with stack storage that the store
+///     does not understand.
+ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
+                                                       SVal Loc, SVal Val) {
+  // Are we storing to something that causes the value to "escape"?
+  bool escapes = true;
+
+  // TODO: Move to StoreManager.
+  if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&Loc)) {
+    escapes = !regionLoc->getRegion()->hasStackStorage();
+
+    if (!escapes) {
+      // To test (3), generate a new state with the binding added.  If it is
+      // the same state, then it escapes (since the store cannot represent
+      // the binding).
+      // Do this only if we know that the store is not supposed to generate the
+      // same state.
+      SVal StoredVal = State->getSVal(regionLoc->getRegion());
+      if (StoredVal != Val)
+        escapes = (State == (State->bindLoc(*regionLoc, Val)));
+    }
+  }
+
+  // If our store can represent the binding and we aren't storing to something
+  // that doesn't have local storage then just return and have the simulation
+  // state continue as is.
+  if (!escapes)
+    return State;
+
+  // Otherwise, find all symbols referenced by 'val' that we are tracking
+  // and stop tracking them.
+  CollectReachableSymbolsCallback Scanner =
+      State->scanReachableSymbols<CollectReachableSymbolsCallback>(Val);
+  const InvalidatedSymbols &EscapedSymbols = Scanner.getSymbols();
+  State = getCheckerManager().runCheckersForPointerEscape(State,
+                                                          EscapedSymbols,
+                                                          /*CallEvent*/ 0);
+
+  return State;
+}
+
+/// Call PointerEscape callback when a value escapes as a result of
+/// region invalidation.
+ProgramStateRef 
+ExprEngine::processPointerEscapedOnInvalidateRegions(ProgramStateRef State,
+    const InvalidatedSymbols *Invalidated,
+    ArrayRef<const MemRegion *> ExplicitRegions,
+    ArrayRef<const MemRegion *> Regions,
+    const CallEvent *Call) {
+  
+  if (!Invalidated || Invalidated->empty())
+    return State;
+
+  if (!Call)
+    return getCheckerManager().runCheckersForPointerEscape(State,
+                                                           *Invalidated, 0);
+    
+  // If the symbols were invalidated by a call, we want to find out which ones 
+  // were invalidated directly due to being arguments to the call.
+  InvalidatedSymbols SymbolsDirectlyInvalidated;
+  for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+      E = ExplicitRegions.end(); I != E; ++I) {
+    if (const SymbolicRegion *R = (*I)->StripCasts()->getAs<SymbolicRegion>())
+      SymbolsDirectlyInvalidated.insert(R->getSymbol());
+  }
+
+  InvalidatedSymbols SymbolsIndirectlyInvalidated;
+  for (InvalidatedSymbols::const_iterator I=Invalidated->begin(),
+      E = Invalidated->end(); I!=E; ++I) {
+    SymbolRef sym = *I;
+    if (SymbolsDirectlyInvalidated.count(sym))
+      continue;
+    SymbolsIndirectlyInvalidated.insert(sym);
+  }
+
+  if (!SymbolsDirectlyInvalidated.empty())
+    State = getCheckerManager().runCheckersForPointerEscape(State,
+        SymbolsDirectlyInvalidated, Call);
+
+  // Notify about the symbols that get indirectly invalidated by the call.
+  if (!SymbolsIndirectlyInvalidated.empty())
+    State = getCheckerManager().runCheckersForPointerEscape(State,
+        SymbolsIndirectlyInvalidated, /*CallEvent*/ 0);
+
+  return State;
+}
+
 /// evalBind - Handle the semantics of binding a value to a specific location.
 ///  This method is used by evalStore and (soon) VisitDeclStmt, and others.
 void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
@@ -1605,27 +1710,33 @@
   getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
                                          StoreE, *this, *PP);
 
+
+  StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
+
   // If the location is not a 'Loc', it will already be handled by
   // the checkers.  There is nothing left to do.
   if (!isa<Loc>(location)) {
-    Dst = CheckedSet;
+    const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/0, /*tag*/0);
+    ProgramStateRef state = Pred->getState();
+    state = processPointerEscapedOnBind(state, location, Val);
+    Bldr.generateNode(L, state, Pred);
     return;
   }
   
-  ExplodedNodeSet TmpDst;
-  StmtNodeBuilder Bldr(CheckedSet, TmpDst, *currBldrCtx);
 
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
        I!=E; ++I) {
     ExplodedNode *PredI = *I;
     ProgramStateRef state = PredI->getState();
     
+    state = processPointerEscapedOnBind(state, location, Val);
+
     // When binding the value, pass on the hint that this is a initialization.
     // For initializations, we do not need to inform clients of region
     // changes.
     state = state->bindLoc(cast<Loc>(location),
                            Val, /* notifyChanges = */ !atDeclInit);
-    
+
     const MemRegion *LocReg = 0;
     if (loc::MemRegionVal *LocRegVal = dyn_cast<loc::MemRegionVal>(&location)) {
       LocReg = LocRegVal->getRegion();
@@ -1634,7 +1745,6 @@
     const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
     Bldr.generateNode(L, state, PredI);
   }
-  Dst.insert(TmpDst);
 }
 
 /// evalStore - Handle the semantics of a store via an assignment.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Wed Dec 19 18:38:25 2012
@@ -144,31 +144,41 @@
 ProgramState::invalidateRegions(ArrayRef<const MemRegion *> Regions,
                                 const Expr *E, unsigned Count,
                                 const LocationContext *LCtx,
-                                StoreManager::InvalidatedSymbols *IS,
+                                bool ResultsInPointerEscape,
+                                InvalidatedSymbols *IS,
                                 const CallEvent *Call) const {
   if (!IS) {
-    StoreManager::InvalidatedSymbols invalidated;
+    InvalidatedSymbols invalidated;
     return invalidateRegionsImpl(Regions, E, Count, LCtx,
+                                 ResultsInPointerEscape,
                                  invalidated, Call);
   }
-  return invalidateRegionsImpl(Regions, E, Count, LCtx, *IS, Call);
+  return invalidateRegionsImpl(Regions, E, Count, LCtx, ResultsInPointerEscape,
+                               *IS, Call);
 }
 
 ProgramStateRef 
 ProgramState::invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
                                     const Expr *E, unsigned Count,
                                     const LocationContext *LCtx,
-                                    StoreManager::InvalidatedSymbols &IS,
+                                    bool ResultsInPointerEscape,
+                                    InvalidatedSymbols &IS,
                                     const CallEvent *Call) const {
   ProgramStateManager &Mgr = getStateManager();
   SubEngine* Eng = Mgr.getOwningEngine();
  
-  if (Eng && Eng->wantsRegionChangeUpdate(this)) {
+  if (Eng) {
     StoreManager::InvalidatedRegions Invalidated;
     const StoreRef &newStore
       = Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS,
                                         Call, &Invalidated);
+
     ProgramStateRef newState = makeWithStore(newStore);
+
+    if (ResultsInPointerEscape)
+      newState = Eng->processPointerEscapedOnInvalidateRegions(newState,
+                                               &IS, Regions, Invalidated, Call);
+
     return Eng->processRegionChanges(newState, &IS, Regions, Invalidated, Call);
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=170625&r1=170624&r2=170625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Wed Dec 19 18:38:25 2012
@@ -811,7 +811,7 @@
   const Expr *Ex;
   unsigned Count;
   const LocationContext *LCtx;
-  StoreManager::InvalidatedSymbols &IS;
+  InvalidatedSymbols &IS;
   StoreManager::InvalidatedRegions *Regions;
 public:
   invalidateRegionsWorker(RegionStoreManager &rm,
@@ -819,7 +819,7 @@
                           RegionBindingsRef b,
                           const Expr *ex, unsigned count,
                           const LocationContext *lctx,
-                          StoreManager::InvalidatedSymbols &is,
+                          InvalidatedSymbols &is,
                           StoreManager::InvalidatedRegions *r,
                           bool includeGlobals)
     : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals),





More information about the cfe-commits mailing list