1 //== Checker.h - Registration mechanism for checkers -------------*- 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 //  This file defines Checker, used to create and register checkers.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
15 
16 #include "clang/Analysis/ProgramPoint.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
20 #include "llvm/Support/Casting.h"
21 
22 namespace clang {
23 namespace ento {
24   class BugReporter;
25 
26 namespace check {
27 
28 template <typename DECL>
29 class ASTDecl {
30   template <typename CHECKER>
31   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
32                          BugReporter &BR) {
33     ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
34   }
35 
36   static bool _handlesDecl(const Decl *D) {
37     return isa<DECL>(D);
38   }
39 public:
40   template <typename CHECKER>
41   static void _register(CHECKER *checker, CheckerManager &mgr) {
42     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
43                                                        _checkDecl<CHECKER>),
44                          _handlesDecl);
45   }
46 };
47 
48 class ASTCodeBody {
49   template <typename CHECKER>
50   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
51                          BugReporter &BR) {
52     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
53   }
54 
55 public:
56   template <typename CHECKER>
57   static void _register(CHECKER *checker, CheckerManager &mgr) {
58     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59                                                        _checkBody<CHECKER>));
60   }
61 };
62 
63 class EndOfTranslationUnit {
64   template <typename CHECKER>
65   static void _checkEndOfTranslationUnit(void *checker,
66                                          const TranslationUnitDecl *TU,
67                                          AnalysisManager& mgr,
68                                          BugReporter &BR) {
69     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
70   }
71 
72 public:
73   template <typename CHECKER>
74   static void _register(CHECKER *checker, CheckerManager &mgr){
75     mgr._registerForEndOfTranslationUnit(
76                               CheckerManager::CheckEndOfTranslationUnit(checker,
77                                           _checkEndOfTranslationUnit<CHECKER>));
78   }
79 };
80 
81 template <typename STMT>
82 class PreStmt {
83   template <typename CHECKER>
84   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86   }
87 
88   static bool _handlesStmt(const Stmt *S) {
89     return isa<STMT>(S);
90   }
91 public:
92   template <typename CHECKER>
93   static void _register(CHECKER *checker, CheckerManager &mgr) {
94     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
95                                                           _checkStmt<CHECKER>),
96                             _handlesStmt);
97   }
98 };
99 
100 template <typename STMT>
101 class PostStmt {
102   template <typename CHECKER>
103   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105   }
106 
107   static bool _handlesStmt(const Stmt *S) {
108     return isa<STMT>(S);
109   }
110 public:
111   template <typename CHECKER>
112   static void _register(CHECKER *checker, CheckerManager &mgr) {
113     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114                                                            _checkStmt<CHECKER>),
115                              _handlesStmt);
116   }
117 };
118 
119 class PreObjCMessage {
120   template <typename CHECKER>
121   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
122                                 CheckerContext &C) {
123     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
124   }
125 
126 public:
127   template <typename CHECKER>
128   static void _register(CHECKER *checker, CheckerManager &mgr) {
129     mgr._registerForPreObjCMessage(
130      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131   }
132 };
133 
134 class ObjCMessageNil {
135   template <typename CHECKER>
136   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
137                                 CheckerContext &C) {
138     ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
139   }
140 
141 public:
142   template <typename CHECKER>
143   static void _register(CHECKER *checker, CheckerManager &mgr) {
144     mgr._registerForObjCMessageNil(
145      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146   }
147 };
148 
149 class PostObjCMessage {
150   template <typename CHECKER>
151   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
152                                 CheckerContext &C) {
153     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
154   }
155 
156 public:
157   template <typename CHECKER>
158   static void _register(CHECKER *checker, CheckerManager &mgr) {
159     mgr._registerForPostObjCMessage(
160      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
161   }
162 };
163 
164 class PreCall {
165   template <typename CHECKER>
166   static void _checkCall(void *checker, const CallEvent &msg,
167                          CheckerContext &C) {
168     ((const CHECKER *)checker)->checkPreCall(msg, C);
169   }
170 
171 public:
172   template <typename CHECKER>
173   static void _register(CHECKER *checker, CheckerManager &mgr) {
174     mgr._registerForPreCall(
175      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176   }
177 };
178 
179 class PostCall {
180   template <typename CHECKER>
181   static void _checkCall(void *checker, const CallEvent &msg,
182                          CheckerContext &C) {
183     ((const CHECKER *)checker)->checkPostCall(msg, C);
184   }
185 
186 public:
187   template <typename CHECKER>
188   static void _register(CHECKER *checker, CheckerManager &mgr) {
189     mgr._registerForPostCall(
190      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
191   }
192 };
193 
194 class Location {
195   template <typename CHECKER>
196   static void _checkLocation(void *checker,
197                              const SVal &location, bool isLoad, const Stmt *S,
198                              CheckerContext &C) {
199     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
200   }
201 
202 public:
203   template <typename CHECKER>
204   static void _register(CHECKER *checker, CheckerManager &mgr) {
205     mgr._registerForLocation(
206            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
207   }
208 };
209 
210 class Bind {
211   template <typename CHECKER>
212   static void _checkBind(void *checker,
213                          const SVal &location, const SVal &val, const Stmt *S,
214                          CheckerContext &C) {
215     ((const CHECKER *)checker)->checkBind(location, val, S, C);
216   }
217 
218 public:
219   template <typename CHECKER>
220   static void _register(CHECKER *checker, CheckerManager &mgr) {
221     mgr._registerForBind(
222            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
223   }
224 };
225 
226 class EndAnalysis {
227   template <typename CHECKER>
228   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
229                                 BugReporter &BR, ExprEngine &Eng) {
230     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
231   }
232 
233 public:
234   template <typename CHECKER>
235   static void _register(CHECKER *checker, CheckerManager &mgr) {
236     mgr._registerForEndAnalysis(
237      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
238   }
239 };
240 
241 class BeginFunction {
242   template <typename CHECKER>
243   static void _checkBeginFunction(void *checker, CheckerContext &C) {
244     ((const CHECKER *)checker)->checkBeginFunction(C);
245   }
246 
247 public:
248   template <typename CHECKER>
249   static void _register(CHECKER *checker, CheckerManager &mgr) {
250     mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
251         checker, _checkBeginFunction<CHECKER>));
252   }
253 };
254 
255 class EndFunction {
256   template <typename CHECKER>
257   static void _checkEndFunction(void *checker, const ReturnStmt *RS,
258                                 CheckerContext &C) {
259     ((const CHECKER *)checker)->checkEndFunction(RS, C);
260   }
261 
262 public:
263   template <typename CHECKER>
264   static void _register(CHECKER *checker, CheckerManager &mgr) {
265     mgr._registerForEndFunction(
266      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
267   }
268 };
269 
270 class BranchCondition {
271   template <typename CHECKER>
272   static void _checkBranchCondition(void *checker, const Stmt *Condition,
273                                     CheckerContext & C) {
274     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
275   }
276 
277 public:
278   template <typename CHECKER>
279   static void _register(CHECKER *checker, CheckerManager &mgr) {
280     mgr._registerForBranchCondition(
281       CheckerManager::CheckBranchConditionFunc(checker,
282                                                _checkBranchCondition<CHECKER>));
283   }
284 };
285 
286 class NewAllocator {
287   template <typename CHECKER>
288   static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call,
289                                  CheckerContext &C) {
290     ((const CHECKER *)checker)->checkNewAllocator(Call, C);
291   }
292 
293 public:
294   template <typename CHECKER>
295   static void _register(CHECKER *checker, CheckerManager &mgr) {
296     mgr._registerForNewAllocator(
297         CheckerManager::CheckNewAllocatorFunc(checker,
298                                               _checkNewAllocator<CHECKER>));
299   }
300 };
301 
302 class LiveSymbols {
303   template <typename CHECKER>
304   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
305                                 SymbolReaper &SR) {
306     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
307   }
308 
309 public:
310   template <typename CHECKER>
311   static void _register(CHECKER *checker, CheckerManager &mgr) {
312     mgr._registerForLiveSymbols(
313      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
314   }
315 };
316 
317 class DeadSymbols {
318   template <typename CHECKER>
319   static void _checkDeadSymbols(void *checker,
320                                 SymbolReaper &SR, CheckerContext &C) {
321     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
322   }
323 
324 public:
325   template <typename CHECKER>
326   static void _register(CHECKER *checker, CheckerManager &mgr) {
327     mgr._registerForDeadSymbols(
328      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
329   }
330 };
331 
332 class RegionChanges {
333   template <typename CHECKER>
334   static ProgramStateRef
335   _checkRegionChanges(void *checker,
336                       ProgramStateRef state,
337                       const InvalidatedSymbols *invalidated,
338                       ArrayRef<const MemRegion *> Explicits,
339                       ArrayRef<const MemRegion *> Regions,
340                       const LocationContext *LCtx,
341                       const CallEvent *Call) {
342     return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
343                                                            Explicits, Regions,
344                                                            LCtx, Call);
345   }
346 
347 public:
348   template <typename CHECKER>
349   static void _register(CHECKER *checker, CheckerManager &mgr) {
350     mgr._registerForRegionChanges(
351           CheckerManager::CheckRegionChangesFunc(checker,
352                                                  _checkRegionChanges<CHECKER>));
353   }
354 };
355 
356 class PointerEscape {
357   template <typename CHECKER>
358   static ProgramStateRef
359   _checkPointerEscape(void *Checker,
360                      ProgramStateRef State,
361                      const InvalidatedSymbols &Escaped,
362                      const CallEvent *Call,
363                      PointerEscapeKind Kind,
364                      RegionAndSymbolInvalidationTraits *ETraits) {
365 
366     if (!ETraits)
367       return ((const CHECKER *)Checker)->checkPointerEscape(State,
368                                                             Escaped,
369                                                             Call,
370                                                             Kind);
371 
372     InvalidatedSymbols RegularEscape;
373     for (SymbolRef Sym : Escaped)
374       if (!ETraits->hasTrait(
375               Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
376           !ETraits->hasTrait(
377               Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
378         RegularEscape.insert(Sym);
379 
380     if (RegularEscape.empty())
381       return State;
382 
383     return ((const CHECKER *)Checker)->checkPointerEscape(State,
384                                                           RegularEscape,
385                                                           Call,
386                                                           Kind);
387   }
388 
389 public:
390   template <typename CHECKER>
391   static void _register(CHECKER *checker, CheckerManager &mgr) {
392     mgr._registerForPointerEscape(
393           CheckerManager::CheckPointerEscapeFunc(checker,
394                                                 _checkPointerEscape<CHECKER>));
395   }
396 };
397 
398 class ConstPointerEscape {
399   template <typename CHECKER>
400   static ProgramStateRef
401   _checkConstPointerEscape(void *Checker,
402                       ProgramStateRef State,
403                       const InvalidatedSymbols &Escaped,
404                       const CallEvent *Call,
405                       PointerEscapeKind Kind,
406                       RegionAndSymbolInvalidationTraits *ETraits) {
407 
408     if (!ETraits)
409       return State;
410 
411     InvalidatedSymbols ConstEscape;
412     for (SymbolRef Sym : Escaped) {
413       if (ETraits->hasTrait(
414               Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
415           !ETraits->hasTrait(
416               Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
417         ConstEscape.insert(Sym);
418     }
419 
420     if (ConstEscape.empty())
421       return State;
422 
423     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
424                                                                ConstEscape,
425                                                                Call,
426                                                                Kind);
427   }
428 
429 public:
430   template <typename CHECKER>
431   static void _register(CHECKER *checker, CheckerManager &mgr) {
432     mgr._registerForPointerEscape(
433       CheckerManager::CheckPointerEscapeFunc(checker,
434                                             _checkConstPointerEscape<CHECKER>));
435   }
436 };
437 
438 
439 template <typename EVENT>
440 class Event {
441   template <typename CHECKER>
442   static void _checkEvent(void *checker, const void *event) {
443     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
444   }
445 public:
446   template <typename CHECKER>
447   static void _register(CHECKER *checker, CheckerManager &mgr) {
448     mgr._registerListenerForEvent<EVENT>(
449                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
450   }
451 };
452 
453 } // end check namespace
454 
455 namespace eval {
456 
457 class Assume {
458   template <typename CHECKER>
459   static ProgramStateRef _evalAssume(void *checker,
460                                          ProgramStateRef state,
461                                          const SVal &cond,
462                                          bool assumption) {
463     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
464   }
465 
466 public:
467   template <typename CHECKER>
468   static void _register(CHECKER *checker, CheckerManager &mgr) {
469     mgr._registerForEvalAssume(
470                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
471   }
472 };
473 
474 class Call {
475   template <typename CHECKER>
476   static bool _evalCall(void *checker, const CallEvent &Call,
477                         CheckerContext &C) {
478     return ((const CHECKER *)checker)->evalCall(Call, C);
479   }
480 
481 public:
482   template <typename CHECKER>
483   static void _register(CHECKER *checker, CheckerManager &mgr) {
484     mgr._registerForEvalCall(
485                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
486   }
487 };
488 
489 } // end eval namespace
490 
491 class CheckerBase : public ProgramPointTag {
492   CheckerNameRef Name;
493   friend class ::clang::ento::CheckerManager;
494 
495 public:
496   StringRef getTagDescription() const override;
497   CheckerNameRef getCheckerName() const;
498 
499   /// See CheckerManager::runCheckersForPrintState.
500   virtual void printState(raw_ostream &Out, ProgramStateRef State,
501                           const char *NL, const char *Sep) const { }
502 };
503 
504 /// Dump checker name to stream.
505 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
506 
507 /// Tag that can use a checker name as a message provider
508 /// (see SimpleProgramPointTag).
509 class CheckerProgramPointTag : public SimpleProgramPointTag {
510 public:
511   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
512   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
513 };
514 
515 template <typename CHECK1, typename... CHECKs>
516 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
517 public:
518   template <typename CHECKER>
519   static void _register(CHECKER *checker, CheckerManager &mgr) {
520     CHECK1::_register(checker, mgr);
521     Checker<CHECKs...>::_register(checker, mgr);
522   }
523 };
524 
525 template <typename CHECK1>
526 class Checker<CHECK1> : public CHECK1, public CheckerBase {
527 public:
528   template <typename CHECKER>
529   static void _register(CHECKER *checker, CheckerManager &mgr) {
530     CHECK1::_register(checker, mgr);
531   }
532 };
533 
534 template <typename EVENT>
535 class EventDispatcher {
536   CheckerManager *Mgr;
537 public:
538   EventDispatcher() : Mgr(nullptr) { }
539 
540   template <typename CHECKER>
541   static void _register(CHECKER *checker, CheckerManager &mgr) {
542     mgr._registerDispatcherForEvent<EVENT>();
543     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
544   }
545 
546   void dispatchEvent(const EVENT &event) const {
547     Mgr->_dispatchEvent(event);
548   }
549 };
550 
551 /// We dereferenced a location that may be null.
552 struct ImplicitNullDerefEvent {
553   SVal Location;
554   bool IsLoad;
555   ExplodedNode *SinkNode;
556   BugReporter *BR;
557   // When true, the dereference is in the source code directly. When false, the
558   // dereference might happen later (for example pointer passed to a parameter
559   // that is marked with nonnull attribute.)
560   bool IsDirectDereference;
561 
562   static int Tag;
563 };
564 
565 } // end ento namespace
566 
567 } // end clang namespace
568 
569 #endif
570