baloghadamsoftware created this revision. baloghadamsoftware added reviewers: NoQ, Szelethus. baloghadamsoftware added a project: clang. Herald added subscribers: Charusso, gamesh411, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet.
A container's `end()` is never less than its `begin(). This patch ensures it. Furthermore it refactors `begin` and `end` symbol creation by moving symbol conjuration into the `create...` functions. This way the functions' responsibilities are clearer and makes possible to add more functions handling these symbols (e.g. functions for handling the container's size) without code multiplication. Repository: rC Clang https://reviews.llvm.org/D61136 Files: lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
Index: lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -300,10 +300,13 @@ SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont); SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont); ProgramStateRef createContainerBegin(ProgramStateRef State, - const MemRegion *Cont, - const SymbolRef Sym); + const MemRegion *Cont, const Expr *E, + QualType T, const LocationContext *LCtx, + unsigned BlockCount); ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, - const SymbolRef Sym); + const Expr *E, QualType T, + const LocationContext *LCtx, + unsigned BlockCount); const IteratorPosition *getIteratorPosition(ProgramStateRef State, const SVal &Val); ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, @@ -1100,11 +1103,9 @@ auto State = C.getState(); auto BeginSym = getContainerBegin(State, ContReg); if (!BeginSym) { - auto &SymMgr = C.getSymbolManager(); - BeginSym = SymMgr.conjureSymbol(CE, C.getLocationContext(), - C.getASTContext().LongTy, C.blockCount()); - State = assumeNoOverflow(State, BeginSym, 4); - State = createContainerBegin(State, ContReg, BeginSym); + State = createContainerBegin(State, ContReg, CE, C.getASTContext().LongTy, + C.getLocationContext(), C.blockCount()); + BeginSym = getContainerBegin(State, ContReg); } State = setIteratorPosition(State, RetVal, IteratorPosition::getPosition(ContReg, BeginSym)); @@ -1124,11 +1125,9 @@ auto State = C.getState(); auto EndSym = getContainerEnd(State, ContReg); if (!EndSym) { - auto &SymMgr = C.getSymbolManager(); - EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(), - C.getASTContext().LongTy, C.blockCount()); - State = assumeNoOverflow(State, EndSym, 4); - State = createContainerEnd(State, ContReg, EndSym); + State = createContainerEnd(State, ContReg, CE, C.getASTContext().LongTy, + C.getLocationContext(), C.blockCount()); + EndSym = getContainerEnd(State, ContReg); } State = setIteratorPosition(State, RetVal, IteratorPosition::getPosition(ContReg, EndSym)); @@ -1592,6 +1591,8 @@ const MemRegion *Reg); SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB, SymbolRef Expr, SymbolRef OldSym, SymbolRef NewSym); +ProgramStateRef ensureNonNegativeDiff(ProgramStateRef State, SymbolRef Sym1, + SymbolRef Sym2); bool isIteratorType(const QualType &Type) { if (Type->isPointerType()) @@ -1892,32 +1893,51 @@ } ProgramStateRef createContainerBegin(ProgramStateRef State, - const MemRegion *Cont, - const SymbolRef Sym) { + const MemRegion *Cont, const Expr *E, + QualType T, const LocationContext *LCtx, + unsigned BlockCount) { // Only create if it does not exist const auto *CDataPtr = getContainerData(State, Cont); + if (CDataPtr && CDataPtr->getBegin()) + return State; + + auto &SymMgr = State->getSymbolManager(); + auto Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount, "begin"); + State = assumeNoOverflow(State, Sym, 4); + if (CDataPtr) { - if (CDataPtr->getBegin()) { - return State; - } const auto CData = CDataPtr->newBegin(Sym); + if (auto EndSym = CDataPtr->getEnd()) { + State = ensureNonNegativeDiff(State, EndSym, Sym); + } return setContainerData(State, Cont, CData); } + const auto CData = ContainerData::fromBegin(Sym); return setContainerData(State, Cont, CData); } ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, - const SymbolRef Sym) { + const Expr *E, QualType T, + const LocationContext *LCtx, + unsigned BlockCount) { // Only create if it does not exist const auto *CDataPtr = getContainerData(State, Cont); + if (CDataPtr && CDataPtr->getEnd()) + return State; + + auto &SymMgr = State->getSymbolManager(); + auto Sym = SymMgr.conjureSymbol(E, LCtx, T, BlockCount, "end"); + State = assumeNoOverflow(State, Sym, 4); + if (CDataPtr) { - if (CDataPtr->getEnd()) { - return State; - } const auto CData = CDataPtr->newEnd(Sym); + if (auto BeginSym = CDataPtr->getBegin()) { + State = ensureNonNegativeDiff(State, Sym, BeginSym); + } return setContainerData(State, Cont, CData); } + const auto CData = ContainerData::fromEnd(Sym); return setContainerData(State, Cont, CData); } @@ -2224,6 +2244,23 @@ BO_EQ); } +ProgramStateRef ensureNonNegativeDiff(ProgramStateRef State, SymbolRef Sym1, + SymbolRef Sym2) { + // First Try to compare them and get a defined value + auto &SVB = State->getStateManager().getSValBuilder(); + + auto nonNeg = + SVB.evalBinOp(State, BO_GE, nonloc::SymbolVal(Sym1), + nonloc::SymbolVal(Sym2), SVB.getConditionType()) + .getAs<DefinedSVal>(); + + if (nonNeg) { + return State->assume(*nonNeg, true); + } + + return State; +} + bool isPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos) { const auto *Cont = Pos.getContainer(); const auto *CData = getContainerData(State, Cont);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits