From: Adam Balogh Date: Mon, 30 Jul 2018 08:52:21 +0000 (+0000) Subject: [Analyzer] Iterator Checker Hotfix: Defer deletion of container data until its last... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0412c73790e89745e5da15323eb4048457a59057;p=clang [Analyzer] Iterator Checker Hotfix: Defer deletion of container data until its last iterator is cleaned up The analyzer may consider a container region as dead while it still has live iterators. We must defer deletion of the data belonging to such containers until all its iterators are dead as well to be able to compare the iterator to the begin and the end of the container which is stored in the container data. Differential Revision: https://reviews.llvm.org/D48427 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338234 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp index 56c250cd16..fc713bc499 100644 --- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -291,6 +291,7 @@ const ContainerData *getContainerData(ProgramStateRef State, const MemRegion *Cont); ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont, const ContainerData &CData); +bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont); bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos); bool isZero(ProgramStateRef State, const NonLoc &Val); } // namespace @@ -536,7 +537,11 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR, auto ContMap = State->get(); for (const auto Cont : ContMap) { if (!SR.isLiveRegion(Cont.first)) { - State = State->remove(Cont.first); + // We must keep the container data while it has live iterators to be able + // to compare them to the begin and the end of the container. + if (!hasLiveIterators(State, Cont.first)) { + State = State->remove(Cont.first); + } } } @@ -1188,6 +1193,22 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State, return NewState; } +bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) { + auto RegionMap = State->get(); + for (const auto Reg : RegionMap) { + if (Reg.second.getContainer() == Cont) + return true; + } + + auto SymbolMap = State->get(); + for (const auto Sym : SymbolMap) { + if (Sym.second.getContainer() == Cont) + return true; + } + + return false; +} + bool isZero(ProgramStateRef State, const NonLoc &Val) { auto &BVF = State->getBasicVals(); return compare(State, Val,