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

Reply via email to