CheckerManager.cpp 33 KB

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