CheckerManager.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. //===- CheckerManager.cpp - Static Analyzer Checker Manager ---------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Defines the Static Analyzer Checker Manager.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  14. #include "clang/AST/DeclBase.h"
  15. #include "clang/AST/Stmt.h"
  16. #include "clang/Analysis/ProgramPoint.h"
  17. #include "clang/Basic/LLVM.h"
  18. #include "clang/StaticAnalyzer/Core/Checker.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  24. #include "llvm/ADT/SmallVector.h"
  25. #include "llvm/Support/Casting.h"
  26. #include "llvm/Support/ErrorHandling.h"
  27. #include <cassert>
  28. #include <vector>
  29. using namespace clang;
  30. using namespace ento;
  31. bool CheckerManager::hasPathSensitiveCheckers() const {
  32. return !StmtCheckers.empty() ||
  33. !PreObjCMessageCheckers.empty() ||
  34. !PostObjCMessageCheckers.empty() ||
  35. !PreCallCheckers.empty() ||
  36. !PostCallCheckers.empty() ||
  37. !LocationCheckers.empty() ||
  38. !BindCheckers.empty() ||
  39. !EndAnalysisCheckers.empty() ||
  40. !EndFunctionCheckers.empty() ||
  41. !BranchConditionCheckers.empty() ||
  42. !LiveSymbolsCheckers.empty() ||
  43. !DeadSymbolsCheckers.empty() ||
  44. !RegionChangesCheckers.empty() ||
  45. !EvalAssumeCheckers.empty() ||
  46. !EvalCallCheckers.empty();
  47. }
  48. void CheckerManager::finishedCheckerRegistration() {
  49. #ifndef NDEBUG
  50. // Make sure that for every event that has listeners, there is at least
  51. // one dispatcher registered for it.
  52. for (const auto &Event : Events)
  53. assert(Event.second.HasDispatcher &&
  54. "No dispatcher registered for an event");
  55. #endif
  56. }
  57. //===----------------------------------------------------------------------===//
  58. // Functions for running checkers for AST traversing..
  59. //===----------------------------------------------------------------------===//
  60. void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
  61. BugReporter &BR) {
  62. assert(D);
  63. unsigned DeclKind = D->getKind();
  64. CachedDeclCheckers *checkers = nullptr;
  65. CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
  66. if (CCI != CachedDeclCheckersMap.end()) {
  67. checkers = &(CCI->second);
  68. } else {
  69. // Find the checkers that should run for this Decl and cache them.
  70. checkers = &CachedDeclCheckersMap[DeclKind];
  71. for (const auto &info : DeclCheckers)
  72. if (info.IsForDeclFn(D))
  73. checkers->push_back(info.CheckFn);
  74. }
  75. assert(checkers);
  76. for (const auto checker : *checkers)
  77. checker(D, mgr, BR);
  78. }
  79. void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
  80. BugReporter &BR) {
  81. assert(D && D->hasBody());
  82. for (const auto BodyChecker : BodyCheckers)
  83. BodyChecker(D, mgr, BR);
  84. }
  85. //===----------------------------------------------------------------------===//
  86. // Functions for running checkers for path-sensitive checking.
  87. //===----------------------------------------------------------------------===//
  88. template <typename CHECK_CTX>
  89. static void expandGraphWithCheckers(CHECK_CTX checkCtx,
  90. ExplodedNodeSet &Dst,
  91. const ExplodedNodeSet &Src) {
  92. const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
  93. if (Src.empty())
  94. return;
  95. typename CHECK_CTX::CheckersTy::const_iterator
  96. I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
  97. if (I == E) {
  98. Dst.insert(Src);
  99. return;
  100. }
  101. ExplodedNodeSet Tmp1, Tmp2;
  102. const ExplodedNodeSet *PrevSet = &Src;
  103. for (; I != E; ++I) {
  104. ExplodedNodeSet *CurrSet = nullptr;
  105. if (I+1 == E)
  106. CurrSet = &Dst;
  107. else {
  108. CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
  109. CurrSet->clear();
  110. }
  111. NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
  112. for (const auto &NI : *PrevSet)
  113. checkCtx.runChecker(*I, B, NI);
  114. // If all the produced transitions are sinks, stop.
  115. if (CurrSet->empty())
  116. return;
  117. // Update which NodeSet is the current one.
  118. PrevSet = CurrSet;
  119. }
  120. }
  121. namespace {
  122. struct CheckStmtContext {
  123. using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
  124. bool IsPreVisit;
  125. const CheckersTy &Checkers;
  126. const Stmt *S;
  127. ExprEngine &Eng;
  128. bool WasInlined;
  129. CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
  130. const Stmt *s, ExprEngine &eng, bool wasInlined = false)
  131. : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
  132. WasInlined(wasInlined) {}
  133. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  134. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  135. void runChecker(CheckerManager::CheckStmtFunc checkFn,
  136. NodeBuilder &Bldr, ExplodedNode *Pred) {
  137. // FIXME: Remove respondsToCallback from CheckerContext;
  138. ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind :
  139. ProgramPoint::PostStmtKind;
  140. const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
  141. Pred->getLocationContext(), checkFn.Checker);
  142. CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
  143. checkFn(S, C);
  144. }
  145. };
  146. } // namespace
  147. /// \brief Run checkers for visiting Stmts.
  148. void CheckerManager::runCheckersForStmt(bool isPreVisit,
  149. ExplodedNodeSet &Dst,
  150. const ExplodedNodeSet &Src,
  151. const Stmt *S,
  152. ExprEngine &Eng,
  153. bool WasInlined) {
  154. CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
  155. S, Eng, WasInlined);
  156. expandGraphWithCheckers(C, Dst, Src);
  157. }
  158. namespace {
  159. struct CheckObjCMessageContext {
  160. using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
  161. ObjCMessageVisitKind Kind;
  162. bool WasInlined;
  163. const CheckersTy &Checkers;
  164. const ObjCMethodCall &Msg;
  165. ExprEngine &Eng;
  166. CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
  167. const CheckersTy &checkers,
  168. const ObjCMethodCall &msg, ExprEngine &eng,
  169. bool wasInlined)
  170. : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
  171. Eng(eng) {}
  172. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  173. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  174. void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
  175. NodeBuilder &Bldr, ExplodedNode *Pred) {
  176. bool IsPreVisit;
  177. switch (Kind) {
  178. case ObjCMessageVisitKind::Pre:
  179. IsPreVisit = true;
  180. break;
  181. case ObjCMessageVisitKind::MessageNil:
  182. case ObjCMessageVisitKind::Post:
  183. IsPreVisit = false;
  184. break;
  185. }
  186. const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
  187. CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
  188. checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
  189. }
  190. };
  191. } // namespace
  192. /// \brief Run checkers for visiting obj-c messages.
  193. void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
  194. ExplodedNodeSet &Dst,
  195. const ExplodedNodeSet &Src,
  196. const ObjCMethodCall &msg,
  197. ExprEngine &Eng,
  198. bool WasInlined) {
  199. auto &checkers = getObjCMessageCheckers(visitKind);
  200. CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
  201. expandGraphWithCheckers(C, Dst, Src);
  202. }
  203. const std::vector<CheckerManager::CheckObjCMessageFunc> &
  204. CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
  205. switch (Kind) {
  206. case ObjCMessageVisitKind::Pre:
  207. return PreObjCMessageCheckers;
  208. break;
  209. case ObjCMessageVisitKind::Post:
  210. return PostObjCMessageCheckers;
  211. case ObjCMessageVisitKind::MessageNil:
  212. return ObjCMessageNilCheckers;
  213. }
  214. llvm_unreachable("Unknown Kind");
  215. }
  216. namespace {
  217. // FIXME: This has all the same signatures as CheckObjCMessageContext.
  218. // Is there a way we can merge the two?
  219. struct CheckCallContext {
  220. using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
  221. bool IsPreVisit, WasInlined;
  222. const CheckersTy &Checkers;
  223. const CallEvent &Call;
  224. ExprEngine &Eng;
  225. CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
  226. const CallEvent &call, ExprEngine &eng,
  227. bool wasInlined)
  228. : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
  229. Call(call), Eng(eng) {}
  230. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  231. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  232. void runChecker(CheckerManager::CheckCallFunc checkFn,
  233. NodeBuilder &Bldr, ExplodedNode *Pred) {
  234. const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
  235. CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
  236. checkFn(*Call.cloneWithState(Pred->getState()), C);
  237. }
  238. };
  239. } // namespace
  240. /// \brief Run checkers for visiting an abstract call event.
  241. void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
  242. ExplodedNodeSet &Dst,
  243. const ExplodedNodeSet &Src,
  244. const CallEvent &Call,
  245. ExprEngine &Eng,
  246. bool WasInlined) {
  247. CheckCallContext C(isPreVisit,
  248. isPreVisit ? PreCallCheckers
  249. : PostCallCheckers,
  250. Call, Eng, WasInlined);
  251. expandGraphWithCheckers(C, Dst, Src);
  252. }
  253. namespace {
  254. struct CheckLocationContext {
  255. using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
  256. const CheckersTy &Checkers;
  257. SVal Loc;
  258. bool IsLoad;
  259. const Stmt *NodeEx; /* Will become a CFGStmt */
  260. const Stmt *BoundEx;
  261. ExprEngine &Eng;
  262. CheckLocationContext(const CheckersTy &checkers,
  263. SVal loc, bool isLoad, const Stmt *NodeEx,
  264. const Stmt *BoundEx,
  265. ExprEngine &eng)
  266. : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
  267. BoundEx(BoundEx), Eng(eng) {}
  268. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  269. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  270. void runChecker(CheckerManager::CheckLocationFunc checkFn,
  271. NodeBuilder &Bldr, ExplodedNode *Pred) {
  272. ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind :
  273. ProgramPoint::PreStoreKind;
  274. const ProgramPoint &L =
  275. ProgramPoint::getProgramPoint(NodeEx, K,
  276. Pred->getLocationContext(),
  277. checkFn.Checker);
  278. CheckerContext C(Bldr, Eng, Pred, L);
  279. checkFn(Loc, IsLoad, BoundEx, C);
  280. }
  281. };
  282. } // namespace
  283. /// \brief Run checkers for load/store of a location.
  284. void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
  285. const ExplodedNodeSet &Src,
  286. SVal location, bool isLoad,
  287. const Stmt *NodeEx,
  288. const Stmt *BoundEx,
  289. ExprEngine &Eng) {
  290. CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
  291. BoundEx, Eng);
  292. expandGraphWithCheckers(C, Dst, Src);
  293. }
  294. namespace {
  295. struct CheckBindContext {
  296. using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
  297. const CheckersTy &Checkers;
  298. SVal Loc;
  299. SVal Val;
  300. const Stmt *S;
  301. ExprEngine &Eng;
  302. const ProgramPoint &PP;
  303. CheckBindContext(const CheckersTy &checkers,
  304. SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
  305. const ProgramPoint &pp)
  306. : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
  307. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  308. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  309. void runChecker(CheckerManager::CheckBindFunc checkFn,
  310. NodeBuilder &Bldr, ExplodedNode *Pred) {
  311. const ProgramPoint &L = PP.withTag(checkFn.Checker);
  312. CheckerContext C(Bldr, Eng, Pred, L);
  313. checkFn(Loc, Val, S, C);
  314. }
  315. };
  316. } // namespace
  317. /// \brief Run checkers for binding of a value to a location.
  318. void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
  319. const ExplodedNodeSet &Src,
  320. SVal location, SVal val,
  321. const Stmt *S, ExprEngine &Eng,
  322. const ProgramPoint &PP) {
  323. CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
  324. expandGraphWithCheckers(C, Dst, Src);
  325. }
  326. void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
  327. BugReporter &BR,
  328. ExprEngine &Eng) {
  329. for (const auto EndAnalysisChecker : EndAnalysisCheckers)
  330. EndAnalysisChecker(G, BR, Eng);
  331. }
  332. namespace {
  333. struct CheckBeginFunctionContext {
  334. using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
  335. const CheckersTy &Checkers;
  336. ExprEngine &Eng;
  337. const ProgramPoint &PP;
  338. CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
  339. const ProgramPoint &PP)
  340. : Checkers(Checkers), Eng(Eng), PP(PP) {}
  341. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  342. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  343. void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
  344. NodeBuilder &Bldr, ExplodedNode *Pred) {
  345. const ProgramPoint &L = PP.withTag(checkFn.Checker);
  346. CheckerContext C(Bldr, Eng, Pred, L);
  347. checkFn(C);
  348. }
  349. };
  350. } // namespace
  351. void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
  352. const BlockEdge &L,
  353. ExplodedNode *Pred,
  354. ExprEngine &Eng) {
  355. ExplodedNodeSet Src;
  356. Src.insert(Pred);
  357. CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
  358. expandGraphWithCheckers(C, Dst, Src);
  359. }
  360. /// \brief Run checkers for end of path.
  361. // Note, We do not chain the checker output (like in expandGraphWithCheckers)
  362. // for this callback since end of path nodes are expected to be final.
  363. void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
  364. ExplodedNodeSet &Dst,
  365. ExplodedNode *Pred,
  366. ExprEngine &Eng) {
  367. // We define the builder outside of the loop bacause if at least one checkers
  368. // creates a sucsessor for Pred, we do not need to generate an
  369. // autotransition for it.
  370. NodeBuilder Bldr(Pred, Dst, BC);
  371. for (const auto checkFn : EndFunctionCheckers) {
  372. const ProgramPoint &L = BlockEntrance(BC.Block,
  373. Pred->getLocationContext(),
  374. checkFn.Checker);
  375. CheckerContext C(Bldr, Eng, Pred, L);
  376. checkFn(C);
  377. }
  378. }
  379. namespace {
  380. struct CheckBranchConditionContext {
  381. using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
  382. const CheckersTy &Checkers;
  383. const Stmt *Condition;
  384. ExprEngine &Eng;
  385. CheckBranchConditionContext(const CheckersTy &checkers,
  386. const Stmt *Cond, ExprEngine &eng)
  387. : Checkers(checkers), Condition(Cond), Eng(eng) {}
  388. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  389. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  390. void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
  391. NodeBuilder &Bldr, ExplodedNode *Pred) {
  392. ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
  393. checkFn.Checker);
  394. CheckerContext C(Bldr, Eng, Pred, L);
  395. checkFn(Condition, C);
  396. }
  397. };
  398. } // namespace
  399. /// \brief Run checkers for branch condition.
  400. void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
  401. ExplodedNodeSet &Dst,
  402. ExplodedNode *Pred,
  403. ExprEngine &Eng) {
  404. ExplodedNodeSet Src;
  405. Src.insert(Pred);
  406. CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
  407. expandGraphWithCheckers(C, Dst, Src);
  408. }
  409. namespace {
  410. struct CheckNewAllocatorContext {
  411. using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
  412. const CheckersTy &Checkers;
  413. const CXXNewExpr *NE;
  414. SVal Target;
  415. bool WasInlined;
  416. ExprEngine &Eng;
  417. CheckNewAllocatorContext(const CheckersTy &Checkers, const CXXNewExpr *NE,
  418. SVal Target, bool WasInlined, ExprEngine &Eng)
  419. : Checkers(Checkers), NE(NE), Target(Target), WasInlined(WasInlined),
  420. Eng(Eng) {}
  421. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  422. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  423. void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
  424. NodeBuilder &Bldr, ExplodedNode *Pred) {
  425. ProgramPoint L = PostAllocatorCall(NE, Pred->getLocationContext());
  426. CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
  427. checkFn(NE, Target, C);
  428. }
  429. };
  430. } // namespace
  431. void CheckerManager::runCheckersForNewAllocator(
  432. const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred,
  433. ExprEngine &Eng, bool WasInlined) {
  434. ExplodedNodeSet Src;
  435. Src.insert(Pred);
  436. CheckNewAllocatorContext C(NewAllocatorCheckers, NE, Target, WasInlined, Eng);
  437. expandGraphWithCheckers(C, Dst, Src);
  438. }
  439. /// \brief Run checkers for live symbols.
  440. void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
  441. SymbolReaper &SymReaper) {
  442. for (const auto LiveSymbolsChecker : LiveSymbolsCheckers)
  443. LiveSymbolsChecker(state, SymReaper);
  444. }
  445. namespace {
  446. struct CheckDeadSymbolsContext {
  447. using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
  448. const CheckersTy &Checkers;
  449. SymbolReaper &SR;
  450. const Stmt *S;
  451. ExprEngine &Eng;
  452. ProgramPoint::Kind ProgarmPointKind;
  453. CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
  454. const Stmt *s, ExprEngine &eng,
  455. ProgramPoint::Kind K)
  456. : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
  457. CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
  458. CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
  459. void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
  460. NodeBuilder &Bldr, ExplodedNode *Pred) {
  461. const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
  462. Pred->getLocationContext(), checkFn.Checker);
  463. CheckerContext C(Bldr, Eng, Pred, L);
  464. // Note, do not pass the statement to the checkers without letting them
  465. // differentiate if we ran remove dead bindings before or after the
  466. // statement.
  467. checkFn(SR, C);
  468. }
  469. };
  470. } // namespace
  471. /// \brief Run checkers for dead symbols.
  472. void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
  473. const ExplodedNodeSet &Src,
  474. SymbolReaper &SymReaper,
  475. const Stmt *S,
  476. ExprEngine &Eng,
  477. ProgramPoint::Kind K) {
  478. CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
  479. expandGraphWithCheckers(C, Dst, Src);
  480. }
  481. /// \brief Run checkers for region changes.
  482. ProgramStateRef
  483. CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
  484. const InvalidatedSymbols *invalidated,
  485. ArrayRef<const MemRegion *> ExplicitRegions,
  486. ArrayRef<const MemRegion *> Regions,
  487. const LocationContext *LCtx,
  488. const CallEvent *Call) {
  489. for (const auto RegionChangesChecker : RegionChangesCheckers) {
  490. // If any checker declares the state infeasible (or if it starts that way),
  491. // bail out.
  492. if (!state)
  493. return nullptr;
  494. state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
  495. LCtx, Call);
  496. }
  497. return state;
  498. }
  499. /// \brief Run checkers to process symbol escape event.
  500. ProgramStateRef
  501. CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
  502. const InvalidatedSymbols &Escaped,
  503. const CallEvent *Call,
  504. PointerEscapeKind Kind,
  505. RegionAndSymbolInvalidationTraits *ETraits) {
  506. assert((Call != nullptr ||
  507. (Kind != PSK_DirectEscapeOnCall &&
  508. Kind != PSK_IndirectEscapeOnCall)) &&
  509. "Call must not be NULL when escaping on call");
  510. for (const auto PointerEscapeChecker : PointerEscapeCheckers) {
  511. // If any checker declares the state infeasible (or if it starts that
  512. // way), bail out.
  513. if (!State)
  514. return nullptr;
  515. State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
  516. }
  517. return State;
  518. }
  519. /// \brief Run checkers for handling assumptions on symbolic values.
  520. ProgramStateRef
  521. CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
  522. SVal Cond, bool Assumption) {
  523. for (const auto EvalAssumeChecker : EvalAssumeCheckers) {
  524. // If any checker declares the state infeasible (or if it starts that way),
  525. // bail out.
  526. if (!state)
  527. return nullptr;
  528. state = EvalAssumeChecker(state, Cond, Assumption);
  529. }
  530. return state;
  531. }
  532. /// \brief Run checkers for evaluating a call.
  533. /// Only one checker will evaluate the call.
  534. void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
  535. const ExplodedNodeSet &Src,
  536. const CallEvent &Call,
  537. ExprEngine &Eng) {
  538. const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
  539. for (const auto Pred : Src) {
  540. bool anyEvaluated = false;
  541. ExplodedNodeSet checkDst;
  542. NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
  543. // Check if any of the EvalCall callbacks can evaluate the call.
  544. for (const auto EvalCallChecker : EvalCallCheckers) {
  545. ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
  546. const ProgramPoint &L =
  547. ProgramPoint::getProgramPoint(CE, K, Pred->getLocationContext(),
  548. EvalCallChecker.Checker);
  549. bool evaluated = false;
  550. { // CheckerContext generates transitions(populates checkDest) on
  551. // destruction, so introduce the scope to make sure it gets properly
  552. // populated.
  553. CheckerContext C(B, Eng, Pred, L);
  554. evaluated = EvalCallChecker(CE, C);
  555. }
  556. assert(!(evaluated && anyEvaluated)
  557. && "There are more than one checkers evaluating the call");
  558. if (evaluated) {
  559. anyEvaluated = true;
  560. Dst.insert(checkDst);
  561. #ifdef NDEBUG
  562. break; // on release don't check that no other checker also evals.
  563. #endif
  564. }
  565. }
  566. // If none of the checkers evaluated the call, ask ExprEngine to handle it.
  567. if (!anyEvaluated) {
  568. NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
  569. Eng.defaultEvalCall(B, Pred, Call);
  570. }
  571. }
  572. }
  573. /// \brief Run checkers for the entire Translation Unit.
  574. void CheckerManager::runCheckersOnEndOfTranslationUnit(
  575. const TranslationUnitDecl *TU,
  576. AnalysisManager &mgr,
  577. BugReporter &BR) {
  578. for (const auto EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
  579. EndOfTranslationUnitChecker(TU, mgr, BR);
  580. }
  581. void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
  582. ProgramStateRef State,
  583. const char *NL, const char *Sep) {
  584. for (const auto &CheckerTag : CheckerTags)
  585. CheckerTag.second->printState(Out, State, NL, Sep);
  586. }
  587. //===----------------------------------------------------------------------===//
  588. // Internal registration functions for AST traversing.
  589. //===----------------------------------------------------------------------===//
  590. void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
  591. HandlesDeclFunc isForDeclFn) {
  592. DeclCheckerInfo info = { checkfn, isForDeclFn };
  593. DeclCheckers.push_back(info);
  594. }
  595. void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
  596. BodyCheckers.push_back(checkfn);
  597. }
  598. //===----------------------------------------------------------------------===//
  599. // Internal registration functions for path-sensitive checking.
  600. //===----------------------------------------------------------------------===//
  601. void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
  602. HandlesStmtFunc isForStmtFn) {
  603. StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
  604. StmtCheckers.push_back(info);
  605. }
  606. void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
  607. HandlesStmtFunc isForStmtFn) {
  608. StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
  609. StmtCheckers.push_back(info);
  610. }
  611. void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
  612. PreObjCMessageCheckers.push_back(checkfn);
  613. }
  614. void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
  615. ObjCMessageNilCheckers.push_back(checkfn);
  616. }
  617. void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
  618. PostObjCMessageCheckers.push_back(checkfn);
  619. }
  620. void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
  621. PreCallCheckers.push_back(checkfn);
  622. }
  623. void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
  624. PostCallCheckers.push_back(checkfn);
  625. }
  626. void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
  627. LocationCheckers.push_back(checkfn);
  628. }
  629. void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
  630. BindCheckers.push_back(checkfn);
  631. }
  632. void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
  633. EndAnalysisCheckers.push_back(checkfn);
  634. }
  635. void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
  636. BeginFunctionCheckers.push_back(checkfn);
  637. }
  638. void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
  639. EndFunctionCheckers.push_back(checkfn);
  640. }
  641. void CheckerManager::_registerForBranchCondition(
  642. CheckBranchConditionFunc checkfn) {
  643. BranchConditionCheckers.push_back(checkfn);
  644. }
  645. void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
  646. NewAllocatorCheckers.push_back(checkfn);
  647. }
  648. void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
  649. LiveSymbolsCheckers.push_back(checkfn);
  650. }
  651. void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
  652. DeadSymbolsCheckers.push_back(checkfn);
  653. }
  654. void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
  655. RegionChangesCheckers.push_back(checkfn);
  656. }
  657. void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
  658. PointerEscapeCheckers.push_back(checkfn);
  659. }
  660. void CheckerManager::_registerForConstPointerEscape(
  661. CheckPointerEscapeFunc checkfn) {
  662. PointerEscapeCheckers.push_back(checkfn);
  663. }
  664. void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
  665. EvalAssumeCheckers.push_back(checkfn);
  666. }
  667. void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
  668. EvalCallCheckers.push_back(checkfn);
  669. }
  670. void CheckerManager::_registerForEndOfTranslationUnit(
  671. CheckEndOfTranslationUnit checkfn) {
  672. EndOfTranslationUnitCheckers.push_back(checkfn);
  673. }
  674. //===----------------------------------------------------------------------===//
  675. // Implementation details.
  676. //===----------------------------------------------------------------------===//
  677. const CheckerManager::CachedStmtCheckers &
  678. CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
  679. assert(S);
  680. unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
  681. CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
  682. if (CCI != CachedStmtCheckersMap.end())
  683. return CCI->second;
  684. // Find the checkers that should run for this Stmt and cache them.
  685. CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
  686. for (const auto &Info : StmtCheckers)
  687. if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
  688. Checkers.push_back(Info.CheckFn);
  689. return Checkers;
  690. }
  691. CheckerManager::~CheckerManager() {
  692. for (const auto CheckerDtor : CheckerDtors)
  693. CheckerDtor();
  694. }