IteratorChecker.cpp 86 KB

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