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> _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,SVal location,bool isLoad,const Stmt * S,CheckerContext & C)196 static void _checkLocation(void *checker, SVal location, bool isLoad, 197 const Stmt *S, CheckerContext &C) { 198 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 199 } 200 201 public: 202 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)203 static void _register(CHECKER *checker, CheckerManager &mgr) { 204 mgr._registerForLocation( 205 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 206 } 207 }; 208 209 class Bind { 210 template <typename CHECKER> _checkBind(void * checker,SVal location,SVal val,const Stmt * S,CheckerContext & C)211 static void _checkBind(void *checker, SVal location, SVal val, const Stmt *S, 212 CheckerContext &C) { 213 ((const CHECKER *)checker)->checkBind(location, val, S, C); 214 } 215 216 public: 217 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)218 static void _register(CHECKER *checker, CheckerManager &mgr) { 219 mgr._registerForBind( 220 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 221 } 222 }; 223 224 class EndAnalysis { 225 template <typename CHECKER> _checkEndAnalysis(void * checker,ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)226 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 227 BugReporter &BR, ExprEngine &Eng) { 228 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 229 } 230 231 public: 232 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)233 static void _register(CHECKER *checker, CheckerManager &mgr) { 234 mgr._registerForEndAnalysis( 235 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 236 } 237 }; 238 239 class BeginFunction { 240 template <typename CHECKER> _checkBeginFunction(void * checker,CheckerContext & C)241 static void _checkBeginFunction(void *checker, CheckerContext &C) { 242 ((const CHECKER *)checker)->checkBeginFunction(C); 243 } 244 245 public: 246 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)247 static void _register(CHECKER *checker, CheckerManager &mgr) { 248 mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( 249 checker, _checkBeginFunction<CHECKER>)); 250 } 251 }; 252 253 class EndFunction { 254 template <typename CHECKER> _checkEndFunction(void * checker,const ReturnStmt * RS,CheckerContext & C)255 static void _checkEndFunction(void *checker, const ReturnStmt *RS, 256 CheckerContext &C) { 257 ((const CHECKER *)checker)->checkEndFunction(RS, C); 258 } 259 260 public: 261 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)262 static void _register(CHECKER *checker, CheckerManager &mgr) { 263 mgr._registerForEndFunction( 264 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 265 } 266 }; 267 268 class BranchCondition { 269 template <typename CHECKER> _checkBranchCondition(void * checker,const Stmt * Condition,CheckerContext & C)270 static void _checkBranchCondition(void *checker, const Stmt *Condition, 271 CheckerContext & C) { 272 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 273 } 274 275 public: 276 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)277 static void _register(CHECKER *checker, CheckerManager &mgr) { 278 mgr._registerForBranchCondition( 279 CheckerManager::CheckBranchConditionFunc(checker, 280 _checkBranchCondition<CHECKER>)); 281 } 282 }; 283 284 class NewAllocator { 285 template <typename CHECKER> _checkNewAllocator(void * checker,const CXXAllocatorCall & Call,CheckerContext & C)286 static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call, 287 CheckerContext &C) { 288 ((const CHECKER *)checker)->checkNewAllocator(Call, C); 289 } 290 291 public: 292 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)293 static void _register(CHECKER *checker, CheckerManager &mgr) { 294 mgr._registerForNewAllocator( 295 CheckerManager::CheckNewAllocatorFunc(checker, 296 _checkNewAllocator<CHECKER>)); 297 } 298 }; 299 300 class LiveSymbols { 301 template <typename CHECKER> _checkLiveSymbols(void * checker,ProgramStateRef state,SymbolReaper & SR)302 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 303 SymbolReaper &SR) { 304 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 305 } 306 307 public: 308 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)309 static void _register(CHECKER *checker, CheckerManager &mgr) { 310 mgr._registerForLiveSymbols( 311 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 312 } 313 }; 314 315 class DeadSymbols { 316 template <typename CHECKER> _checkDeadSymbols(void * checker,SymbolReaper & SR,CheckerContext & C)317 static void _checkDeadSymbols(void *checker, 318 SymbolReaper &SR, CheckerContext &C) { 319 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 320 } 321 322 public: 323 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)324 static void _register(CHECKER *checker, CheckerManager &mgr) { 325 mgr._registerForDeadSymbols( 326 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 327 } 328 }; 329 330 class RegionChanges { 331 template <typename CHECKER> 332 static ProgramStateRef _checkRegionChanges(void * checker,ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const LocationContext * LCtx,const CallEvent * Call)333 _checkRegionChanges(void *checker, 334 ProgramStateRef state, 335 const InvalidatedSymbols *invalidated, 336 ArrayRef<const MemRegion *> Explicits, 337 ArrayRef<const MemRegion *> Regions, 338 const LocationContext *LCtx, 339 const CallEvent *Call) { 340 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, 341 Explicits, Regions, 342 LCtx, Call); 343 } 344 345 public: 346 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)347 static void _register(CHECKER *checker, CheckerManager &mgr) { 348 mgr._registerForRegionChanges( 349 CheckerManager::CheckRegionChangesFunc(checker, 350 _checkRegionChanges<CHECKER>)); 351 } 352 }; 353 354 class PointerEscape { 355 template <typename CHECKER> 356 static ProgramStateRef _checkPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)357 _checkPointerEscape(void *Checker, 358 ProgramStateRef State, 359 const InvalidatedSymbols &Escaped, 360 const CallEvent *Call, 361 PointerEscapeKind Kind, 362 RegionAndSymbolInvalidationTraits *ETraits) { 363 364 if (!ETraits) 365 return ((const CHECKER *)Checker)->checkPointerEscape(State, 366 Escaped, 367 Call, 368 Kind); 369 370 InvalidatedSymbols RegularEscape; 371 for (SymbolRef Sym : Escaped) 372 if (!ETraits->hasTrait( 373 Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 374 !ETraits->hasTrait( 375 Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 376 RegularEscape.insert(Sym); 377 378 if (RegularEscape.empty()) 379 return State; 380 381 return ((const CHECKER *)Checker)->checkPointerEscape(State, 382 RegularEscape, 383 Call, 384 Kind); 385 } 386 387 public: 388 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)389 static void _register(CHECKER *checker, CheckerManager &mgr) { 390 mgr._registerForPointerEscape( 391 CheckerManager::CheckPointerEscapeFunc(checker, 392 _checkPointerEscape<CHECKER>)); 393 } 394 }; 395 396 class ConstPointerEscape { 397 template <typename CHECKER> 398 static ProgramStateRef _checkConstPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)399 _checkConstPointerEscape(void *Checker, 400 ProgramStateRef State, 401 const InvalidatedSymbols &Escaped, 402 const CallEvent *Call, 403 PointerEscapeKind Kind, 404 RegionAndSymbolInvalidationTraits *ETraits) { 405 406 if (!ETraits) 407 return State; 408 409 InvalidatedSymbols ConstEscape; 410 for (SymbolRef Sym : Escaped) { 411 if (ETraits->hasTrait( 412 Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 413 !ETraits->hasTrait( 414 Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 415 ConstEscape.insert(Sym); 416 } 417 418 if (ConstEscape.empty()) 419 return State; 420 421 return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 422 ConstEscape, 423 Call, 424 Kind); 425 } 426 427 public: 428 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)429 static void _register(CHECKER *checker, CheckerManager &mgr) { 430 mgr._registerForPointerEscape( 431 CheckerManager::CheckPointerEscapeFunc(checker, 432 _checkConstPointerEscape<CHECKER>)); 433 } 434 }; 435 436 437 template <typename EVENT> 438 class Event { 439 template <typename CHECKER> _checkEvent(void * checker,const void * event)440 static void _checkEvent(void *checker, const void *event) { 441 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 442 } 443 public: 444 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)445 static void _register(CHECKER *checker, CheckerManager &mgr) { 446 mgr._registerListenerForEvent<EVENT>( 447 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 448 } 449 }; 450 451 } // end check namespace 452 453 namespace eval { 454 455 class Assume { 456 template <typename CHECKER> _evalAssume(void * checker,ProgramStateRef state,SVal cond,bool assumption)457 static ProgramStateRef _evalAssume(void *checker, ProgramStateRef state, 458 SVal cond, bool assumption) { 459 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 460 } 461 462 public: 463 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)464 static void _register(CHECKER *checker, CheckerManager &mgr) { 465 mgr._registerForEvalAssume( 466 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 467 } 468 }; 469 470 class Call { 471 template <typename CHECKER> _evalCall(void * checker,const CallEvent & Call,CheckerContext & C)472 static bool _evalCall(void *checker, const CallEvent &Call, 473 CheckerContext &C) { 474 return ((const CHECKER *)checker)->evalCall(Call, C); 475 } 476 477 public: 478 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)479 static void _register(CHECKER *checker, CheckerManager &mgr) { 480 mgr._registerForEvalCall( 481 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 482 } 483 }; 484 485 } // end eval namespace 486 487 class CheckerBase : public ProgramPointTag { 488 CheckerNameRef Name; 489 friend class ::clang::ento::CheckerManager; 490 491 public: 492 StringRef getTagDescription() const override; 493 CheckerNameRef getCheckerName() const; 494 495 /// See CheckerManager::runCheckersForPrintState. printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep)496 virtual void printState(raw_ostream &Out, ProgramStateRef State, 497 const char *NL, const char *Sep) const { } 498 }; 499 500 /// Dump checker name to stream. 501 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 502 503 /// Tag that can use a checker name as a message provider 504 /// (see SimpleProgramPointTag). 505 class CheckerProgramPointTag : public SimpleProgramPointTag { 506 public: 507 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 508 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 509 }; 510 511 template <typename CHECK1, typename... CHECKs> 512 class Checker : public CHECK1, public CHECKs..., public CheckerBase { 513 public: 514 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)515 static void _register(CHECKER *checker, CheckerManager &mgr) { 516 CHECK1::_register(checker, mgr); 517 Checker<CHECKs...>::_register(checker, mgr); 518 } 519 }; 520 521 template <typename CHECK1> 522 class Checker<CHECK1> : public CHECK1, public CheckerBase { 523 public: 524 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)525 static void _register(CHECKER *checker, CheckerManager &mgr) { 526 CHECK1::_register(checker, mgr); 527 } 528 }; 529 530 template <typename EVENT> 531 class EventDispatcher { 532 CheckerManager *Mgr = nullptr; 533 public: 534 EventDispatcher() = default; 535 536 template <typename CHECKER> _register(CHECKER * checker,CheckerManager & mgr)537 static void _register(CHECKER *checker, CheckerManager &mgr) { 538 mgr._registerDispatcherForEvent<EVENT>(); 539 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 540 } 541 dispatchEvent(const EVENT & event)542 void dispatchEvent(const EVENT &event) const { 543 Mgr->_dispatchEvent(event); 544 } 545 }; 546 547 /// We dereferenced a location that may be null. 548 struct ImplicitNullDerefEvent { 549 SVal Location; 550 bool IsLoad; 551 ExplodedNode *SinkNode; 552 BugReporter *BR; 553 // When true, the dereference is in the source code directly. When false, the 554 // dereference might happen later (for example pointer passed to a parameter 555 // that is marked with nonnull attribute.) 556 bool IsDirectDereference; 557 558 static int Tag; 559 }; 560 561 } // end ento namespace 562 563 } // end clang namespace 564 565 #endif 566