1 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines Checker, used to create and register checkers.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
16 
17 #include "clang/Analysis/ProgramPoint.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>
_checkDecl(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)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 
_handlesDecl(const Decl * D)36   static bool _handlesDecl(const Decl *D) {
37     return isa<DECL>(D);
38   }
39 public:
40   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkBody(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkEndOfTranslationUnit(void * checker,const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)84   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86   }
87 
_handlesStmt(const Stmt * S)88   static bool _handlesStmt(const Stmt *S) {
89     return isa<STMT>(S);
90   }
91 public:
92   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)103   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105   }
106 
_handlesStmt(const Stmt * S)107   static bool _handlesStmt(const Stmt *S) {
108     return isa<STMT>(S);
109   }
110 public:
111   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkLocation(void * checker,const SVal & location,bool isLoad,const Stmt * S,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkBind(void * checker,const SVal & location,const SVal & val,const Stmt * S,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkEndAnalysis(void * checker,ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)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>
_register(CHECKER * checker,CheckerManager & mgr)235   static void _register(CHECKER *checker, CheckerManager &mgr) {
236     mgr._registerForEndAnalysis(
237      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
238   }
239 };
240 
241 class EndFunction {
242   template <typename CHECKER>
_checkEndFunction(void * checker,CheckerContext & C)243   static void _checkEndFunction(void *checker,
244                                 CheckerContext &C) {
245     ((const CHECKER *)checker)->checkEndFunction(C);
246   }
247 
248 public:
249   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)250   static void _register(CHECKER *checker, CheckerManager &mgr) {
251     mgr._registerForEndFunction(
252      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
253   }
254 };
255 
256 class BranchCondition {
257   template <typename CHECKER>
_checkBranchCondition(void * checker,const Stmt * Condition,CheckerContext & C)258   static void _checkBranchCondition(void *checker, const Stmt *Condition,
259                                     CheckerContext & C) {
260     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
261   }
262 
263 public:
264   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)265   static void _register(CHECKER *checker, CheckerManager &mgr) {
266     mgr._registerForBranchCondition(
267       CheckerManager::CheckBranchConditionFunc(checker,
268                                                _checkBranchCondition<CHECKER>));
269   }
270 };
271 
272 class LiveSymbols {
273   template <typename CHECKER>
_checkLiveSymbols(void * checker,ProgramStateRef state,SymbolReaper & SR)274   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
275                                 SymbolReaper &SR) {
276     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
277   }
278 
279 public:
280   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)281   static void _register(CHECKER *checker, CheckerManager &mgr) {
282     mgr._registerForLiveSymbols(
283      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
284   }
285 };
286 
287 class DeadSymbols {
288   template <typename CHECKER>
_checkDeadSymbols(void * checker,SymbolReaper & SR,CheckerContext & C)289   static void _checkDeadSymbols(void *checker,
290                                 SymbolReaper &SR, CheckerContext &C) {
291     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
292   }
293 
294 public:
295   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)296   static void _register(CHECKER *checker, CheckerManager &mgr) {
297     mgr._registerForDeadSymbols(
298      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
299   }
300 };
301 
302 class RegionChanges {
303   template <typename CHECKER>
304   static ProgramStateRef
_checkRegionChanges(void * checker,ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const CallEvent * Call)305   _checkRegionChanges(void *checker,
306                       ProgramStateRef state,
307                       const InvalidatedSymbols *invalidated,
308                       ArrayRef<const MemRegion *> Explicits,
309                       ArrayRef<const MemRegion *> Regions,
310                       const CallEvent *Call) {
311     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
312                                                       Explicits, Regions, Call);
313   }
314   template <typename CHECKER>
_wantsRegionChangeUpdate(void * checker,ProgramStateRef state)315   static bool _wantsRegionChangeUpdate(void *checker,
316                                        ProgramStateRef state) {
317     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
318   }
319 
320 public:
321   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)322   static void _register(CHECKER *checker, CheckerManager &mgr) {
323     mgr._registerForRegionChanges(
324           CheckerManager::CheckRegionChangesFunc(checker,
325                                                  _checkRegionChanges<CHECKER>),
326           CheckerManager::WantsRegionChangeUpdateFunc(checker,
327                                             _wantsRegionChangeUpdate<CHECKER>));
328   }
329 };
330 
331 class PointerEscape {
332   template <typename CHECKER>
333   static ProgramStateRef
_checkPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)334   _checkPointerEscape(void *Checker,
335                      ProgramStateRef State,
336                      const InvalidatedSymbols &Escaped,
337                      const CallEvent *Call,
338                      PointerEscapeKind Kind,
339                      RegionAndSymbolInvalidationTraits *ETraits) {
340 
341     if (!ETraits)
342       return ((const CHECKER *)Checker)->checkPointerEscape(State,
343                                                             Escaped,
344                                                             Call,
345                                                             Kind);
346 
347     InvalidatedSymbols RegularEscape;
348     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
349                                             E = Escaped.end(); I != E; ++I)
350       if (!ETraits->hasTrait(*I,
351               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
352           !ETraits->hasTrait(*I,
353               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
354         RegularEscape.insert(*I);
355 
356     if (RegularEscape.empty())
357       return State;
358 
359     return ((const CHECKER *)Checker)->checkPointerEscape(State,
360                                                           RegularEscape,
361                                                           Call,
362                                                           Kind);
363   }
364 
365 public:
366   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)367   static void _register(CHECKER *checker, CheckerManager &mgr) {
368     mgr._registerForPointerEscape(
369           CheckerManager::CheckPointerEscapeFunc(checker,
370                                                 _checkPointerEscape<CHECKER>));
371   }
372 };
373 
374 class ConstPointerEscape {
375   template <typename CHECKER>
376   static ProgramStateRef
_checkConstPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)377   _checkConstPointerEscape(void *Checker,
378                       ProgramStateRef State,
379                       const InvalidatedSymbols &Escaped,
380                       const CallEvent *Call,
381                       PointerEscapeKind Kind,
382                       RegionAndSymbolInvalidationTraits *ETraits) {
383 
384     if (!ETraits)
385       return State;
386 
387     InvalidatedSymbols ConstEscape;
388     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
389                                             E = Escaped.end(); I != E; ++I)
390       if (ETraits->hasTrait(*I,
391               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
392           !ETraits->hasTrait(*I,
393               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
394         ConstEscape.insert(*I);
395 
396     if (ConstEscape.empty())
397       return State;
398 
399     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
400                                                                ConstEscape,
401                                                                Call,
402                                                                Kind);
403   }
404 
405 public:
406   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)407   static void _register(CHECKER *checker, CheckerManager &mgr) {
408     mgr._registerForPointerEscape(
409       CheckerManager::CheckPointerEscapeFunc(checker,
410                                             _checkConstPointerEscape<CHECKER>));
411   }
412 };
413 
414 
415 template <typename EVENT>
416 class Event {
417   template <typename CHECKER>
_checkEvent(void * checker,const void * event)418   static void _checkEvent(void *checker, const void *event) {
419     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
420   }
421 public:
422   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)423   static void _register(CHECKER *checker, CheckerManager &mgr) {
424     mgr._registerListenerForEvent<EVENT>(
425                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
426   }
427 };
428 
429 } // end check namespace
430 
431 namespace eval {
432 
433 class Assume {
434   template <typename CHECKER>
_evalAssume(void * checker,ProgramStateRef state,const SVal & cond,bool assumption)435   static ProgramStateRef _evalAssume(void *checker,
436                                          ProgramStateRef state,
437                                          const SVal &cond,
438                                          bool assumption) {
439     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
440   }
441 
442 public:
443   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)444   static void _register(CHECKER *checker, CheckerManager &mgr) {
445     mgr._registerForEvalAssume(
446                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
447   }
448 };
449 
450 class Call {
451   template <typename CHECKER>
_evalCall(void * checker,const CallExpr * CE,CheckerContext & C)452   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
453     return ((const CHECKER *)checker)->evalCall(CE, C);
454   }
455 
456 public:
457   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)458   static void _register(CHECKER *checker, CheckerManager &mgr) {
459     mgr._registerForEvalCall(
460                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
461   }
462 };
463 
464 } // end eval namespace
465 
466 class CheckerBase : public ProgramPointTag {
467   CheckName Name;
468   friend class ::clang::ento::CheckerManager;
469 
470 public:
471   StringRef getTagDescription() const override;
472   CheckName getCheckName() const;
473 
474   /// See CheckerManager::runCheckersForPrintState.
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep)475   virtual void printState(raw_ostream &Out, ProgramStateRef State,
476                           const char *NL, const char *Sep) const { }
477 };
478 
479 /// Dump checker name to stream.
480 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
481 
482 /// Tag that can use a checker name as a message provider
483 /// (see SimpleProgramPointTag).
484 class CheckerProgramPointTag : public SimpleProgramPointTag {
485 public:
486   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
487   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
488 };
489 
490 template <typename CHECK1, typename... CHECKs>
491 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
492 public:
493   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)494   static void _register(CHECKER *checker, CheckerManager &mgr) {
495     CHECK1::_register(checker, mgr);
496     Checker<CHECKs...>::_register(checker, mgr);
497   }
498 };
499 
500 template <typename CHECK1>
501 class Checker<CHECK1> : public CHECK1, public CheckerBase {
502 public:
503   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)504   static void _register(CHECKER *checker, CheckerManager &mgr) {
505     CHECK1::_register(checker, mgr);
506   }
507 };
508 
509 template <typename EVENT>
510 class EventDispatcher {
511   CheckerManager *Mgr;
512 public:
EventDispatcher()513   EventDispatcher() : Mgr(nullptr) { }
514 
515   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)516   static void _register(CHECKER *checker, CheckerManager &mgr) {
517     mgr._registerDispatcherForEvent<EVENT>();
518     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
519   }
520 
dispatchEvent(const EVENT & event)521   void dispatchEvent(const EVENT &event) const {
522     Mgr->_dispatchEvent(event);
523   }
524 };
525 
526 /// \brief We dereferenced a location that may be null.
527 struct ImplicitNullDerefEvent {
528   SVal Location;
529   bool IsLoad;
530   ExplodedNode *SinkNode;
531   BugReporter *BR;
532   // When true, the dereference is in the source code directly. When false, the
533   // dereference might happen later (for example pointer passed to a parameter
534   // that is marked with nonnull attribute.)
535   bool IsDirectDereference;
536 };
537 
538 /// \brief A helper class which wraps a boolean value set to false by default.
539 ///
540 /// This class should behave exactly like 'bool' except that it doesn't need to
541 /// be explicitly initialized.
542 struct DefaultBool {
543   bool val;
DefaultBoolDefaultBool544   DefaultBool() : val(false) {}
545   /*implicit*/ operator bool&() { return val; }
546   /*implicit*/ operator const bool&() const { return val; }
547   DefaultBool &operator=(bool b) { val = b; return *this; }
548 };
549 
550 } // end ento namespace
551 
552 } // end clang namespace
553 
554 #endif
555