This revision was automatically updated to reflect the committed changes.
Closed by commit rGf3a28202ef58: [analyzer] Keep track of escaped locals 
(authored by xazax.hun).

Changed prior to commit:
  https://reviews.llvm.org/D71152?vs=232675&id=233124#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71152/new/

https://reviews.llvm.org/D71152

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/lib/StaticAnalyzer/Core/ProgramState.cpp
  clang/test/Analysis/symbol-escape.cpp

Index: clang/test/Analysis/symbol-escape.cpp
===================================================================
--- clang/test/Analysis/symbol-escape.cpp
+++ clang/test/Analysis/symbol-escape.cpp
@@ -31,3 +31,12 @@
   return Baz;
 }
 
+void save_ptr(int **);
+void delete_saved();
+
+void store_to_escaped_region() {
+  int *p;
+  save_ptr(&p);
+  p = new int;
+  delete_saved();
+} // no-warning
Index: clang/lib/StaticAnalyzer/Core/ProgramState.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -41,7 +41,8 @@
     Mgr.freeStates.push_back(s);
   }
 }
-}}
+} // namespace ento
+} // namespace clang
 
 ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
                  StoreRef st, GenericDataMap gdm)
@@ -209,6 +210,13 @@
   ProgramStateRef newState = makeWithStore(newStore);
 
   if (CausedByPointerEscape) {
+    for (const MemRegion *R : Invalidated) {
+      if (!R->hasStackStorage())
+        continue;
+
+      newState = Eng.processLocalRegionEscape(newState, R->getBaseRegion());
+    }
+
     newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
                                                  TopLevelInvalidated,
                                                  Call,
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -193,6 +193,8 @@
 REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
                                  ObjectsUnderConstructionMap)
 
+REGISTER_SET_WITH_PROGRAMSTATE(EscapedLocals, const MemRegion *)
+
 //===----------------------------------------------------------------------===//
 // Engine construction and deletion.
 //===----------------------------------------------------------------------===//
@@ -723,6 +725,12 @@
       SymReaper.markLive(MR);
   }
 
+  EscapedLocalsTy EscapedRegions = CleanedState->get<EscapedLocals>();
+  for (const MemRegion *MR : EscapedRegions) {
+    if (!SymReaper.isLiveRegion(MR))
+      CleanedState = CleanedState->remove<EscapedLocals>(MR);
+  }
+
   getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
 
   // Create a state in which dead bindings are removed from the environment
@@ -1194,6 +1202,11 @@
       State, Scanner.getSymbols(), /*CallEvent*/ nullptr, K, nullptr);
 }
 
+ProgramStateRef ExprEngine::processLocalRegionEscape(ProgramStateRef State,
+                                                     const MemRegion *R) const {
+  return State->add<EscapedLocals>(R);
+}
+
 void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
                        ExplodedNodeSet &DstTop) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -2680,7 +2693,8 @@
 
 // A value escapes in four 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.
+// (2) We are binding to a MemRegion that does not have stack storage
+//     or the stack storage is escaped.
 // (3) We are binding to a top-level parameter region with a non-trivial
 //     destructor. We won't see the destructor during analysis, but it's there.
 // (4) We are binding to a MemRegion with stack storage that the store
@@ -2691,7 +2705,7 @@
 
   // Cases (1) and (2).
   const MemRegion *MR = Loc.getAsRegion();
-  if (!MR || !MR->hasStackStorage())
+  if (!MR || !MR->hasStackStorage() || State->contains<EscapedLocals>(MR))
     return escapeValue(State, Val, PSK_EscapeOnBind);
 
   // Case (3).
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -149,14 +149,16 @@
   }
 
   virtual ProgramStateRef
-  processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0;
+  processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val,
+                              const LocationContext *LCtx) = 0;
+
+  virtual ProgramStateRef notifyCheckersOfPointerEscape(
+      ProgramStateRef State, const InvalidatedSymbols *Invalidated,
+      ArrayRef<const MemRegion *> ExplicitRegions, const CallEvent *Call,
+      RegionAndSymbolInvalidationTraits &HTraits) = 0;
 
   virtual ProgramStateRef
-  notifyCheckersOfPointerEscape(ProgramStateRef State,
-                           const InvalidatedSymbols *Invalidated,
-                           ArrayRef<const MemRegion *> ExplicitRegions,
-                           const CallEvent *Call,
-                           RegionAndSymbolInvalidationTraits &HTraits) = 0;
+  processLocalRegionEscape(ProgramStateRef State, const MemRegion *R) const = 0;
 
   /// printJson - Called by ProgramStateManager to print checker-specific data.
   virtual void printJson(raw_ostream &Out, ProgramStateRef State,
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -27,7 +27,7 @@
 
 namespace llvm {
 class APSInt;
-}
+} // namespace llvm
 
 namespace clang {
 class ASTContext;
@@ -872,8 +872,8 @@
   bool scan(const SymExpr *sym);
 };
 
-} // end ento namespace
+} // namespace ento
 
-} // end clang namespace
+} // namespace clang
 
 #endif
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -627,6 +627,9 @@
                            const CallEvent *Call,
                            RegionAndSymbolInvalidationTraits &ITraits) override;
 
+  ProgramStateRef processLocalRegionEscape(ProgramStateRef State,
+                                           const MemRegion *R) const override;
+
   /// A simple wrapper when you only need to notify checkers of pointer-escape
   /// of a single value.
   ProgramStateRef escapeValue(ProgramStateRef State, SVal V,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to