IteratorChecker.cpp 90 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408
  1. //===-- IteratorChecker.cpp ---------------------------------------*- C++ -*--//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Defines a checker for using iterators outside their range (past end). Usage
  11. // means here dereferencing, incrementing etc.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. //
  15. // In the code, iterator can be represented as a:
  16. // * type-I: typedef-ed pointer. Operations over such iterator, such as
  17. // comparisons or increments, are modeled straightforwardly by the
  18. // analyzer.
  19. // * type-II: structure with its method bodies available. Operations over such
  20. // iterator are inlined by the analyzer, and results of modeling
  21. // these operations are exposing implementation details of the
  22. // iterators, which is not necessarily helping.
  23. // * type-III: completely opaque structure. Operations over such iterator are
  24. // modeled conservatively, producing conjured symbols everywhere.
  25. //
  26. // To handle all these types in a common way we introduce a structure called
  27. // IteratorPosition which is an abstraction of the position the iterator
  28. // represents using symbolic expressions. The checker handles all the
  29. // operations on this structure.
  30. //
  31. // Additionally, depending on the circumstances, operators of types II and III
  32. // can be represented as:
  33. // * type-IIa, type-IIIa: conjured structure symbols - when returned by value
  34. // from conservatively evaluated methods such as
  35. // `.begin()`.
  36. // * type-IIb, type-IIIb: memory regions of iterator-typed objects, such as
  37. // variables or temporaries, when the iterator object is
  38. // currently treated as an lvalue.
  39. // * type-IIc, type-IIIc: compound values of iterator-typed objects, when the
  40. // iterator object is treated as an rvalue taken of a
  41. // particular lvalue, eg. a copy of "type-a" iterator
  42. // object, or an iterator that existed before the
  43. // analysis has started.
  44. //
  45. // To handle any of these three different representations stored in an SVal we
  46. // use setter and getters functions which separate the three cases. To store
  47. // them we use a pointer union of symbol and memory region.
  48. //
  49. // The checker works the following way: We record the begin and the
  50. // past-end iterator for all containers whenever their `.begin()` and `.end()`
  51. // are called. Since the Constraint Manager cannot handle such SVals we need
  52. // to take over its role. We post-check equality and non-equality comparisons
  53. // and record that the two sides are equal if we are in the 'equal' branch
  54. // (true-branch for `==` and false-branch for `!=`).
  55. //
  56. // In case of type-I or type-II iterators we get a concrete integer as a result
  57. // of the comparison (1 or 0) but in case of type-III we only get a Symbol. In
  58. // this latter case we record the symbol and reload it in evalAssume() and do
  59. // the propagation there. We also handle (maybe double) negated comparisons
  60. // which are represented in the form of (x == 0 or x != 0) where x is the
  61. // comparison itself.
  62. //
  63. // Since `SimpleConstraintManager` cannot handle complex symbolic expressions
  64. // we only use expressions of the format S, S+n or S-n for iterator positions
  65. // where S is a conjured symbol and n is an unsigned concrete integer. When
  66. // making an assumption e.g. `S1 + n == S2 + m` we store `S1 - S2 == m - n` as
  67. // a constraint which we later retrieve when doing an actual comparison.
  68. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  69. #include "clang/AST/DeclTemplate.h"
  70. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  71. #include "clang/StaticAnalyzer/Core/Checker.h"
  72. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  73. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  74. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
  75. #include <utility>
  76. using namespace clang;
  77. using namespace ento;
  78. namespace {
  79. // Abstract position of an iterator. This helps to handle all three kinds
  80. // of operators in a common way by using a symbolic position.
  81. struct IteratorPosition {
  82. private:
  83. // Container the iterator belongs to
  84. const MemRegion *Cont;
  85. // Whether iterator is valid
  86. const bool Valid;
  87. // Abstract offset
  88. const SymbolRef Offset;
  89. IteratorPosition(const MemRegion *C, bool V, SymbolRef Of)
  90. : Cont(C), Valid(V), Offset(Of) {}
  91. public:
  92. const MemRegion *getContainer() const { return Cont; }
  93. bool isValid() const { return Valid; }
  94. SymbolRef getOffset() const { return Offset; }
  95. IteratorPosition invalidate() const {
  96. return IteratorPosition(Cont, false, Offset);
  97. }
  98. static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) {
  99. return IteratorPosition(C, true, Of);
  100. }
  101. IteratorPosition setTo(SymbolRef NewOf) const {
  102. return IteratorPosition(Cont, Valid, NewOf);
  103. }
  104. IteratorPosition reAssign(const MemRegion *NewCont) const {
  105. return IteratorPosition(NewCont, Valid, Offset);
  106. }
  107. bool operator==(const IteratorPosition &X) const {
  108. return Cont == X.Cont && Valid == X.Valid && Offset == X.Offset;
  109. }
  110. bool operator!=(const IteratorPosition &X) const {
  111. return Cont != X.Cont || Valid != X.Valid || Offset != X.Offset;
  112. }
  113. void Profile(llvm::FoldingSetNodeID &ID) const {
  114. ID.AddPointer(Cont);
  115. ID.AddInteger(Valid);
  116. ID.Add(Offset);
  117. }
  118. };
  119. typedef llvm::PointerUnion<const MemRegion *, SymbolRef> RegionOrSymbol;
  120. // Structure to record the symbolic begin and end position of a container
  121. struct ContainerData {
  122. private:
  123. const SymbolRef Begin, End;
  124. ContainerData(SymbolRef B, SymbolRef E) : Begin(B), End(E) {}
  125. public:
  126. static ContainerData fromBegin(SymbolRef B) {
  127. return ContainerData(B, nullptr);
  128. }
  129. static ContainerData fromEnd(SymbolRef E) {
  130. return ContainerData(nullptr, E);
  131. }
  132. SymbolRef getBegin() const { return Begin; }
  133. SymbolRef getEnd() const { return End; }
  134. ContainerData newBegin(SymbolRef B) const { return ContainerData(B, End); }
  135. ContainerData newEnd(SymbolRef E) const { return ContainerData(Begin, E); }
  136. bool operator==(const ContainerData &X) const {
  137. return Begin == X.Begin && End == X.End;
  138. }
  139. bool operator!=(const ContainerData &X) const {
  140. return Begin != X.Begin || End != X.End;
  141. }
  142. void Profile(llvm::FoldingSetNodeID &ID) const {
  143. ID.Add(Begin);
  144. ID.Add(End);
  145. }
  146. };
  147. // Structure fo recording iterator comparisons. We needed to retrieve the
  148. // original comparison expression in assumptions.
  149. struct IteratorComparison {
  150. private:
  151. RegionOrSymbol Left, Right;
  152. bool Equality;
  153. public:
  154. IteratorComparison(RegionOrSymbol L, RegionOrSymbol R, bool Eq)
  155. : Left(L), Right(R), Equality(Eq) {}
  156. RegionOrSymbol getLeft() const { return Left; }
  157. RegionOrSymbol getRight() const { return Right; }
  158. bool isEquality() const { return Equality; }
  159. bool operator==(const IteratorComparison &X) const {
  160. return Left == X.Left && Right == X.Right && Equality == X.Equality;
  161. }
  162. bool operator!=(const IteratorComparison &X) const {
  163. return Left != X.Left || Right != X.Right || Equality != X.Equality;
  164. }
  165. void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Equality); }
  166. };
  167. class IteratorChecker
  168. : public Checker<check::PreCall, check::PostCall,
  169. check::PostStmt<MaterializeTemporaryExpr>, check::Bind,
  170. check::LiveSymbols, check::DeadSymbols,
  171. eval::Assume> {
  172. std::unique_ptr<BugType> OutOfRangeBugType;
  173. std::unique_ptr<BugType> MismatchedBugType;
  174. std::unique_ptr<BugType> InvalidatedBugType;
  175. void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal,
  176. const SVal &RVal, OverloadedOperatorKind Op) const;
  177. void verifyAccess(CheckerContext &C, const SVal &Val) const;
  178. void verifyDereference(CheckerContext &C, const SVal &Val) const;
  179. void handleIncrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
  180. bool Postfix) const;
  181. void handleDecrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
  182. bool Postfix) const;
  183. void handleRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op,
  184. const SVal &RetVal, const SVal &LHS,
  185. const SVal &RHS) const;
  186. void handleBegin(CheckerContext &C, const Expr *CE, const SVal &RetVal,
  187. const SVal &Cont) const;
  188. void handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal,
  189. const SVal &Cont) const;
  190. void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal,
  191. const MemRegion *Cont) const;
  192. void handleAssign(CheckerContext &C, const SVal &Cont,
  193. const Expr *CE = nullptr,
  194. const SVal &OldCont = UndefinedVal()) const;
  195. void handleClear(CheckerContext &C, const SVal &Cont) const;
  196. void handlePushBack(CheckerContext &C, const SVal &Cont) const;
  197. void handlePopBack(CheckerContext &C, const SVal &Cont) const;
  198. void handlePushFront(CheckerContext &C, const SVal &Cont) const;
  199. void handlePopFront(CheckerContext &C, const SVal &Cont) const;
  200. void handleInsert(CheckerContext &C, const SVal &Iter) const;
  201. void handleErase(CheckerContext &C, const SVal &Iter) const;
  202. void handleErase(CheckerContext &C, const SVal &Iter1,
  203. const SVal &Iter2) const;
  204. void handleEraseAfter(CheckerContext &C, const SVal &Iter) const;
  205. void handleEraseAfter(CheckerContext &C, const SVal &Iter1,
  206. const SVal &Iter2) const;
  207. void verifyIncrement(CheckerContext &C, const SVal &Iter) const;
  208. void verifyDecrement(CheckerContext &C, const SVal &Iter) const;
  209. void verifyRandomIncrOrDecr(CheckerContext &C, OverloadedOperatorKind Op,
  210. const SVal &LHS, const SVal &RHS) const;
  211. void verifyMatch(CheckerContext &C, const SVal &Iter,
  212. const MemRegion *Cont) const;
  213. void verifyMatch(CheckerContext &C, const SVal &Iter1,
  214. const SVal &Iter2) const;
  215. IteratorPosition advancePosition(CheckerContext &C, OverloadedOperatorKind Op,
  216. const IteratorPosition &Pos,
  217. const SVal &Distance) const;
  218. void reportOutOfRangeBug(const StringRef &Message, const SVal &Val,
  219. CheckerContext &C, ExplodedNode *ErrNode) const;
  220. void reportMismatchedBug(const StringRef &Message, const SVal &Val1,
  221. const SVal &Val2, CheckerContext &C,
  222. ExplodedNode *ErrNode) const;
  223. void reportMismatchedBug(const StringRef &Message, const SVal &Val,
  224. const MemRegion *Reg, CheckerContext &C,
  225. ExplodedNode *ErrNode) const;
  226. void reportInvalidatedBug(const StringRef &Message, const SVal &Val,
  227. CheckerContext &C, ExplodedNode *ErrNode) const;
  228. public:
  229. IteratorChecker();
  230. enum CheckKind {
  231. CK_IteratorRangeChecker,
  232. CK_MismatchedIteratorChecker,
  233. CK_InvalidatedIteratorChecker,
  234. CK_NumCheckKinds
  235. };
  236. DefaultBool ChecksEnabled[CK_NumCheckKinds];
  237. CheckName CheckNames[CK_NumCheckKinds];
  238. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  239. void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  240. void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
  241. void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
  242. void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
  243. void checkPostStmt(const MaterializeTemporaryExpr *MTE,
  244. CheckerContext &C) const;
  245. void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
  246. void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
  247. ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
  248. bool Assumption) const;
  249. };
  250. } // namespace
  251. REGISTER_MAP_WITH_PROGRAMSTATE(IteratorSymbolMap, SymbolRef, IteratorPosition)
  252. REGISTER_MAP_WITH_PROGRAMSTATE(IteratorRegionMap, const MemRegion *,
  253. IteratorPosition)
  254. REGISTER_MAP_WITH_PROGRAMSTATE(ContainerMap, const MemRegion *, ContainerData)
  255. REGISTER_MAP_WITH_PROGRAMSTATE(IteratorComparisonMap, const SymExpr *,
  256. IteratorComparison)
  257. namespace {
  258. bool isIteratorType(const QualType &Type);
  259. bool isIterator(const CXXRecordDecl *CRD);
  260. bool isComparisonOperator(OverloadedOperatorKind OK);
  261. bool isBeginCall(const FunctionDecl *Func);
  262. bool isEndCall(const FunctionDecl *Func);
  263. bool isAssignCall(const FunctionDecl *Func);
  264. bool isClearCall(const FunctionDecl *Func);
  265. bool isPushBackCall(const FunctionDecl *Func);
  266. bool isEmplaceBackCall(const FunctionDecl *Func);
  267. bool isPopBackCall(const FunctionDecl *Func);
  268. bool isPushFrontCall(const FunctionDecl *Func);
  269. bool isEmplaceFrontCall(const FunctionDecl *Func);
  270. bool isPopFrontCall(const FunctionDecl *Func);
  271. bool isInsertCall(const FunctionDecl *Func);
  272. bool isEraseCall(const FunctionDecl *Func);
  273. bool isEraseAfterCall(const FunctionDecl *Func);
  274. bool isEmplaceCall(const FunctionDecl *Func);
  275. bool isAssignmentOperator(OverloadedOperatorKind OK);
  276. bool isSimpleComparisonOperator(OverloadedOperatorKind OK);
  277. bool isAccessOperator(OverloadedOperatorKind OK);
  278. bool isDereferenceOperator(OverloadedOperatorKind OK);
  279. bool isIncrementOperator(OverloadedOperatorKind OK);
  280. bool isDecrementOperator(OverloadedOperatorKind OK);
  281. bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK);
  282. bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg);
  283. bool frontModifiable(ProgramStateRef State, const MemRegion *Reg);
  284. bool backModifiable(ProgramStateRef State, const MemRegion *Reg);
  285. BinaryOperator::Opcode getOpcode(const SymExpr *SE);
  286. const RegionOrSymbol getRegionOrSymbol(const SVal &Val);
  287. const ProgramStateRef processComparison(ProgramStateRef State,
  288. RegionOrSymbol LVal,
  289. RegionOrSymbol RVal, bool Equal);
  290. const ProgramStateRef saveComparison(ProgramStateRef State,
  291. const SymExpr *Condition, const SVal &LVal,
  292. const SVal &RVal, bool Eq);
  293. const IteratorComparison *loadComparison(ProgramStateRef State,
  294. const SymExpr *Condition);
  295. SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont);
  296. SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
  297. ProgramStateRef createContainerBegin(ProgramStateRef State,
  298. const MemRegion *Cont,
  299. const SymbolRef Sym);
  300. ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
  301. const SymbolRef Sym);
  302. const IteratorPosition *getIteratorPosition(ProgramStateRef State,
  303. const SVal &Val);
  304. const IteratorPosition *getIteratorPosition(ProgramStateRef State,
  305. RegionOrSymbol RegOrSym);
  306. ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
  307. const IteratorPosition &Pos);
  308. ProgramStateRef setIteratorPosition(ProgramStateRef State,
  309. RegionOrSymbol RegOrSym,
  310. const IteratorPosition &Pos);
  311. ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val);
  312. ProgramStateRef adjustIteratorPosition(ProgramStateRef State,
  313. RegionOrSymbol RegOrSym,
  314. const IteratorPosition &Pos, bool Equal);
  315. ProgramStateRef relateIteratorPositions(ProgramStateRef State,
  316. const IteratorPosition &Pos1,
  317. const IteratorPosition &Pos2,
  318. bool Equal);
  319. ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
  320. const MemRegion *Cont);
  321. ProgramStateRef
  322. invalidateAllIteratorPositionsExcept(ProgramStateRef State,
  323. const MemRegion *Cont, SymbolRef Offset,
  324. BinaryOperator::Opcode Opc);
  325. ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
  326. SymbolRef Offset,
  327. BinaryOperator::Opcode Opc);
  328. ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
  329. SymbolRef Offset1,
  330. BinaryOperator::Opcode Opc1,
  331. SymbolRef Offset2,
  332. BinaryOperator::Opcode Opc2);
  333. ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
  334. const MemRegion *Cont,
  335. const MemRegion *NewCont);
  336. ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
  337. const MemRegion *Cont,
  338. const MemRegion *NewCont,
  339. SymbolRef Offset,
  340. BinaryOperator::Opcode Opc);
  341. ProgramStateRef rebaseSymbolInIteratorPositionsIf(
  342. ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
  343. SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc);
  344. const ContainerData *getContainerData(ProgramStateRef State,
  345. const MemRegion *Cont);
  346. ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
  347. const ContainerData &CData);
  348. bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
  349. bool isBoundThroughLazyCompoundVal(const Environment &Env,
  350. const MemRegion *Reg);
  351. bool isPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos);
  352. bool isAheadOfRange(ProgramStateRef State, const IteratorPosition &Pos);
  353. bool isBehindPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos);
  354. bool isZero(ProgramStateRef State, const NonLoc &Val);
  355. } // namespace
  356. IteratorChecker::IteratorChecker() {
  357. OutOfRangeBugType.reset(
  358. new BugType(this, "Iterator out of range", "Misuse of STL APIs",
  359. /*SuppressOnSink=*/true));
  360. MismatchedBugType.reset(
  361. new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs",
  362. /*SuppressOnSink=*/true));
  363. InvalidatedBugType.reset(
  364. new BugType(this, "Iterator invalidated", "Misuse of STL APIs",
  365. /*SuppressOnSink=*/true));
  366. }
  367. void IteratorChecker::checkPreCall(const CallEvent &Call,
  368. CheckerContext &C) const {
  369. // Check for out of range access or access of invalidated position and
  370. // iterator mismatches
  371. const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
  372. if (!Func)
  373. return;
  374. if (Func->isOverloadedOperator()) {
  375. if (ChecksEnabled[CK_InvalidatedIteratorChecker] &&
  376. isAccessOperator(Func->getOverloadedOperator())) {
  377. // Check for any kind of access of invalidated iterator positions
  378. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  379. verifyAccess(C, InstCall->getCXXThisVal());
  380. } else {
  381. verifyAccess(C, Call.getArgSVal(0));
  382. }
  383. }
  384. if (ChecksEnabled[CK_IteratorRangeChecker]) {
  385. if (isIncrementOperator(Func->getOverloadedOperator())) {
  386. // Check for out-of-range incrementions
  387. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  388. verifyIncrement(C, InstCall->getCXXThisVal());
  389. } else {
  390. if (Call.getNumArgs() >= 1) {
  391. verifyIncrement(C, Call.getArgSVal(0));
  392. }
  393. }
  394. } else if (isDecrementOperator(Func->getOverloadedOperator())) {
  395. // Check for out-of-range decrementions
  396. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  397. verifyDecrement(C, InstCall->getCXXThisVal());
  398. } else {
  399. if (Call.getNumArgs() >= 1) {
  400. verifyDecrement(C, Call.getArgSVal(0));
  401. }
  402. }
  403. } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
  404. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  405. // Check for out-of-range incrementions and decrementions
  406. if (Call.getNumArgs() >= 1) {
  407. verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  408. InstCall->getCXXThisVal(),
  409. Call.getArgSVal(0));
  410. }
  411. } else {
  412. if (Call.getNumArgs() >= 2) {
  413. verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  414. Call.getArgSVal(0), Call.getArgSVal(1));
  415. }
  416. }
  417. } else if (isDereferenceOperator(Func->getOverloadedOperator())) {
  418. // Check for dereference of out-of-range iterators
  419. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  420. verifyDereference(C, InstCall->getCXXThisVal());
  421. } else {
  422. verifyDereference(C, Call.getArgSVal(0));
  423. }
  424. }
  425. } else if (ChecksEnabled[CK_MismatchedIteratorChecker] &&
  426. isComparisonOperator(Func->getOverloadedOperator())) {
  427. // Check for comparisons of iterators of different containers
  428. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  429. if (Call.getNumArgs() < 1)
  430. return;
  431. if (!isIteratorType(InstCall->getCXXThisExpr()->getType()) ||
  432. !isIteratorType(Call.getArgExpr(0)->getType()))
  433. return;
  434. verifyMatch(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
  435. } else {
  436. if (Call.getNumArgs() < 2)
  437. return;
  438. if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
  439. !isIteratorType(Call.getArgExpr(1)->getType()))
  440. return;
  441. verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
  442. }
  443. }
  444. } else if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  445. if (!ChecksEnabled[CK_MismatchedIteratorChecker])
  446. return;
  447. const auto *ContReg = InstCall->getCXXThisVal().getAsRegion();
  448. if (!ContReg)
  449. return;
  450. // Check for erase, insert and emplace using iterator of another container
  451. if (isEraseCall(Func) || isEraseAfterCall(Func)) {
  452. verifyMatch(C, Call.getArgSVal(0),
  453. InstCall->getCXXThisVal().getAsRegion());
  454. if (Call.getNumArgs() == 2) {
  455. verifyMatch(C, Call.getArgSVal(1),
  456. InstCall->getCXXThisVal().getAsRegion());
  457. }
  458. } else if (isInsertCall(Func)) {
  459. verifyMatch(C, Call.getArgSVal(0),
  460. InstCall->getCXXThisVal().getAsRegion());
  461. if (Call.getNumArgs() == 3 &&
  462. isIteratorType(Call.getArgExpr(1)->getType()) &&
  463. isIteratorType(Call.getArgExpr(2)->getType())) {
  464. verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
  465. }
  466. } else if (isEmplaceCall(Func)) {
  467. verifyMatch(C, Call.getArgSVal(0),
  468. InstCall->getCXXThisVal().getAsRegion());
  469. }
  470. } else if (isa<CXXConstructorCall>(&Call)) {
  471. // Check match of first-last iterator pair in a constructor of a container
  472. if (Call.getNumArgs() < 2)
  473. return;
  474. const auto *Ctr = cast<CXXConstructorDecl>(Call.getDecl());
  475. if (Ctr->getNumParams() < 2)
  476. return;
  477. if (Ctr->getParamDecl(0)->getName() != "first" ||
  478. Ctr->getParamDecl(1)->getName() != "last")
  479. return;
  480. if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
  481. !isIteratorType(Call.getArgExpr(1)->getType()))
  482. return;
  483. verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
  484. } else {
  485. // The main purpose of iterators is to abstract away from different
  486. // containers and provide a (maybe limited) uniform access to them.
  487. // This implies that any correctly written template function that
  488. // works on multiple containers using iterators takes different
  489. // template parameters for different containers. So we can safely
  490. // assume that passing iterators of different containers as arguments
  491. // whose type replaces the same template parameter is a bug.
  492. //
  493. // Example:
  494. // template<typename I1, typename I2>
  495. // void f(I1 first1, I1 last1, I2 first2, I2 last2);
  496. //
  497. // In this case the first two arguments to f() must be iterators must belong
  498. // to the same container and the last to also to the same container but
  499. // not necessarily to the same as the first two.
  500. if (!ChecksEnabled[CK_MismatchedIteratorChecker])
  501. return;
  502. const auto *Templ = Func->getPrimaryTemplate();
  503. if (!Templ)
  504. return;
  505. const auto *TParams = Templ->getTemplateParameters();
  506. const auto *TArgs = Func->getTemplateSpecializationArgs();
  507. // Iterate over all the template parameters
  508. for (size_t I = 0; I < TParams->size(); ++I) {
  509. const auto *TPDecl = dyn_cast<TemplateTypeParmDecl>(TParams->getParam(I));
  510. if (!TPDecl)
  511. continue;
  512. if (TPDecl->isParameterPack())
  513. continue;
  514. const auto TAType = TArgs->get(I).getAsType();
  515. if (!isIteratorType(TAType))
  516. continue;
  517. SVal LHS = UndefinedVal();
  518. // For every template parameter which is an iterator type in the
  519. // instantiation look for all functions' parameters' type by it and
  520. // check whether they belong to the same container
  521. for (auto J = 0U; J < Func->getNumParams(); ++J) {
  522. const auto *Param = Func->getParamDecl(J);
  523. const auto *ParamType =
  524. Param->getType()->getAs<SubstTemplateTypeParmType>();
  525. if (!ParamType ||
  526. ParamType->getReplacedParameter()->getDecl() != TPDecl)
  527. continue;
  528. if (LHS.isUndef()) {
  529. LHS = Call.getArgSVal(J);
  530. } else {
  531. verifyMatch(C, LHS, Call.getArgSVal(J));
  532. }
  533. }
  534. }
  535. }
  536. }
  537. void IteratorChecker::checkPostCall(const CallEvent &Call,
  538. CheckerContext &C) const {
  539. // Record new iterator positions and iterator position changes
  540. const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
  541. if (!Func)
  542. return;
  543. if (Func->isOverloadedOperator()) {
  544. const auto Op = Func->getOverloadedOperator();
  545. if (isAssignmentOperator(Op)) {
  546. const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call);
  547. if (Func->getParamDecl(0)->getType()->isRValueReferenceType()) {
  548. handleAssign(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
  549. Call.getArgSVal(0));
  550. } else {
  551. handleAssign(C, InstCall->getCXXThisVal());
  552. }
  553. } else if (isSimpleComparisonOperator(Op)) {
  554. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  555. handleComparison(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
  556. Call.getArgSVal(0), Op);
  557. } else {
  558. handleComparison(C, Call.getReturnValue(), Call.getArgSVal(0),
  559. Call.getArgSVal(1), Op);
  560. }
  561. } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
  562. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  563. if (Call.getNumArgs() >= 1) {
  564. handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  565. Call.getReturnValue(),
  566. InstCall->getCXXThisVal(), Call.getArgSVal(0));
  567. }
  568. } else {
  569. if (Call.getNumArgs() >= 2) {
  570. handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
  571. Call.getReturnValue(), Call.getArgSVal(0),
  572. Call.getArgSVal(1));
  573. }
  574. }
  575. } else if (isIncrementOperator(Func->getOverloadedOperator())) {
  576. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  577. handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
  578. Call.getNumArgs());
  579. } else {
  580. handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
  581. Call.getNumArgs());
  582. }
  583. } else if (isDecrementOperator(Func->getOverloadedOperator())) {
  584. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  585. handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
  586. Call.getNumArgs());
  587. } else {
  588. handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
  589. Call.getNumArgs());
  590. }
  591. }
  592. } else {
  593. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  594. if (isAssignCall(Func)) {
  595. handleAssign(C, InstCall->getCXXThisVal());
  596. } else if (isClearCall(Func)) {
  597. handleClear(C, InstCall->getCXXThisVal());
  598. } else if (isPushBackCall(Func) || isEmplaceBackCall(Func)) {
  599. handlePushBack(C, InstCall->getCXXThisVal());
  600. } else if (isPopBackCall(Func)) {
  601. handlePopBack(C, InstCall->getCXXThisVal());
  602. } else if (isPushFrontCall(Func) || isEmplaceFrontCall(Func)) {
  603. handlePushFront(C, InstCall->getCXXThisVal());
  604. } else if (isPopFrontCall(Func)) {
  605. handlePopFront(C, InstCall->getCXXThisVal());
  606. } else if (isInsertCall(Func) || isEmplaceCall(Func)) {
  607. handleInsert(C, Call.getArgSVal(0));
  608. } else if (isEraseCall(Func)) {
  609. if (Call.getNumArgs() == 1) {
  610. handleErase(C, Call.getArgSVal(0));
  611. } else if (Call.getNumArgs() == 2) {
  612. handleErase(C, Call.getArgSVal(0), Call.getArgSVal(1));
  613. }
  614. } else if (isEraseAfterCall(Func)) {
  615. if (Call.getNumArgs() == 1) {
  616. handleEraseAfter(C, Call.getArgSVal(0));
  617. } else if (Call.getNumArgs() == 2) {
  618. handleEraseAfter(C, Call.getArgSVal(0), Call.getArgSVal(1));
  619. }
  620. }
  621. }
  622. const auto *OrigExpr = Call.getOriginExpr();
  623. if (!OrigExpr)
  624. return;
  625. if (!isIteratorType(Call.getResultType()))
  626. return;
  627. auto State = C.getState();
  628. if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
  629. if (isBeginCall(Func)) {
  630. handleBegin(C, OrigExpr, Call.getReturnValue(),
  631. InstCall->getCXXThisVal());
  632. return;
  633. }
  634. if (isEndCall(Func)) {
  635. handleEnd(C, OrigExpr, Call.getReturnValue(),
  636. InstCall->getCXXThisVal());
  637. return;
  638. }
  639. }
  640. // Already bound to container?
  641. if (getIteratorPosition(State, Call.getReturnValue()))
  642. return;
  643. // Copy-like and move constructors
  644. if (isa<CXXConstructorCall>(&Call) && Call.getNumArgs() == 1) {
  645. if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
  646. State = setIteratorPosition(State, Call.getReturnValue(), *Pos);
  647. if (cast<CXXConstructorDecl>(Func)->isMoveConstructor()) {
  648. State = removeIteratorPosition(State, Call.getArgSVal(0));
  649. }
  650. C.addTransition(State);
  651. return;
  652. }
  653. }
  654. // Assumption: if return value is an iterator which is not yet bound to a
  655. // container, then look for the first iterator argument, and
  656. // bind the return value to the same container. This approach
  657. // works for STL algorithms.
  658. // FIXME: Add a more conservative mode
  659. for (unsigned i = 0; i < Call.getNumArgs(); ++i) {
  660. if (isIteratorType(Call.getArgExpr(i)->getType())) {
  661. if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(i))) {
  662. assignToContainer(C, OrigExpr, Call.getReturnValue(),
  663. Pos->getContainer());
  664. return;
  665. }
  666. }
  667. }
  668. }
  669. }
  670. void IteratorChecker::checkBind(SVal Loc, SVal Val, const Stmt *S,
  671. CheckerContext &C) const {
  672. auto State = C.getState();
  673. const auto *Pos = getIteratorPosition(State, Val);
  674. if (Pos) {
  675. State = setIteratorPosition(State, Loc, *Pos);
  676. C.addTransition(State);
  677. } else {
  678. const auto *OldPos = getIteratorPosition(State, Loc);
  679. if (OldPos) {
  680. State = removeIteratorPosition(State, Loc);
  681. C.addTransition(State);
  682. }
  683. }
  684. }
  685. void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE,
  686. CheckerContext &C) const {
  687. /* Transfer iterator state to temporary objects */
  688. auto State = C.getState();
  689. const auto *Pos =
  690. getIteratorPosition(State, C.getSVal(MTE->GetTemporaryExpr()));
  691. if (!Pos)
  692. return;
  693. State = setIteratorPosition(State, C.getSVal(MTE), *Pos);
  694. C.addTransition(State);
  695. }
  696. void IteratorChecker::checkLiveSymbols(ProgramStateRef State,
  697. SymbolReaper &SR) const {
  698. // Keep symbolic expressions of iterator positions, container begins and ends
  699. // alive
  700. auto RegionMap = State->get<IteratorRegionMap>();
  701. for (const auto Reg : RegionMap) {
  702. const auto Offset = Reg.second.getOffset();
  703. for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
  704. if (isa<SymbolData>(*i))
  705. SR.markLive(*i);
  706. }
  707. auto SymbolMap = State->get<IteratorSymbolMap>();
  708. for (const auto Sym : SymbolMap) {
  709. const auto Offset = Sym.second.getOffset();
  710. for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
  711. if (isa<SymbolData>(*i))
  712. SR.markLive(*i);
  713. }
  714. auto ContMap = State->get<ContainerMap>();
  715. for (const auto Cont : ContMap) {
  716. const auto CData = Cont.second;
  717. if (CData.getBegin()) {
  718. SR.markLive(CData.getBegin());
  719. if(const auto *SIE = dyn_cast<SymIntExpr>(CData.getBegin()))
  720. SR.markLive(SIE->getLHS());
  721. }
  722. if (CData.getEnd()) {
  723. SR.markLive(CData.getEnd());
  724. if(const auto *SIE = dyn_cast<SymIntExpr>(CData.getEnd()))
  725. SR.markLive(SIE->getLHS());
  726. }
  727. }
  728. }
  729. void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
  730. CheckerContext &C) const {
  731. // Cleanup
  732. auto State = C.getState();
  733. auto RegionMap = State->get<IteratorRegionMap>();
  734. for (const auto Reg : RegionMap) {
  735. if (!SR.isLiveRegion(Reg.first)) {
  736. // The region behind the `LazyCompoundVal` is often cleaned up before
  737. // the `LazyCompoundVal` itself. If there are iterator positions keyed
  738. // by these regions their cleanup must be deferred.
  739. if (!isBoundThroughLazyCompoundVal(State->getEnvironment(), Reg.first)) {
  740. State = State->remove<IteratorRegionMap>(Reg.first);
  741. }
  742. }
  743. }
  744. auto SymbolMap = State->get<IteratorSymbolMap>();
  745. for (const auto Sym : SymbolMap) {
  746. if (!SR.isLive(Sym.first)) {
  747. State = State->remove<IteratorSymbolMap>(Sym.first);
  748. }
  749. }
  750. auto ContMap = State->get<ContainerMap>();
  751. for (const auto Cont : ContMap) {
  752. if (!SR.isLiveRegion(Cont.first)) {
  753. // We must keep the container data while it has live iterators to be able
  754. // to compare them to the begin and the end of the container.
  755. if (!hasLiveIterators(State, Cont.first)) {
  756. State = State->remove<ContainerMap>(Cont.first);
  757. }
  758. }
  759. }
  760. auto ComparisonMap = State->get<IteratorComparisonMap>();
  761. for (const auto Comp : ComparisonMap) {
  762. if (!SR.isLive(Comp.first)) {
  763. State = State->remove<IteratorComparisonMap>(Comp.first);
  764. }
  765. }
  766. C.addTransition(State);
  767. }
  768. ProgramStateRef IteratorChecker::evalAssume(ProgramStateRef State, SVal Cond,
  769. bool Assumption) const {
  770. // Load recorded comparison and transfer iterator state between sides
  771. // according to comparison operator and assumption
  772. const auto *SE = Cond.getAsSymExpr();
  773. if (!SE)
  774. return State;
  775. auto Opc = getOpcode(SE);
  776. if (Opc != BO_EQ && Opc != BO_NE)
  777. return State;
  778. bool Negated = false;
  779. const auto *Comp = loadComparison(State, SE);
  780. if (!Comp) {
  781. // Try negated comparison, which is a SymExpr to 0 integer comparison
  782. const auto *SIE = dyn_cast<SymIntExpr>(SE);
  783. if (!SIE)
  784. return State;
  785. if (SIE->getRHS() != 0)
  786. return State;
  787. SE = SIE->getLHS();
  788. Negated = SIE->getOpcode() == BO_EQ; // Equal to zero means negation
  789. Opc = getOpcode(SE);
  790. if (Opc != BO_EQ && Opc != BO_NE)
  791. return State;
  792. Comp = loadComparison(State, SE);
  793. if (!Comp)
  794. return State;
  795. }
  796. return processComparison(State, Comp->getLeft(), Comp->getRight(),
  797. (Comp->isEquality() == Assumption) != Negated);
  798. }
  799. void IteratorChecker::handleComparison(CheckerContext &C, const SVal &RetVal,
  800. const SVal &LVal, const SVal &RVal,
  801. OverloadedOperatorKind Op) const {
  802. // Record the operands and the operator of the comparison for the next
  803. // evalAssume, if the result is a symbolic expression. If it is a concrete
  804. // value (only one branch is possible), then transfer the state between
  805. // the operands according to the operator and the result
  806. auto State = C.getState();
  807. if (const auto *Condition = RetVal.getAsSymbolicExpression()) {
  808. const auto *LPos = getIteratorPosition(State, LVal);
  809. const auto *RPos = getIteratorPosition(State, RVal);
  810. if (!LPos && !RPos)
  811. return;
  812. State = saveComparison(State, Condition, LVal, RVal, Op == OO_EqualEqual);
  813. C.addTransition(State);
  814. } else if (const auto TruthVal = RetVal.getAs<nonloc::ConcreteInt>()) {
  815. if ((State = processComparison(
  816. State, getRegionOrSymbol(LVal), getRegionOrSymbol(RVal),
  817. (Op == OO_EqualEqual) == (TruthVal->getValue() != 0)))) {
  818. C.addTransition(State);
  819. } else {
  820. C.generateSink(State, C.getPredecessor());
  821. }
  822. }
  823. }
  824. void IteratorChecker::verifyDereference(CheckerContext &C,
  825. const SVal &Val) const {
  826. auto State = C.getState();
  827. const auto *Pos = getIteratorPosition(State, Val);
  828. if (Pos && isPastTheEnd(State, *Pos)) {
  829. auto *N = C.generateNonFatalErrorNode(State);
  830. if (!N)
  831. return;
  832. reportOutOfRangeBug("Past-the-end iterator dereferenced.", Val, C, N);
  833. return;
  834. }
  835. }
  836. void IteratorChecker::verifyAccess(CheckerContext &C, const SVal &Val) const {
  837. auto State = C.getState();
  838. const auto *Pos = getIteratorPosition(State, Val);
  839. if (Pos && !Pos->isValid()) {
  840. auto *N = C.generateNonFatalErrorNode(State);
  841. if (!N) {
  842. return;
  843. }
  844. reportInvalidatedBug("Invalidated iterator accessed.", Val, C, N);
  845. }
  846. }
  847. void IteratorChecker::handleIncrement(CheckerContext &C, const SVal &RetVal,
  848. const SVal &Iter, bool Postfix) const {
  849. // Increment the symbolic expressions which represents the position of the
  850. // iterator
  851. auto State = C.getState();
  852. const auto *Pos = getIteratorPosition(State, Iter);
  853. if (Pos) {
  854. auto &SymMgr = C.getSymbolManager();
  855. auto &BVF = SymMgr.getBasicVals();
  856. const auto NewPos =
  857. advancePosition(C, OO_Plus, *Pos,
  858. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
  859. State = setIteratorPosition(State, Iter, NewPos);
  860. State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
  861. C.addTransition(State);
  862. }
  863. }
  864. void IteratorChecker::handleDecrement(CheckerContext &C, const SVal &RetVal,
  865. const SVal &Iter, bool Postfix) const {
  866. // Decrement the symbolic expressions which represents the position of the
  867. // iterator
  868. auto State = C.getState();
  869. const auto *Pos = getIteratorPosition(State, Iter);
  870. if (Pos) {
  871. auto &SymMgr = C.getSymbolManager();
  872. auto &BVF = SymMgr.getBasicVals();
  873. const auto NewPos =
  874. advancePosition(C, OO_Minus, *Pos,
  875. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
  876. State = setIteratorPosition(State, Iter, NewPos);
  877. State = setIteratorPosition(State, RetVal, Postfix ? *Pos : NewPos);
  878. C.addTransition(State);
  879. }
  880. }
  881. // This function tells the analyzer's engine that symbols produced by our
  882. // checker, most notably iterator positions, are relatively small.
  883. // A distance between items in the container should not be very large.
  884. // By assuming that it is within around 1/8 of the address space,
  885. // we can help the analyzer perform operations on these symbols
  886. // without being afraid of integer overflows.
  887. // FIXME: Should we provide it as an API, so that all checkers could use it?
  888. static ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym,
  889. long Scale) {
  890. SValBuilder &SVB = State->getStateManager().getSValBuilder();
  891. BasicValueFactory &BV = SVB.getBasicValueFactory();
  892. QualType T = Sym->getType();
  893. assert(T->isSignedIntegerOrEnumerationType());
  894. APSIntType AT = BV.getAPSIntType(T);
  895. ProgramStateRef NewState = State;
  896. llvm::APSInt Max = AT.getMaxValue() / AT.getValue(Scale);
  897. SVal IsCappedFromAbove =
  898. SVB.evalBinOpNN(State, BO_LE, nonloc::SymbolVal(Sym),
  899. nonloc::ConcreteInt(Max), SVB.getConditionType());
  900. if (auto DV = IsCappedFromAbove.getAs<DefinedSVal>()) {
  901. NewState = NewState->assume(*DV, true);
  902. if (!NewState)
  903. return State;
  904. }
  905. llvm::APSInt Min = -Max;
  906. SVal IsCappedFromBelow =
  907. SVB.evalBinOpNN(State, BO_GE, nonloc::SymbolVal(Sym),
  908. nonloc::ConcreteInt(Min), SVB.getConditionType());
  909. if (auto DV = IsCappedFromBelow.getAs<DefinedSVal>()) {
  910. NewState = NewState->assume(*DV, true);
  911. if (!NewState)
  912. return State;
  913. }
  914. return NewState;
  915. }
  916. void IteratorChecker::handleRandomIncrOrDecr(CheckerContext &C,
  917. OverloadedOperatorKind Op,
  918. const SVal &RetVal,
  919. const SVal &LHS,
  920. const SVal &RHS) const {
  921. // Increment or decrement the symbolic expressions which represents the
  922. // position of the iterator
  923. auto State = C.getState();
  924. const auto *Pos = getIteratorPosition(State, LHS);
  925. if (!Pos)
  926. return;
  927. const auto *value = &RHS;
  928. if (auto loc = RHS.getAs<Loc>()) {
  929. const auto val = State->getRawSVal(*loc);
  930. value = &val;
  931. }
  932. auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
  933. State =
  934. setIteratorPosition(State, TgtVal, advancePosition(C, Op, *Pos, *value));
  935. C.addTransition(State);
  936. }
  937. void IteratorChecker::verifyIncrement(CheckerContext &C,
  938. const SVal &Iter) const {
  939. auto &BVF = C.getSValBuilder().getBasicValueFactory();
  940. verifyRandomIncrOrDecr(C, OO_Plus, Iter,
  941. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
  942. }
  943. void IteratorChecker::verifyDecrement(CheckerContext &C,
  944. const SVal &Iter) const {
  945. auto &BVF = C.getSValBuilder().getBasicValueFactory();
  946. verifyRandomIncrOrDecr(C, OO_Minus, Iter,
  947. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
  948. }
  949. void IteratorChecker::verifyRandomIncrOrDecr(CheckerContext &C,
  950. OverloadedOperatorKind Op,
  951. const SVal &LHS,
  952. const SVal &RHS) const {
  953. auto State = C.getState();
  954. // If the iterator is initially inside its range, then the operation is valid
  955. const auto *Pos = getIteratorPosition(State, LHS);
  956. if (!Pos)
  957. return;
  958. auto Value = RHS;
  959. if (auto ValAsLoc = RHS.getAs<Loc>()) {
  960. Value = State->getRawSVal(*ValAsLoc);
  961. }
  962. if (Value.isUnknown())
  963. return;
  964. // Incremention or decremention by 0 is never a bug.
  965. if (isZero(State, Value.castAs<NonLoc>()))
  966. return;
  967. // The result may be the past-end iterator of the container, but any other
  968. // out of range position is undefined behaviour
  969. if (isAheadOfRange(State, advancePosition(C, Op, *Pos, Value))) {
  970. auto *N = C.generateNonFatalErrorNode(State);
  971. if (!N)
  972. return;
  973. reportOutOfRangeBug("Iterator decremented ahead of its valid range.", LHS,
  974. C, N);
  975. }
  976. if (isBehindPastTheEnd(State, advancePosition(C, Op, *Pos, Value))) {
  977. auto *N = C.generateNonFatalErrorNode(State);
  978. if (!N)
  979. return;
  980. reportOutOfRangeBug("Iterator incremented behind the past-the-end "
  981. "iterator.", LHS, C, N);
  982. }
  983. }
  984. void IteratorChecker::verifyMatch(CheckerContext &C, const SVal &Iter,
  985. const MemRegion *Cont) const {
  986. // Verify match between a container and the container of an iterator
  987. Cont = Cont->getMostDerivedObjectRegion();
  988. auto State = C.getState();
  989. const auto *Pos = getIteratorPosition(State, Iter);
  990. if (Pos && Pos->getContainer() != Cont) {
  991. auto *N = C.generateNonFatalErrorNode(State);
  992. if (!N) {
  993. return;
  994. }
  995. reportMismatchedBug("Container accessed using foreign iterator argument.", Iter, Cont, C, N);
  996. }
  997. }
  998. void IteratorChecker::verifyMatch(CheckerContext &C, const SVal &Iter1,
  999. const SVal &Iter2) const {
  1000. // Verify match between the containers of two iterators
  1001. auto State = C.getState();
  1002. const auto *Pos1 = getIteratorPosition(State, Iter1);
  1003. const auto *Pos2 = getIteratorPosition(State, Iter2);
  1004. if (Pos1 && Pos2 && Pos1->getContainer() != Pos2->getContainer()) {
  1005. auto *N = C.generateNonFatalErrorNode(State);
  1006. if (!N)
  1007. return;
  1008. reportMismatchedBug("Iterators of different containers used where the "
  1009. "same container is expected.", Iter1, Iter2, C, N);
  1010. }
  1011. }
  1012. void IteratorChecker::handleBegin(CheckerContext &C, const Expr *CE,
  1013. const SVal &RetVal, const SVal &Cont) const {
  1014. const auto *ContReg = Cont.getAsRegion();
  1015. if (!ContReg)
  1016. return;
  1017. ContReg = ContReg->getMostDerivedObjectRegion();
  1018. // If the container already has a begin symbol then use it. Otherwise first
  1019. // create a new one.
  1020. auto State = C.getState();
  1021. auto BeginSym = getContainerBegin(State, ContReg);
  1022. if (!BeginSym) {
  1023. auto &SymMgr = C.getSymbolManager();
  1024. BeginSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
  1025. C.getASTContext().LongTy, C.blockCount());
  1026. State = assumeNoOverflow(State, BeginSym, 4);
  1027. State = createContainerBegin(State, ContReg, BeginSym);
  1028. }
  1029. State = setIteratorPosition(State, RetVal,
  1030. IteratorPosition::getPosition(ContReg, BeginSym));
  1031. C.addTransition(State);
  1032. }
  1033. void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE,
  1034. const SVal &RetVal, const SVal &Cont) const {
  1035. const auto *ContReg = Cont.getAsRegion();
  1036. if (!ContReg)
  1037. return;
  1038. ContReg = ContReg->getMostDerivedObjectRegion();
  1039. // If the container already has an end symbol then use it. Otherwise first
  1040. // create a new one.
  1041. auto State = C.getState();
  1042. auto EndSym = getContainerEnd(State, ContReg);
  1043. if (!EndSym) {
  1044. auto &SymMgr = C.getSymbolManager();
  1045. EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
  1046. C.getASTContext().LongTy, C.blockCount());
  1047. State = assumeNoOverflow(State, EndSym, 4);
  1048. State = createContainerEnd(State, ContReg, EndSym);
  1049. }
  1050. State = setIteratorPosition(State, RetVal,
  1051. IteratorPosition::getPosition(ContReg, EndSym));
  1052. C.addTransition(State);
  1053. }
  1054. void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE,
  1055. const SVal &RetVal,
  1056. const MemRegion *Cont) const {
  1057. Cont = Cont->getMostDerivedObjectRegion();
  1058. auto State = C.getState();
  1059. auto &SymMgr = C.getSymbolManager();
  1060. auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
  1061. C.getASTContext().LongTy, C.blockCount());
  1062. State = assumeNoOverflow(State, Sym, 4);
  1063. State = setIteratorPosition(State, RetVal,
  1064. IteratorPosition::getPosition(Cont, Sym));
  1065. C.addTransition(State);
  1066. }
  1067. void IteratorChecker::handleAssign(CheckerContext &C, const SVal &Cont,
  1068. const Expr *CE, const SVal &OldCont) const {
  1069. const auto *ContReg = Cont.getAsRegion();
  1070. if (!ContReg)
  1071. return;
  1072. ContReg = ContReg->getMostDerivedObjectRegion();
  1073. // Assignment of a new value to a container always invalidates all its
  1074. // iterators
  1075. auto State = C.getState();
  1076. const auto CData = getContainerData(State, ContReg);
  1077. if (CData) {
  1078. State = invalidateAllIteratorPositions(State, ContReg);
  1079. }
  1080. // In case of move, iterators of the old container (except the past-end
  1081. // iterators) remain valid but refer to the new container
  1082. if (!OldCont.isUndef()) {
  1083. const auto *OldContReg = OldCont.getAsRegion();
  1084. if (OldContReg) {
  1085. OldContReg = OldContReg->getMostDerivedObjectRegion();
  1086. const auto OldCData = getContainerData(State, OldContReg);
  1087. if (OldCData) {
  1088. if (const auto OldEndSym = OldCData->getEnd()) {
  1089. // If we already assigned an "end" symbol to the old container, then
  1090. // first reassign all iterator positions to the new container which
  1091. // are not past the container (thus not greater or equal to the
  1092. // current "end" symbol).
  1093. State = reassignAllIteratorPositionsUnless(State, OldContReg, ContReg,
  1094. OldEndSym, BO_GE);
  1095. auto &SymMgr = C.getSymbolManager();
  1096. auto &SVB = C.getSValBuilder();
  1097. // Then generate and assign a new "end" symbol for the new container.
  1098. auto NewEndSym =
  1099. SymMgr.conjureSymbol(CE, C.getLocationContext(),
  1100. C.getASTContext().LongTy, C.blockCount());
  1101. State = assumeNoOverflow(State, NewEndSym, 4);
  1102. if (CData) {
  1103. State = setContainerData(State, ContReg, CData->newEnd(NewEndSym));
  1104. } else {
  1105. State = setContainerData(State, ContReg,
  1106. ContainerData::fromEnd(NewEndSym));
  1107. }
  1108. // Finally, replace the old "end" symbol in the already reassigned
  1109. // iterator positions with the new "end" symbol.
  1110. State = rebaseSymbolInIteratorPositionsIf(
  1111. State, SVB, OldEndSym, NewEndSym, OldEndSym, BO_LT);
  1112. } else {
  1113. // There was no "end" symbol assigned yet to the old container,
  1114. // so reassign all iterator positions to the new container.
  1115. State = reassignAllIteratorPositions(State, OldContReg, ContReg);
  1116. }
  1117. if (const auto OldBeginSym = OldCData->getBegin()) {
  1118. // If we already assigned a "begin" symbol to the old container, then
  1119. // assign it to the new container and remove it from the old one.
  1120. if (CData) {
  1121. State =
  1122. setContainerData(State, ContReg, CData->newBegin(OldBeginSym));
  1123. } else {
  1124. State = setContainerData(State, ContReg,
  1125. ContainerData::fromBegin(OldBeginSym));
  1126. }
  1127. State =
  1128. setContainerData(State, OldContReg, OldCData->newEnd(nullptr));
  1129. }
  1130. } else {
  1131. // There was neither "begin" nor "end" symbol assigned yet to the old
  1132. // container, so reassign all iterator positions to the new container.
  1133. State = reassignAllIteratorPositions(State, OldContReg, ContReg);
  1134. }
  1135. }
  1136. }
  1137. C.addTransition(State);
  1138. }
  1139. void IteratorChecker::handleClear(CheckerContext &C, const SVal &Cont) const {
  1140. const auto *ContReg = Cont.getAsRegion();
  1141. if (!ContReg)
  1142. return;
  1143. ContReg = ContReg->getMostDerivedObjectRegion();
  1144. // The clear() operation invalidates all the iterators, except the past-end
  1145. // iterators of list-like containers
  1146. auto State = C.getState();
  1147. if (!hasSubscriptOperator(State, ContReg) ||
  1148. !backModifiable(State, ContReg)) {
  1149. const auto CData = getContainerData(State, ContReg);
  1150. if (CData) {
  1151. if (const auto EndSym = CData->getEnd()) {
  1152. State =
  1153. invalidateAllIteratorPositionsExcept(State, ContReg, EndSym, BO_GE);
  1154. C.addTransition(State);
  1155. return;
  1156. }
  1157. }
  1158. }
  1159. State = invalidateAllIteratorPositions(State, ContReg);
  1160. C.addTransition(State);
  1161. }
  1162. void IteratorChecker::handlePushBack(CheckerContext &C,
  1163. const SVal &Cont) const {
  1164. const auto *ContReg = Cont.getAsRegion();
  1165. if (!ContReg)
  1166. return;
  1167. ContReg = ContReg->getMostDerivedObjectRegion();
  1168. // For deque-like containers invalidate all iterator positions
  1169. auto State = C.getState();
  1170. if (hasSubscriptOperator(State, ContReg) && frontModifiable(State, ContReg)) {
  1171. State = invalidateAllIteratorPositions(State, ContReg);
  1172. C.addTransition(State);
  1173. return;
  1174. }
  1175. const auto CData = getContainerData(State, ContReg);
  1176. if (!CData)
  1177. return;
  1178. // For vector-like containers invalidate the past-end iterator positions
  1179. if (const auto EndSym = CData->getEnd()) {
  1180. if (hasSubscriptOperator(State, ContReg)) {
  1181. State = invalidateIteratorPositions(State, EndSym, BO_GE);
  1182. }
  1183. auto &SymMgr = C.getSymbolManager();
  1184. auto &BVF = SymMgr.getBasicVals();
  1185. auto &SVB = C.getSValBuilder();
  1186. const auto newEndSym =
  1187. SVB.evalBinOp(State, BO_Add,
  1188. nonloc::SymbolVal(EndSym),
  1189. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
  1190. SymMgr.getType(EndSym)).getAsSymbol();
  1191. State = setContainerData(State, ContReg, CData->newEnd(newEndSym));
  1192. }
  1193. C.addTransition(State);
  1194. }
  1195. void IteratorChecker::handlePopBack(CheckerContext &C, const SVal &Cont) const {
  1196. const auto *ContReg = Cont.getAsRegion();
  1197. if (!ContReg)
  1198. return;
  1199. ContReg = ContReg->getMostDerivedObjectRegion();
  1200. auto State = C.getState();
  1201. const auto CData = getContainerData(State, ContReg);
  1202. if (!CData)
  1203. return;
  1204. if (const auto EndSym = CData->getEnd()) {
  1205. auto &SymMgr = C.getSymbolManager();
  1206. auto &BVF = SymMgr.getBasicVals();
  1207. auto &SVB = C.getSValBuilder();
  1208. const auto BackSym =
  1209. SVB.evalBinOp(State, BO_Sub,
  1210. nonloc::SymbolVal(EndSym),
  1211. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
  1212. SymMgr.getType(EndSym)).getAsSymbol();
  1213. // For vector-like and deque-like containers invalidate the last and the
  1214. // past-end iterator positions. For list-like containers only invalidate
  1215. // the last position
  1216. if (hasSubscriptOperator(State, ContReg) &&
  1217. backModifiable(State, ContReg)) {
  1218. State = invalidateIteratorPositions(State, BackSym, BO_GE);
  1219. State = setContainerData(State, ContReg, CData->newEnd(nullptr));
  1220. } else {
  1221. State = invalidateIteratorPositions(State, BackSym, BO_EQ);
  1222. }
  1223. auto newEndSym = BackSym;
  1224. State = setContainerData(State, ContReg, CData->newEnd(newEndSym));
  1225. C.addTransition(State);
  1226. }
  1227. }
  1228. void IteratorChecker::handlePushFront(CheckerContext &C,
  1229. const SVal &Cont) const {
  1230. const auto *ContReg = Cont.getAsRegion();
  1231. if (!ContReg)
  1232. return;
  1233. ContReg = ContReg->getMostDerivedObjectRegion();
  1234. // For deque-like containers invalidate all iterator positions
  1235. auto State = C.getState();
  1236. if (hasSubscriptOperator(State, ContReg)) {
  1237. State = invalidateAllIteratorPositions(State, ContReg);
  1238. C.addTransition(State);
  1239. } else {
  1240. const auto CData = getContainerData(State, ContReg);
  1241. if (!CData)
  1242. return;
  1243. if (const auto BeginSym = CData->getBegin()) {
  1244. auto &SymMgr = C.getSymbolManager();
  1245. auto &BVF = SymMgr.getBasicVals();
  1246. auto &SVB = C.getSValBuilder();
  1247. const auto newBeginSym =
  1248. SVB.evalBinOp(State, BO_Sub,
  1249. nonloc::SymbolVal(BeginSym),
  1250. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
  1251. SymMgr.getType(BeginSym)).getAsSymbol();
  1252. State = setContainerData(State, ContReg, CData->newBegin(newBeginSym));
  1253. C.addTransition(State);
  1254. }
  1255. }
  1256. }
  1257. void IteratorChecker::handlePopFront(CheckerContext &C,
  1258. const SVal &Cont) const {
  1259. const auto *ContReg = Cont.getAsRegion();
  1260. if (!ContReg)
  1261. return;
  1262. ContReg = ContReg->getMostDerivedObjectRegion();
  1263. auto State = C.getState();
  1264. const auto CData = getContainerData(State, ContReg);
  1265. if (!CData)
  1266. return;
  1267. // For deque-like containers invalidate all iterator positions. For list-like
  1268. // iterators only invalidate the first position
  1269. if (const auto BeginSym = CData->getBegin()) {
  1270. if (hasSubscriptOperator(State, ContReg)) {
  1271. State = invalidateIteratorPositions(State, BeginSym, BO_LE);
  1272. } else {
  1273. State = invalidateIteratorPositions(State, BeginSym, BO_EQ);
  1274. }
  1275. auto &SymMgr = C.getSymbolManager();
  1276. auto &BVF = SymMgr.getBasicVals();
  1277. auto &SVB = C.getSValBuilder();
  1278. const auto newBeginSym =
  1279. SVB.evalBinOp(State, BO_Add,
  1280. nonloc::SymbolVal(BeginSym),
  1281. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
  1282. SymMgr.getType(BeginSym)).getAsSymbol();
  1283. State = setContainerData(State, ContReg, CData->newBegin(newBeginSym));
  1284. C.addTransition(State);
  1285. }
  1286. }
  1287. void IteratorChecker::handleInsert(CheckerContext &C, const SVal &Iter) const {
  1288. auto State = C.getState();
  1289. const auto *Pos = getIteratorPosition(State, Iter);
  1290. if (!Pos)
  1291. return;
  1292. // For deque-like containers invalidate all iterator positions. For
  1293. // vector-like containers invalidate iterator positions after the insertion.
  1294. const auto *Cont = Pos->getContainer();
  1295. if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
  1296. if (frontModifiable(State, Cont)) {
  1297. State = invalidateAllIteratorPositions(State, Cont);
  1298. } else {
  1299. State = invalidateIteratorPositions(State, Pos->getOffset(), BO_GE);
  1300. }
  1301. if (const auto *CData = getContainerData(State, Cont)) {
  1302. if (const auto EndSym = CData->getEnd()) {
  1303. State = invalidateIteratorPositions(State, EndSym, BO_GE);
  1304. State = setContainerData(State, Cont, CData->newEnd(nullptr));
  1305. }
  1306. }
  1307. C.addTransition(State);
  1308. }
  1309. }
  1310. void IteratorChecker::handleErase(CheckerContext &C, const SVal &Iter) const {
  1311. auto State = C.getState();
  1312. const auto *Pos = getIteratorPosition(State, Iter);
  1313. if (!Pos)
  1314. return;
  1315. // For deque-like containers invalidate all iterator positions. For
  1316. // vector-like containers invalidate iterator positions at and after the
  1317. // deletion. For list-like containers only invalidate the deleted position.
  1318. const auto *Cont = Pos->getContainer();
  1319. if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
  1320. if (frontModifiable(State, Cont)) {
  1321. State = invalidateAllIteratorPositions(State, Cont);
  1322. } else {
  1323. State = invalidateIteratorPositions(State, Pos->getOffset(), BO_GE);
  1324. }
  1325. if (const auto *CData = getContainerData(State, Cont)) {
  1326. if (const auto EndSym = CData->getEnd()) {
  1327. State = invalidateIteratorPositions(State, EndSym, BO_GE);
  1328. State = setContainerData(State, Cont, CData->newEnd(nullptr));
  1329. }
  1330. }
  1331. } else {
  1332. State = invalidateIteratorPositions(State, Pos->getOffset(), BO_EQ);
  1333. }
  1334. C.addTransition(State);
  1335. }
  1336. void IteratorChecker::handleErase(CheckerContext &C, const SVal &Iter1,
  1337. const SVal &Iter2) const {
  1338. auto State = C.getState();
  1339. const auto *Pos1 = getIteratorPosition(State, Iter1);
  1340. const auto *Pos2 = getIteratorPosition(State, Iter2);
  1341. if (!Pos1 || !Pos2)
  1342. return;
  1343. // For deque-like containers invalidate all iterator positions. For
  1344. // vector-like containers invalidate iterator positions at and after the
  1345. // deletion range. For list-like containers only invalidate the deleted
  1346. // position range [first..last].
  1347. const auto *Cont = Pos1->getContainer();
  1348. if (hasSubscriptOperator(State, Cont) && backModifiable(State, Cont)) {
  1349. if (frontModifiable(State, Cont)) {
  1350. State = invalidateAllIteratorPositions(State, Cont);
  1351. } else {
  1352. State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GE);
  1353. }
  1354. if (const auto *CData = getContainerData(State, Cont)) {
  1355. if (const auto EndSym = CData->getEnd()) {
  1356. State = invalidateIteratorPositions(State, EndSym, BO_GE);
  1357. State = setContainerData(State, Cont, CData->newEnd(nullptr));
  1358. }
  1359. }
  1360. } else {
  1361. State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GE,
  1362. Pos2->getOffset(), BO_LT);
  1363. }
  1364. C.addTransition(State);
  1365. }
  1366. void IteratorChecker::handleEraseAfter(CheckerContext &C,
  1367. const SVal &Iter) const {
  1368. auto State = C.getState();
  1369. const auto *Pos = getIteratorPosition(State, Iter);
  1370. if (!Pos)
  1371. return;
  1372. // Invalidate the deleted iterator position, which is the position of the
  1373. // parameter plus one.
  1374. auto &SymMgr = C.getSymbolManager();
  1375. auto &BVF = SymMgr.getBasicVals();
  1376. auto &SVB = C.getSValBuilder();
  1377. const auto NextSym =
  1378. SVB.evalBinOp(State, BO_Add,
  1379. nonloc::SymbolVal(Pos->getOffset()),
  1380. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))),
  1381. SymMgr.getType(Pos->getOffset())).getAsSymbol();
  1382. State = invalidateIteratorPositions(State, NextSym, BO_EQ);
  1383. C.addTransition(State);
  1384. }
  1385. void IteratorChecker::handleEraseAfter(CheckerContext &C, const SVal &Iter1,
  1386. const SVal &Iter2) const {
  1387. auto State = C.getState();
  1388. const auto *Pos1 = getIteratorPosition(State, Iter1);
  1389. const auto *Pos2 = getIteratorPosition(State, Iter2);
  1390. if (!Pos1 || !Pos2)
  1391. return;
  1392. // Invalidate the deleted iterator position range (first..last)
  1393. State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GT,
  1394. Pos2->getOffset(), BO_LT);
  1395. C.addTransition(State);
  1396. }
  1397. IteratorPosition IteratorChecker::advancePosition(CheckerContext &C,
  1398. OverloadedOperatorKind Op,
  1399. const IteratorPosition &Pos,
  1400. const SVal &Distance) const {
  1401. auto State = C.getState();
  1402. auto &SymMgr = C.getSymbolManager();
  1403. auto &SVB = C.getSValBuilder();
  1404. assert ((Op == OO_Plus || Op == OO_PlusEqual ||
  1405. Op == OO_Minus || Op == OO_MinusEqual) &&
  1406. "Advance operator must be one of +, -, += and -=.");
  1407. auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
  1408. if (const auto IntDist = Distance.getAs<nonloc::ConcreteInt>()) {
  1409. // For concrete integers we can calculate the new position
  1410. return Pos.setTo(SVB.evalBinOp(State, BinOp,
  1411. nonloc::SymbolVal(Pos.getOffset()), *IntDist,
  1412. SymMgr.getType(Pos.getOffset()))
  1413. .getAsSymbol());
  1414. } else {
  1415. // For other symbols create a new symbol to keep expressions simple
  1416. const auto &LCtx = C.getLocationContext();
  1417. const auto NewPosSym = SymMgr.conjureSymbol(nullptr, LCtx,
  1418. SymMgr.getType(Pos.getOffset()),
  1419. C.blockCount());
  1420. State = assumeNoOverflow(State, NewPosSym, 4);
  1421. return Pos.setTo(NewPosSym);
  1422. }
  1423. }
  1424. void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
  1425. const SVal &Val, CheckerContext &C,
  1426. ExplodedNode *ErrNode) const {
  1427. auto R = llvm::make_unique<BugReport>(*OutOfRangeBugType, Message, ErrNode);
  1428. R->markInteresting(Val);
  1429. C.emitReport(std::move(R));
  1430. }
  1431. void IteratorChecker::reportMismatchedBug(const StringRef &Message,
  1432. const SVal &Val1, const SVal &Val2,
  1433. CheckerContext &C,
  1434. ExplodedNode *ErrNode) const {
  1435. auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
  1436. R->markInteresting(Val1);
  1437. R->markInteresting(Val2);
  1438. C.emitReport(std::move(R));
  1439. }
  1440. void IteratorChecker::reportMismatchedBug(const StringRef &Message,
  1441. const SVal &Val, const MemRegion *Reg,
  1442. CheckerContext &C,
  1443. ExplodedNode *ErrNode) const {
  1444. auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
  1445. R->markInteresting(Val);
  1446. R->markInteresting(Reg);
  1447. C.emitReport(std::move(R));
  1448. }
  1449. void IteratorChecker::reportInvalidatedBug(const StringRef &Message,
  1450. const SVal &Val, CheckerContext &C,
  1451. ExplodedNode *ErrNode) const {
  1452. auto R = llvm::make_unique<BugReport>(*InvalidatedBugType, Message, ErrNode);
  1453. R->markInteresting(Val);
  1454. C.emitReport(std::move(R));
  1455. }
  1456. namespace {
  1457. bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
  1458. bool isGreater(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
  1459. bool isEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2);
  1460. bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
  1461. BinaryOperator::Opcode Opc);
  1462. bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
  1463. BinaryOperator::Opcode Opc);
  1464. const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
  1465. const MemRegion *Reg);
  1466. SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB, SymbolRef Expr,
  1467. SymbolRef OldSym, SymbolRef NewSym);
  1468. bool isIteratorType(const QualType &Type) {
  1469. if (Type->isPointerType())
  1470. return true;
  1471. const auto *CRD = Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl();
  1472. return isIterator(CRD);
  1473. }
  1474. bool isIterator(const CXXRecordDecl *CRD) {
  1475. if (!CRD)
  1476. return false;
  1477. const auto Name = CRD->getName();
  1478. if (!(Name.endswith_lower("iterator") || Name.endswith_lower("iter") ||
  1479. Name.endswith_lower("it")))
  1480. return false;
  1481. bool HasCopyCtor = false, HasCopyAssign = true, HasDtor = false,
  1482. HasPreIncrOp = false, HasPostIncrOp = false, HasDerefOp = false;
  1483. for (const auto *Method : CRD->methods()) {
  1484. if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(Method)) {
  1485. if (Ctor->isCopyConstructor()) {
  1486. HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() == AS_public;
  1487. }
  1488. continue;
  1489. }
  1490. if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
  1491. HasDtor = !Dtor->isDeleted() && Dtor->getAccess() == AS_public;
  1492. continue;
  1493. }
  1494. if (Method->isCopyAssignmentOperator()) {
  1495. HasCopyAssign = !Method->isDeleted() && Method->getAccess() == AS_public;
  1496. continue;
  1497. }
  1498. if (!Method->isOverloadedOperator())
  1499. continue;
  1500. const auto OPK = Method->getOverloadedOperator();
  1501. if (OPK == OO_PlusPlus) {
  1502. HasPreIncrOp = HasPreIncrOp || (Method->getNumParams() == 0);
  1503. HasPostIncrOp = HasPostIncrOp || (Method->getNumParams() == 1);
  1504. continue;
  1505. }
  1506. if (OPK == OO_Star) {
  1507. HasDerefOp = (Method->getNumParams() == 0);
  1508. continue;
  1509. }
  1510. }
  1511. return HasCopyCtor && HasCopyAssign && HasDtor && HasPreIncrOp &&
  1512. HasPostIncrOp && HasDerefOp;
  1513. }
  1514. bool isComparisonOperator(OverloadedOperatorKind OK) {
  1515. return OK == OO_EqualEqual || OK == OO_ExclaimEqual || OK == OO_Less ||
  1516. OK == OO_LessEqual || OK == OO_Greater || OK == OO_GreaterEqual;
  1517. }
  1518. bool isBeginCall(const FunctionDecl *Func) {
  1519. const auto *IdInfo = Func->getIdentifier();
  1520. if (!IdInfo)
  1521. return false;
  1522. return IdInfo->getName().endswith_lower("begin");
  1523. }
  1524. bool isEndCall(const FunctionDecl *Func) {
  1525. const auto *IdInfo = Func->getIdentifier();
  1526. if (!IdInfo)
  1527. return false;
  1528. return IdInfo->getName().endswith_lower("end");
  1529. }
  1530. bool isAssignCall(const FunctionDecl *Func) {
  1531. const auto *IdInfo = Func->getIdentifier();
  1532. if (!IdInfo)
  1533. return false;
  1534. if (Func->getNumParams() > 2)
  1535. return false;
  1536. return IdInfo->getName() == "assign";
  1537. }
  1538. bool isClearCall(const FunctionDecl *Func) {
  1539. const auto *IdInfo = Func->getIdentifier();
  1540. if (!IdInfo)
  1541. return false;
  1542. if (Func->getNumParams() > 0)
  1543. return false;
  1544. return IdInfo->getName() == "clear";
  1545. }
  1546. bool isPushBackCall(const FunctionDecl *Func) {
  1547. const auto *IdInfo = Func->getIdentifier();
  1548. if (!IdInfo)
  1549. return false;
  1550. if (Func->getNumParams() != 1)
  1551. return false;
  1552. return IdInfo->getName() == "push_back";
  1553. }
  1554. bool isEmplaceBackCall(const FunctionDecl *Func) {
  1555. const auto *IdInfo = Func->getIdentifier();
  1556. if (!IdInfo)
  1557. return false;
  1558. if (Func->getNumParams() < 1)
  1559. return false;
  1560. return IdInfo->getName() == "emplace_back";
  1561. }
  1562. bool isPopBackCall(const FunctionDecl *Func) {
  1563. const auto *IdInfo = Func->getIdentifier();
  1564. if (!IdInfo)
  1565. return false;
  1566. if (Func->getNumParams() > 0)
  1567. return false;
  1568. return IdInfo->getName() == "pop_back";
  1569. }
  1570. bool isPushFrontCall(const FunctionDecl *Func) {
  1571. const auto *IdInfo = Func->getIdentifier();
  1572. if (!IdInfo)
  1573. return false;
  1574. if (Func->getNumParams() != 1)
  1575. return false;
  1576. return IdInfo->getName() == "push_front";
  1577. }
  1578. bool isEmplaceFrontCall(const FunctionDecl *Func) {
  1579. const auto *IdInfo = Func->getIdentifier();
  1580. if (!IdInfo)
  1581. return false;
  1582. if (Func->getNumParams() < 1)
  1583. return false;
  1584. return IdInfo->getName() == "emplace_front";
  1585. }
  1586. bool isPopFrontCall(const FunctionDecl *Func) {
  1587. const auto *IdInfo = Func->getIdentifier();
  1588. if (!IdInfo)
  1589. return false;
  1590. if (Func->getNumParams() > 0)
  1591. return false;
  1592. return IdInfo->getName() == "pop_front";
  1593. }
  1594. bool isInsertCall(const FunctionDecl *Func) {
  1595. const auto *IdInfo = Func->getIdentifier();
  1596. if (!IdInfo)
  1597. return false;
  1598. if (Func->getNumParams() < 2 || Func->getNumParams() > 3)
  1599. return false;
  1600. if (!isIteratorType(Func->getParamDecl(0)->getType()))
  1601. return false;
  1602. return IdInfo->getName() == "insert";
  1603. }
  1604. bool isEmplaceCall(const FunctionDecl *Func) {
  1605. const auto *IdInfo = Func->getIdentifier();
  1606. if (!IdInfo)
  1607. return false;
  1608. if (Func->getNumParams() < 2)
  1609. return false;
  1610. if (!isIteratorType(Func->getParamDecl(0)->getType()))
  1611. return false;
  1612. return IdInfo->getName() == "emplace";
  1613. }
  1614. bool isEraseCall(const FunctionDecl *Func) {
  1615. const auto *IdInfo = Func->getIdentifier();
  1616. if (!IdInfo)
  1617. return false;
  1618. if (Func->getNumParams() < 1 || Func->getNumParams() > 2)
  1619. return false;
  1620. if (!isIteratorType(Func->getParamDecl(0)->getType()))
  1621. return false;
  1622. if (Func->getNumParams() == 2 &&
  1623. !isIteratorType(Func->getParamDecl(1)->getType()))
  1624. return false;
  1625. return IdInfo->getName() == "erase";
  1626. }
  1627. bool isEraseAfterCall(const FunctionDecl *Func) {
  1628. const auto *IdInfo = Func->getIdentifier();
  1629. if (!IdInfo)
  1630. return false;
  1631. if (Func->getNumParams() < 1 || Func->getNumParams() > 2)
  1632. return false;
  1633. if (!isIteratorType(Func->getParamDecl(0)->getType()))
  1634. return false;
  1635. if (Func->getNumParams() == 2 &&
  1636. !isIteratorType(Func->getParamDecl(1)->getType()))
  1637. return false;
  1638. return IdInfo->getName() == "erase_after";
  1639. }
  1640. bool isAssignmentOperator(OverloadedOperatorKind OK) { return OK == OO_Equal; }
  1641. bool isSimpleComparisonOperator(OverloadedOperatorKind OK) {
  1642. return OK == OO_EqualEqual || OK == OO_ExclaimEqual;
  1643. }
  1644. bool isAccessOperator(OverloadedOperatorKind OK) {
  1645. return isDereferenceOperator(OK) || isIncrementOperator(OK) ||
  1646. isDecrementOperator(OK) || isRandomIncrOrDecrOperator(OK);
  1647. }
  1648. bool isDereferenceOperator(OverloadedOperatorKind OK) {
  1649. return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar ||
  1650. OK == OO_Subscript;
  1651. }
  1652. bool isIncrementOperator(OverloadedOperatorKind OK) {
  1653. return OK == OO_PlusPlus;
  1654. }
  1655. bool isDecrementOperator(OverloadedOperatorKind OK) {
  1656. return OK == OO_MinusMinus;
  1657. }
  1658. bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK) {
  1659. return OK == OO_Plus || OK == OO_PlusEqual || OK == OO_Minus ||
  1660. OK == OO_MinusEqual;
  1661. }
  1662. BinaryOperator::Opcode getOpcode(const SymExpr *SE) {
  1663. if (const auto *BSE = dyn_cast<BinarySymExpr>(SE)) {
  1664. return BSE->getOpcode();
  1665. } else if (const auto *SC = dyn_cast<SymbolConjured>(SE)) {
  1666. const auto *COE = dyn_cast_or_null<CXXOperatorCallExpr>(SC->getStmt());
  1667. if (!COE)
  1668. return BO_Comma; // Extremal value, neither EQ nor NE
  1669. if (COE->getOperator() == OO_EqualEqual) {
  1670. return BO_EQ;
  1671. } else if (COE->getOperator() == OO_ExclaimEqual) {
  1672. return BO_NE;
  1673. }
  1674. return BO_Comma; // Extremal value, neither EQ nor NE
  1675. }
  1676. return BO_Comma; // Extremal value, neither EQ nor NE
  1677. }
  1678. bool hasSubscriptOperator(ProgramStateRef State, const MemRegion *Reg) {
  1679. const auto *CRD = getCXXRecordDecl(State, Reg);
  1680. if (!CRD)
  1681. return false;
  1682. for (const auto *Method : CRD->methods()) {
  1683. if (!Method->isOverloadedOperator())
  1684. continue;
  1685. const auto OPK = Method->getOverloadedOperator();
  1686. if (OPK == OO_Subscript) {
  1687. return true;
  1688. }
  1689. }
  1690. return false;
  1691. }
  1692. bool frontModifiable(ProgramStateRef State, const MemRegion *Reg) {
  1693. const auto *CRD = getCXXRecordDecl(State, Reg);
  1694. if (!CRD)
  1695. return false;
  1696. for (const auto *Method : CRD->methods()) {
  1697. if (!Method->getDeclName().isIdentifier())
  1698. continue;
  1699. if (Method->getName() == "push_front" || Method->getName() == "pop_front") {
  1700. return true;
  1701. }
  1702. }
  1703. return false;
  1704. }
  1705. bool backModifiable(ProgramStateRef State, const MemRegion *Reg) {
  1706. const auto *CRD = getCXXRecordDecl(State, Reg);
  1707. if (!CRD)
  1708. return false;
  1709. for (const auto *Method : CRD->methods()) {
  1710. if (!Method->getDeclName().isIdentifier())
  1711. continue;
  1712. if (Method->getName() == "push_back" || Method->getName() == "pop_back") {
  1713. return true;
  1714. }
  1715. }
  1716. return false;
  1717. }
  1718. const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
  1719. const MemRegion *Reg) {
  1720. auto TI = getDynamicTypeInfo(State, Reg);
  1721. if (!TI.isValid())
  1722. return nullptr;
  1723. auto Type = TI.getType();
  1724. if (const auto *RefT = Type->getAs<ReferenceType>()) {
  1725. Type = RefT->getPointeeType();
  1726. }
  1727. return Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl();
  1728. }
  1729. const RegionOrSymbol getRegionOrSymbol(const SVal &Val) {
  1730. if (const auto Reg = Val.getAsRegion()) {
  1731. return Reg;
  1732. } else if (const auto Sym = Val.getAsSymbol()) {
  1733. return Sym;
  1734. } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
  1735. return LCVal->getRegion();
  1736. }
  1737. return RegionOrSymbol();
  1738. }
  1739. const ProgramStateRef processComparison(ProgramStateRef State,
  1740. RegionOrSymbol LVal,
  1741. RegionOrSymbol RVal, bool Equal) {
  1742. const auto *LPos = getIteratorPosition(State, LVal);
  1743. const auto *RPos = getIteratorPosition(State, RVal);
  1744. if (LPos && !RPos) {
  1745. State = adjustIteratorPosition(State, RVal, *LPos, Equal);
  1746. } else if (!LPos && RPos) {
  1747. State = adjustIteratorPosition(State, LVal, *RPos, Equal);
  1748. } else if (LPos && RPos) {
  1749. State = relateIteratorPositions(State, *LPos, *RPos, Equal);
  1750. }
  1751. return State;
  1752. }
  1753. const ProgramStateRef saveComparison(ProgramStateRef State,
  1754. const SymExpr *Condition, const SVal &LVal,
  1755. const SVal &RVal, bool Eq) {
  1756. const auto Left = getRegionOrSymbol(LVal);
  1757. const auto Right = getRegionOrSymbol(RVal);
  1758. if (!Left || !Right)
  1759. return State;
  1760. return State->set<IteratorComparisonMap>(Condition,
  1761. IteratorComparison(Left, Right, Eq));
  1762. }
  1763. const IteratorComparison *loadComparison(ProgramStateRef State,
  1764. const SymExpr *Condition) {
  1765. return State->get<IteratorComparisonMap>(Condition);
  1766. }
  1767. SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont) {
  1768. const auto *CDataPtr = getContainerData(State, Cont);
  1769. if (!CDataPtr)
  1770. return nullptr;
  1771. return CDataPtr->getBegin();
  1772. }
  1773. SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
  1774. const auto *CDataPtr = getContainerData(State, Cont);
  1775. if (!CDataPtr)
  1776. return nullptr;
  1777. return CDataPtr->getEnd();
  1778. }
  1779. ProgramStateRef createContainerBegin(ProgramStateRef State,
  1780. const MemRegion *Cont,
  1781. const SymbolRef Sym) {
  1782. // Only create if it does not exist
  1783. const auto *CDataPtr = getContainerData(State, Cont);
  1784. if (CDataPtr) {
  1785. if (CDataPtr->getBegin()) {
  1786. return State;
  1787. }
  1788. const auto CData = CDataPtr->newBegin(Sym);
  1789. return setContainerData(State, Cont, CData);
  1790. }
  1791. const auto CData = ContainerData::fromBegin(Sym);
  1792. return setContainerData(State, Cont, CData);
  1793. }
  1794. ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
  1795. const SymbolRef Sym) {
  1796. // Only create if it does not exist
  1797. const auto *CDataPtr = getContainerData(State, Cont);
  1798. if (CDataPtr) {
  1799. if (CDataPtr->getEnd()) {
  1800. return State;
  1801. }
  1802. const auto CData = CDataPtr->newEnd(Sym);
  1803. return setContainerData(State, Cont, CData);
  1804. }
  1805. const auto CData = ContainerData::fromEnd(Sym);
  1806. return setContainerData(State, Cont, CData);
  1807. }
  1808. const ContainerData *getContainerData(ProgramStateRef State,
  1809. const MemRegion *Cont) {
  1810. return State->get<ContainerMap>(Cont);
  1811. }
  1812. ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
  1813. const ContainerData &CData) {
  1814. return State->set<ContainerMap>(Cont, CData);
  1815. }
  1816. const IteratorPosition *getIteratorPosition(ProgramStateRef State,
  1817. const SVal &Val) {
  1818. if (auto Reg = Val.getAsRegion()) {
  1819. Reg = Reg->getMostDerivedObjectRegion();
  1820. return State->get<IteratorRegionMap>(Reg);
  1821. } else if (const auto Sym = Val.getAsSymbol()) {
  1822. return State->get<IteratorSymbolMap>(Sym);
  1823. } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
  1824. return State->get<IteratorRegionMap>(LCVal->getRegion());
  1825. }
  1826. return nullptr;
  1827. }
  1828. const IteratorPosition *getIteratorPosition(ProgramStateRef State,
  1829. RegionOrSymbol RegOrSym) {
  1830. if (RegOrSym.is<const MemRegion *>()) {
  1831. auto Reg = RegOrSym.get<const MemRegion *>()->getMostDerivedObjectRegion();
  1832. return State->get<IteratorRegionMap>(Reg);
  1833. } else if (RegOrSym.is<SymbolRef>()) {
  1834. return State->get<IteratorSymbolMap>(RegOrSym.get<SymbolRef>());
  1835. }
  1836. return nullptr;
  1837. }
  1838. ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
  1839. const IteratorPosition &Pos) {
  1840. if (auto Reg = Val.getAsRegion()) {
  1841. Reg = Reg->getMostDerivedObjectRegion();
  1842. return State->set<IteratorRegionMap>(Reg, Pos);
  1843. } else if (const auto Sym = Val.getAsSymbol()) {
  1844. return State->set<IteratorSymbolMap>(Sym, Pos);
  1845. } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
  1846. return State->set<IteratorRegionMap>(LCVal->getRegion(), Pos);
  1847. }
  1848. return nullptr;
  1849. }
  1850. ProgramStateRef setIteratorPosition(ProgramStateRef State,
  1851. RegionOrSymbol RegOrSym,
  1852. const IteratorPosition &Pos) {
  1853. if (RegOrSym.is<const MemRegion *>()) {
  1854. auto Reg = RegOrSym.get<const MemRegion *>()->getMostDerivedObjectRegion();
  1855. return State->set<IteratorRegionMap>(Reg, Pos);
  1856. } else if (RegOrSym.is<SymbolRef>()) {
  1857. return State->set<IteratorSymbolMap>(RegOrSym.get<SymbolRef>(), Pos);
  1858. }
  1859. return nullptr;
  1860. }
  1861. ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val) {
  1862. if (auto Reg = Val.getAsRegion()) {
  1863. Reg = Reg->getMostDerivedObjectRegion();
  1864. return State->remove<IteratorRegionMap>(Reg);
  1865. } else if (const auto Sym = Val.getAsSymbol()) {
  1866. return State->remove<IteratorSymbolMap>(Sym);
  1867. } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
  1868. return State->remove<IteratorRegionMap>(LCVal->getRegion());
  1869. }
  1870. return nullptr;
  1871. }
  1872. ProgramStateRef adjustIteratorPosition(ProgramStateRef State,
  1873. RegionOrSymbol RegOrSym,
  1874. const IteratorPosition &Pos,
  1875. bool Equal) {
  1876. if (Equal) {
  1877. return setIteratorPosition(State, RegOrSym, Pos);
  1878. } else {
  1879. return State;
  1880. }
  1881. }
  1882. ProgramStateRef relateIteratorPositions(ProgramStateRef State,
  1883. const IteratorPosition &Pos1,
  1884. const IteratorPosition &Pos2,
  1885. bool Equal) {
  1886. auto &SVB = State->getStateManager().getSValBuilder();
  1887. // FIXME: This code should be reworked as follows:
  1888. // 1. Subtract the operands using evalBinOp().
  1889. // 2. Assume that the result doesn't overflow.
  1890. // 3. Compare the result to 0.
  1891. // 4. Assume the result of the comparison.
  1892. const auto comparison =
  1893. SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()),
  1894. nonloc::SymbolVal(Pos2.getOffset()),
  1895. SVB.getConditionType());
  1896. assert(comparison.getAs<DefinedSVal>() &&
  1897. "Symbol comparison must be a `DefinedSVal`");
  1898. auto NewState = State->assume(comparison.castAs<DefinedSVal>(), Equal);
  1899. if (const auto CompSym = comparison.getAsSymbol()) {
  1900. assert(isa<SymIntExpr>(CompSym) &&
  1901. "Symbol comparison must be a `SymIntExpr`");
  1902. assert(BinaryOperator::isComparisonOp(
  1903. cast<SymIntExpr>(CompSym)->getOpcode()) &&
  1904. "Symbol comparison must be a comparison");
  1905. return assumeNoOverflow(NewState, cast<SymIntExpr>(CompSym)->getLHS(), 2);
  1906. }
  1907. return NewState;
  1908. }
  1909. bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
  1910. auto RegionMap = State->get<IteratorRegionMap>();
  1911. for (const auto Reg : RegionMap) {
  1912. if (Reg.second.getContainer() == Cont)
  1913. return true;
  1914. }
  1915. auto SymbolMap = State->get<IteratorSymbolMap>();
  1916. for (const auto Sym : SymbolMap) {
  1917. if (Sym.second.getContainer() == Cont)
  1918. return true;
  1919. }
  1920. return false;
  1921. }
  1922. bool isBoundThroughLazyCompoundVal(const Environment &Env,
  1923. const MemRegion *Reg) {
  1924. for (const auto Binding: Env) {
  1925. if (const auto LCVal = Binding.second.getAs<nonloc::LazyCompoundVal>()) {
  1926. if (LCVal->getRegion() == Reg)
  1927. return true;
  1928. }
  1929. }
  1930. return false;
  1931. }
  1932. template <typename Condition, typename Process>
  1933. ProgramStateRef processIteratorPositions(ProgramStateRef State, Condition Cond,
  1934. Process Proc) {
  1935. auto &RegionMapFactory = State->get_context<IteratorRegionMap>();
  1936. auto RegionMap = State->get<IteratorRegionMap>();
  1937. bool Changed = false;
  1938. for (const auto Reg : RegionMap) {
  1939. if (Cond(Reg.second)) {
  1940. RegionMap = RegionMapFactory.add(RegionMap, Reg.first, Proc(Reg.second));
  1941. Changed = true;
  1942. }
  1943. }
  1944. if (Changed)
  1945. State = State->set<IteratorRegionMap>(RegionMap);
  1946. auto &SymbolMapFactory = State->get_context<IteratorSymbolMap>();
  1947. auto SymbolMap = State->get<IteratorSymbolMap>();
  1948. Changed = false;
  1949. for (const auto Sym : SymbolMap) {
  1950. if (Cond(Sym.second)) {
  1951. SymbolMap = SymbolMapFactory.add(SymbolMap, Sym.first, Proc(Sym.second));
  1952. Changed = true;
  1953. }
  1954. }
  1955. if (Changed)
  1956. State = State->set<IteratorSymbolMap>(SymbolMap);
  1957. return State;
  1958. }
  1959. ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
  1960. const MemRegion *Cont) {
  1961. auto MatchCont = [&](const IteratorPosition &Pos) {
  1962. return Pos.getContainer() == Cont;
  1963. };
  1964. auto Invalidate = [&](const IteratorPosition &Pos) {
  1965. return Pos.invalidate();
  1966. };
  1967. return processIteratorPositions(State, MatchCont, Invalidate);
  1968. }
  1969. ProgramStateRef
  1970. invalidateAllIteratorPositionsExcept(ProgramStateRef State,
  1971. const MemRegion *Cont, SymbolRef Offset,
  1972. BinaryOperator::Opcode Opc) {
  1973. auto MatchContAndCompare = [&](const IteratorPosition &Pos) {
  1974. return Pos.getContainer() == Cont &&
  1975. !compare(State, Pos.getOffset(), Offset, Opc);
  1976. };
  1977. auto Invalidate = [&](const IteratorPosition &Pos) {
  1978. return Pos.invalidate();
  1979. };
  1980. return processIteratorPositions(State, MatchContAndCompare, Invalidate);
  1981. }
  1982. ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
  1983. SymbolRef Offset,
  1984. BinaryOperator::Opcode Opc) {
  1985. auto Compare = [&](const IteratorPosition &Pos) {
  1986. return compare(State, Pos.getOffset(), Offset, Opc);
  1987. };
  1988. auto Invalidate = [&](const IteratorPosition &Pos) {
  1989. return Pos.invalidate();
  1990. };
  1991. return processIteratorPositions(State, Compare, Invalidate);
  1992. }
  1993. ProgramStateRef invalidateIteratorPositions(ProgramStateRef State,
  1994. SymbolRef Offset1,
  1995. BinaryOperator::Opcode Opc1,
  1996. SymbolRef Offset2,
  1997. BinaryOperator::Opcode Opc2) {
  1998. auto Compare = [&](const IteratorPosition &Pos) {
  1999. return compare(State, Pos.getOffset(), Offset1, Opc1) &&
  2000. compare(State, Pos.getOffset(), Offset2, Opc2);
  2001. };
  2002. auto Invalidate = [&](const IteratorPosition &Pos) {
  2003. return Pos.invalidate();
  2004. };
  2005. return processIteratorPositions(State, Compare, Invalidate);
  2006. }
  2007. ProgramStateRef reassignAllIteratorPositions(ProgramStateRef State,
  2008. const MemRegion *Cont,
  2009. const MemRegion *NewCont) {
  2010. auto MatchCont = [&](const IteratorPosition &Pos) {
  2011. return Pos.getContainer() == Cont;
  2012. };
  2013. auto ReAssign = [&](const IteratorPosition &Pos) {
  2014. return Pos.reAssign(NewCont);
  2015. };
  2016. return processIteratorPositions(State, MatchCont, ReAssign);
  2017. }
  2018. ProgramStateRef reassignAllIteratorPositionsUnless(ProgramStateRef State,
  2019. const MemRegion *Cont,
  2020. const MemRegion *NewCont,
  2021. SymbolRef Offset,
  2022. BinaryOperator::Opcode Opc) {
  2023. auto MatchContAndCompare = [&](const IteratorPosition &Pos) {
  2024. return Pos.getContainer() == Cont &&
  2025. !compare(State, Pos.getOffset(), Offset, Opc);
  2026. };
  2027. auto ReAssign = [&](const IteratorPosition &Pos) {
  2028. return Pos.reAssign(NewCont);
  2029. };
  2030. return processIteratorPositions(State, MatchContAndCompare, ReAssign);
  2031. }
  2032. // This function rebases symbolic expression `OldSym + Int` to `NewSym + Int`,
  2033. // `OldSym - Int` to `NewSym - Int` and `OldSym` to `NewSym` in any iterator
  2034. // position offsets where `CondSym` is true.
  2035. ProgramStateRef rebaseSymbolInIteratorPositionsIf(
  2036. ProgramStateRef State, SValBuilder &SVB, SymbolRef OldSym,
  2037. SymbolRef NewSym, SymbolRef CondSym, BinaryOperator::Opcode Opc) {
  2038. auto LessThanEnd = [&](const IteratorPosition &Pos) {
  2039. return compare(State, Pos.getOffset(), CondSym, Opc);
  2040. };
  2041. auto RebaseSymbol = [&](const IteratorPosition &Pos) {
  2042. return Pos.setTo(rebaseSymbol(State, SVB, Pos.getOffset(), OldSym,
  2043. NewSym));
  2044. };
  2045. return processIteratorPositions(State, LessThanEnd, RebaseSymbol);
  2046. }
  2047. // This function rebases symbolic expression `OldExpr + Int` to `NewExpr + Int`,
  2048. // `OldExpr - Int` to `NewExpr - Int` and `OldExpr` to `NewExpr` in expression
  2049. // `OrigExpr`.
  2050. SymbolRef rebaseSymbol(ProgramStateRef State, SValBuilder &SVB,
  2051. SymbolRef OrigExpr, SymbolRef OldExpr,
  2052. SymbolRef NewSym) {
  2053. auto &SymMgr = SVB.getSymbolManager();
  2054. auto Diff = SVB.evalBinOpNN(State, BO_Sub, nonloc::SymbolVal(OrigExpr),
  2055. nonloc::SymbolVal(OldExpr),
  2056. SymMgr.getType(OrigExpr));
  2057. const auto DiffInt = Diff.getAs<nonloc::ConcreteInt>();
  2058. if (!DiffInt)
  2059. return OrigExpr;
  2060. return SVB.evalBinOpNN(State, BO_Add, *DiffInt, nonloc::SymbolVal(NewSym),
  2061. SymMgr.getType(OrigExpr)).getAsSymbol();
  2062. }
  2063. bool isZero(ProgramStateRef State, const NonLoc &Val) {
  2064. auto &BVF = State->getBasicVals();
  2065. return compare(State, Val,
  2066. nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))),
  2067. BO_EQ);
  2068. }
  2069. bool isPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos) {
  2070. const auto *Cont = Pos.getContainer();
  2071. const auto *CData = getContainerData(State, Cont);
  2072. if (!CData)
  2073. return false;
  2074. const auto End = CData->getEnd();
  2075. if (End) {
  2076. if (isEqual(State, Pos.getOffset(), End)) {
  2077. return true;
  2078. }
  2079. }
  2080. return false;
  2081. }
  2082. bool isAheadOfRange(ProgramStateRef State, const IteratorPosition &Pos) {
  2083. const auto *Cont = Pos.getContainer();
  2084. const auto *CData = getContainerData(State, Cont);
  2085. if (!CData)
  2086. return false;
  2087. const auto Beg = CData->getBegin();
  2088. if (Beg) {
  2089. if (isLess(State, Pos.getOffset(), Beg)) {
  2090. return true;
  2091. }
  2092. }
  2093. return false;
  2094. }
  2095. bool isBehindPastTheEnd(ProgramStateRef State, const IteratorPosition &Pos) {
  2096. const auto *Cont = Pos.getContainer();
  2097. const auto *CData = getContainerData(State, Cont);
  2098. if (!CData)
  2099. return false;
  2100. const auto End = CData->getEnd();
  2101. if (End) {
  2102. if (isGreater(State, Pos.getOffset(), End)) {
  2103. return true;
  2104. }
  2105. }
  2106. return false;
  2107. }
  2108. bool isLess(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
  2109. return compare(State, Sym1, Sym2, BO_LT);
  2110. }
  2111. bool isGreater(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
  2112. return compare(State, Sym1, Sym2, BO_GT);
  2113. }
  2114. bool isEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) {
  2115. return compare(State, Sym1, Sym2, BO_EQ);
  2116. }
  2117. bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
  2118. BinaryOperator::Opcode Opc) {
  2119. return compare(State, nonloc::SymbolVal(Sym1), nonloc::SymbolVal(Sym2), Opc);
  2120. }
  2121. bool compare(ProgramStateRef State, NonLoc NL1, NonLoc NL2,
  2122. BinaryOperator::Opcode Opc) {
  2123. auto &SVB = State->getStateManager().getSValBuilder();
  2124. const auto comparison =
  2125. SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
  2126. assert(comparison.getAs<DefinedSVal>() &&
  2127. "Symbol comparison must be a `DefinedSVal`");
  2128. return !State->assume(comparison.castAs<DefinedSVal>(), false);
  2129. }
  2130. } // namespace
  2131. #define REGISTER_CHECKER(name) \
  2132. void ento::register##name(CheckerManager &Mgr) { \
  2133. auto *checker = Mgr.registerChecker<IteratorChecker>(); \
  2134. checker->ChecksEnabled[IteratorChecker::CK_##name] = true; \
  2135. checker->CheckNames[IteratorChecker::CK_##name] = \
  2136. Mgr.getCurrentCheckName(); \
  2137. }
  2138. REGISTER_CHECKER(IteratorRangeChecker)
  2139. REGISTER_CHECKER(MismatchedIteratorChecker)
  2140. REGISTER_CHECKER(InvalidatedIteratorChecker)