xazax.hun updated this revision to Diff 232968.
xazax.hun edited the summary of this revision.
xazax.hun added a comment.

- Added a test. More rigorous tests will come in  the FuchsiaHandleChecker.
- Added a new PSK_ entry.


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

https://reviews.llvm.org/D71224

Files:
  clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
  clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
  clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  clang/test/Analysis/analyzer-config.c
  clang/test/Analysis/ponter-escape-on-conservative-calls.c

Index: clang/test/Analysis/ponter-escape-on-conservative-calls.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/ponter-escape-on-conservative-calls.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PointerEscape=true -analyzer-config debug.AnalysisOrder:PostCall=true %s 2>&1 | FileCheck %s
+
+
+void f(int *);
+
+int main() {
+    int a;
+    f(&a);
+    return 0;
+}
+
+// CHECK: PostCall
+// CHECK-NEXT: PointerEscape
Index: clang/test/Analysis/analyzer-config.c
===================================================================
--- clang/test/Analysis/analyzer-config.c
+++ clang/test/Analysis/analyzer-config.c
@@ -37,6 +37,7 @@
 // CHECK-NEXT: debug.AnalysisOrder:EndFunction = false
 // CHECK-NEXT: debug.AnalysisOrder:LiveSymbols = false
 // CHECK-NEXT: debug.AnalysisOrder:NewAllocator = false
+// CHECK-NEXT: debug.AnalysisOrder:PointerEscape = false
 // CHECK-NEXT: debug.AnalysisOrder:PostCall = false
 // CHECK-NEXT: debug.AnalysisOrder:PostStmtArraySubscriptExpr = false
 // CHECK-NEXT: debug.AnalysisOrder:PostStmtCXXNewExpr = false
@@ -97,4 +98,4 @@
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 94
+// CHECK-NEXT: num-entries = 95
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -592,9 +592,71 @@
   for (auto I : dstCallEvaluated)
     finishArgumentConstruction(dstArgumentCleanup, I, Call);
 
-  // Finally, run any post-call checks.
-  getCheckerManager().runCheckersForPostCall(Dst, dstArgumentCleanup,
+  ExplodedNodeSet dstPostCall;
+  getCheckerManager().runCheckersForPostCall(dstPostCall, dstArgumentCleanup,
                                              Call, *this);
+
+  // Escaping symbols conjured during invalidationg the regions above.
+  // Note that, for inlined calls the nodes were put back into the worklist,
+  // so we can assume that every node belongs to a conservative call at this
+  // point.
+  class CollectReachableSymbolsCallback final : public SymbolVisitor {
+    ProgramStateRef State;
+    InvalidatedSymbols &Symbols;
+
+  public:
+    explicit CollectReachableSymbolsCallback(ProgramStateRef State,
+                                             InvalidatedSymbols &Symbols)
+        : State(State), Symbols(Symbols) {}
+
+    bool VisitSymbol(SymbolRef Sym) override { return true; }
+    bool VisitMemRegion(const MemRegion *MR) override {
+      if (MR->hasStackStorage())
+        return false;
+      QualType T;
+      if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
+        T = TR->getLocationType();
+      else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+        T = SR->getSymbol()->getType();
+      if (T->isVoidPointerType())
+        return false;
+      SVal StoredVal = State->getSVal(MR);
+      if (SymbolRef Sym = StoredVal.getAsSymbol())
+        Symbols.insert(Sym);
+      return true;
+    }
+  };
+
+  // Run pointerEscape callback with the newly conjured symbols.
+  for (auto I : dstPostCall) {
+    NodeBuilder B(I, Dst, *currBldrCtx);
+    InvalidatedSymbols Symbols;
+    ProgramStateRef State = I->getState();
+    CollectReachableSymbolsCallback Scanner(State, Symbols);
+    const FunctionDecl *FuncDecl =
+        dyn_cast_or_null<FunctionDecl>(Call.getDecl());
+    if (FuncDecl) {
+      for (unsigned Arg = 0; Arg < Call.getNumArgs(); ++Arg) {
+        if (Arg >= FuncDecl->getNumParams())
+          break;
+        QualType ParamTy = FuncDecl->getParamDecl(Arg)->getType();
+        if (ParamTy.isNull() ||
+            (!ParamTy->isPointerType() && !ParamTy->isReferenceType()))
+          continue;
+        if (ParamTy->getPointeeType().isConstQualified())
+          continue;
+        State->scanReachableSymbols(Call.getArgSVal(Arg), Scanner);
+      }
+    }
+
+    State = getCheckerManager().runCheckersForPointerEscape(
+        State, Symbols, &Call, PSK_EscapeOnConservativeCall, nullptr);
+
+    if (State == I->getState())
+      Dst.insert(I);
+    else
+      B.generateNode(I->getLocation(), State, I);
+  }
 }
 
 ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call,
@@ -670,8 +732,7 @@
 // Conservatively evaluate call by invalidating regions and binding
 // a conjured return value.
 void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
-                                      ExplodedNode *Pred,
-                                      ProgramStateRef State) {
+                                      ExplodedNode *Pred, ProgramStateRef State) {
   State = Call.invalidateRegions(currBldrCtx->blockCount(), State);
   State = bindReturnValue(Call, Pred->getLocationContext(), State);
 
Index: clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -40,6 +40,7 @@
                      check::EndFunction,
                      check::NewAllocator,
                      check::Bind,
+                     check::PointerEscape,
                      check::RegionChanges,
                      check::LiveSymbols> {
 
@@ -165,6 +166,15 @@
       llvm::errs() << "RegionChanges\n";
     return State;
   }
+
+  ProgramStateRef checkPointerEscape(ProgramStateRef State,
+                                     const InvalidatedSymbols &Escaped,
+                                     const CallEvent *Call,
+                                     PointerEscapeKind Kind) const {
+    if (isCallbackEnabled(State, "PointerEscape"))
+      llvm::errs() << "PointerEscape\n";
+    return State;
+  }
 };
 } // end anonymous namespace
 
Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -85,6 +85,11 @@
   /// argument to a function.
   PSK_IndirectEscapeOnCall,
 
+
+  /// Escape for a new symbol that was generated into a region
+  /// that the analyzer cannot follow during a conservative call.
+  PSK_EscapeOnConservativeCall,
+
   /// The reason for pointer escape is unknown. For example,
   /// a region containing this pointer is invalidated.
   PSK_EscapeOther
Index: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1268,6 +1268,12 @@
                   "false",
                   Released,
                   Hide>,
+    CmdLineOption<Boolean,
+                  "PointerEscape",
+                  "",
+                  "false",
+                  Released,
+                  Hide>,
     CmdLineOption<Boolean,
                   "*",
                   "Enables all callbacks.",
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to