RedDocMD updated this revision to Diff 364486.
RedDocMD added a comment.

Bug fix in modelling


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D105821

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -753,10 +753,13 @@
                                             *Call, *this);
 
   ExplodedNodeSet DstInvalidated;
-  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
-  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
-       I != E; ++I)
-    defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  // StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
+  // for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E =
+  // DstPreCall.end();
+  //      I != E; ++I)
+  //   defaultEvalCall(Bldr, *I, *Call, CallOpts);
+  getCheckerManager().runCheckersForEvalCall(DstInvalidated, DstPreCall, *Call,
+                                             *this, CallOpts);
 
   getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
                                              *Call, *this);
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -664,14 +664,11 @@
     for (const auto &EvalCallChecker : EvalCallCheckers) {
       // TODO: Support the situation when the call doesn't correspond
       // to any Expr.
-      ProgramPoint L = ProgramPoint::getProgramPoint(
-          Call.getOriginExpr(), ProgramPoint::PostStmtKind,
-          Pred->getLocationContext(), EvalCallChecker.Checker);
       bool evaluated = false;
       { // CheckerContext generates transitions(populates checkDest) on
         // destruction, so introduce the scope to make sure it gets properly
         // populated.
-        CheckerContext C(B, Eng, Pred, L);
+        CheckerContext C(B, Eng, Pred, Call.getProgramPoint());
         evaluated = EvalCallChecker(Call, C);
       }
       assert(!(evaluated && anyEvaluated)
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -139,7 +139,7 @@
 
   if (RD->getDeclName().isIdentifier()) {
     StringRef Name = RD->getName();
-    return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
+    return llvm::is_contained(STD_PTR_NAMES, Name);
   }
   return false;
 }
@@ -275,6 +275,29 @@
          smartptr::isStdSmartPtr(Call.getArgExpr(1));
 }
 
+std::pair<ProgramStateRef, bool>
+invalidateInnerPointer(const MemRegion *ThisRegion, ProgramStateRef State,
+                       const CallEvent &Call, CheckerContext &C) {
+  const auto *InnerPtrVal = State->get<TrackedRegionMap>(ThisRegion);
+  if (InnerPtrVal) {
+    State = State->invalidateRegions(*InnerPtrVal, nullptr, C.blockCount(),
+                                     C.getLocationContext(), true);
+
+    const QualType &Type = getInnerPointerType(Call, C);
+    const auto *RD = Type->getAsCXXRecordDecl();
+    if (!RD)
+      return {State, false};
+    const auto *DD = RD->getDestructor();
+
+    const auto InnerDestrCall =
+        C.getStateManager().getCallEventManager().getCXXDestructorCall(
+            DD, nullptr, InnerPtrVal->getAsRegion(), RD->bases().empty(), State,
+            C.getLocationContext());
+    InnerDestrCall->invalidateRegions(C.blockCount(), State);
+  }
+  return {State, true};
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
                                 CheckerContext &C) const {
 
@@ -372,6 +395,23 @@
     }
   }
 
+  if (const auto *DC = dyn_cast<CXXDestructorCall>(&Call)) {
+    const MemRegion *ThisRegion = DC->getCXXThisVal().getAsRegion();
+    if (!ThisRegion)
+      return false;
+    State = State->remove<TrackedRegionMap>(ThisRegion);
+    bool ShouldGiveUp;
+    std::tie(State, ShouldGiveUp) =
+        invalidateInnerPointer(ThisRegion, State, Call, C);
+    // This tag is required to prevent later crashes due to the non-addition
+    // of new States. Having a tag ensures that the call to addTransition
+    // actually adds a new state.
+    static SimpleProgramPointTag SPPT("SmartPtrModeling",
+                                      "on destructor modeling");
+    C.addTransition(State, &SPPT);
+    return !ShouldGiveUp;
+  }
+
   if (!ModelSmartPtrDereference)
     return false;
 
@@ -402,10 +442,14 @@
           }));
     } else {
       const auto *TrackingExpr = Call.getArgExpr(0);
-      assert(TrackingExpr->getType()->isPointerType() &&
-             "Adding a non pointer value to TrackedRegionMap");
+      if (!TrackingExpr->getType()->isPointerType())
+        return false;
       auto ArgVal = Call.getArgSVal(0);
       State = State->set<TrackedRegionMap>(ThisRegion, ArgVal);
+      // Escape the pointer passed here
+      State = C.getStateManager().getOwningEngine().processPointerEscapedOnBind(
+          State, {std::make_pair(CC->getCXXThisVal(), ArgVal)},
+          C.getLocationContext(), PSK_DirectEscapeOnCall, &Call);
 
       C.addTransition(State, C.getNoteTag([ThisRegion, TrackingExpr,
                                            ArgVal](PathSensitiveBugReport &BR,
@@ -561,10 +605,8 @@
     Out << Sep << "Smart ptr regions :" << NL;
     for (auto I : RS) {
       I.first->dumpToStream(Out);
-      if (smartptr::isNullSmartPtr(State, I.first))
-        Out << ": Null";
-      else
-        Out << ": Non Null";
+      Out << ": ";
+      I.second.dumpToStream(Out);
       Out << NL;
     }
   }
@@ -609,7 +651,14 @@
 
   assert(Call.getArgExpr(0)->getType()->isPointerType() &&
          "Adding a non pointer value to TrackedRegionMap");
-  State = State->set<TrackedRegionMap>(ThisRegion, Call.getArgSVal(0));
+  auto Result = invalidateInnerPointer(ThisRegion, State, Call, C);
+  State = Result.first;
+  const auto ArgVal = Call.getArgSVal(0);
+  State = State->set<TrackedRegionMap>(ThisRegion, ArgVal);
+  // Escape the pointer passed here
+  State = C.getStateManager().getOwningEngine().processPointerEscapedOnBind(
+      State, {std::make_pair(IC->getCXXThisVal(), ArgVal)},
+      C.getLocationContext(), PSK_DirectEscapeOnCall, &Call);
   const auto *TrackingExpr = Call.getArgExpr(0);
   C.addTransition(
       State, C.getNoteTag([ThisRegion, TrackingExpr](PathSensitiveBugReport &BR,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to