xazax.hun created this revision.
xazax.hun added reviewers: NoQ, Szelethus, baloghadamsoftware, dcoughlin, 
haowei.
xazax.hun added a project: clang.
Herald added subscribers: Charusso, gamesh411, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet.
xazax.hun added a comment.

So some of the questions that came to my mind:

1. Should this be exposed to the checkers?
2. Where should we actually have this trait registered? ProgramState? 
ExprEngine? Both of them need access, and due to layering I feel like it cannot 
be in ExprEngine but I might be wrong.


This is working progress but I wanted to share early to discuss the direction.

This looks relatively painless so far, but note that the locals are not cleaned 
up from the state just yet.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71152

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.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,13 @@
   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
@@ -16,6 +16,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
 #include "llvm/Support/raw_ostream.h"
@@ -41,7 +42,23 @@
     Mgr.freeStates.push_back(s);
   }
 }
-}}
+} // namespace ento
+} // namespace clang
+
+namespace {
+struct EscapedLocals{};
+} // namespace
+
+template <>
+struct ProgramStateTrait<EscapedLocals> :
+  public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion *>> {
+  static void *GDMIndex();
+};
+
+void *ProgramStateTrait<EscapedLocals>::GDMIndex() {
+  static int index = 0;
+  return &index;
+}
 
 ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
                  StoreRef st, GenericDataMap gdm)
@@ -209,6 +226,12 @@
   ProgramStateRef newState = makeWithStore(newStore);
 
   if (CausedByPointerEscape) {
+    for (const MemRegion *R : Invalidated) {
+      if (!R->hasStackStorage())
+        continue;
+      newState = newState->add<EscapedLocals>(R);
+    }
+
     newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
                                                  TopLevelInvalidated,
                                                  Call,
@@ -642,3 +665,7 @@
   }
   return true;
 }
+
+bool ProgramState::isEscapedLocal(const MemRegion *R) const {
+  return this->contains<EscapedLocals>(R);
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2680,7 +2680,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 +2692,7 @@
 
   // Cases (1) and (2).
   const MemRegion *MR = Loc.getAsRegion();
-  if (!MR || !MR->hasStackStorage())
+  if (!MR || !MR->hasStackStorage() || State->isEscapedLocal(MR))
     return escapeValue(State, Val, PSK_EscapeOnBind);
 
   // Case (3).
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
@@ -345,6 +345,9 @@
   /// a value of such type.
   SVal getSValAsScalarOrLoc(const MemRegion *R) const;
 
+  /// TODO
+  bool isEscapedLocal(const MemRegion *R) const;
+
   using region_iterator = const MemRegion **;
 
   /// Visits the symbols reachable from the given SVal using the provided
@@ -872,8 +875,8 @@
   bool scan(const SymExpr *sym);
 };
 
-} // end ento namespace
+} // namespace ento
 
-} // end clang namespace
+} // namespace clang
 
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to