]> granicus.if.org Git - clang/commitdiff
[analyzer] Clean up the program state map of DanglingInternalBufferChecker.
authorReka Kovacs <rekanikolett@gmail.com>
Sat, 9 Jun 2018 21:08:27 +0000 (21:08 +0000)
committerReka Kovacs <rekanikolett@gmail.com>
Sat, 9 Jun 2018 21:08:27 +0000 (21:08 +0000)
Symbols are cleaned up from the program state map when they go out of scope.
Memory regions are cleaned up when the corresponding object is destroyed, and
additionally in 'checkDeadSymbols' in case destructor modeling was incomplete.

Differential Revision: https://reviews.llvm.org/D47416

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334352 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp

index e7884ee104a35e451b86c6e2396563df92a65f5f..18f0a22e4a75063000c6ac5f5d28754847d5e111 100644 (file)
@@ -26,7 +26,8 @@ using namespace ento;
 
 namespace {
 
-class DanglingInternalBufferChecker : public Checker<check::PostCall> {
+class DanglingInternalBufferChecker : public Checker<check::DeadSymbols,
+                                                     check::PostCall> {
   CallDescription CStrFn;
 
 public:
@@ -36,6 +37,9 @@ public:
   /// corresponding string object region in the ProgramState. Mark the symbol
   /// released if the string object is destroyed.
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+  /// Clean up the ProgramState map.
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
 };
 
 } // end anonymous namespace
@@ -76,12 +80,29 @@ void DanglingInternalBufferChecker::checkPostCall(const CallEvent &Call,
       // FIXME: What if Origin is null?
       const Expr *Origin = Call.getOriginExpr();
       State = allocation_state::markReleased(State, *StrBufferPtr, Origin);
+      State = State->remove<RawPtrMap>(TypedR);
       C.addTransition(State);
       return;
     }
   }
 }
 
+void DanglingInternalBufferChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                                     CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  RawPtrMapTy RPM = State->get<RawPtrMap>();
+  for (const auto Entry : RPM) {
+    if (!SymReaper.isLive(Entry.second))
+      State = State->remove<RawPtrMap>(Entry.first);
+    if (!SymReaper.isLiveRegion(Entry.first)) {
+      // Due to incomplete destructor support, some dead regions might still
+      // remain in the program state map. Clean them up.
+      State = State->remove<RawPtrMap>(Entry.first);
+    }
+  }
+  C.addTransition(State);
+}
+
 void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) {
   registerNewDeleteChecker(Mgr);
   Mgr.registerChecker<DanglingInternalBufferChecker>();