1 //===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- 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 a meta-engine for path-sensitive dataflow analysis that 10 // is built on CoreEngine, but provides the boilerplate to execute transfer 11 // functions and build the ExplodedGraph at the expression level. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H 16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H 17 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/Type.h" 20 #include "clang/Analysis/CFG.h" 21 #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 22 #include "clang/Analysis/ProgramPoint.h" 23 #include "clang/Basic/LLVM.h" 24 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 25 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 26 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" 27 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 28 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" 29 #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" 30 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 31 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 32 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 33 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 34 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 35 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 36 #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" 37 #include "llvm/ADT/ArrayRef.h" 38 #include <cassert> 39 #include <optional> 40 #include <utility> 41 42 namespace clang { 43 44 class AnalysisDeclContextManager; 45 class AnalyzerOptions; 46 class ASTContext; 47 class CFGBlock; 48 class CFGElement; 49 class ConstructionContext; 50 class CXXBindTemporaryExpr; 51 class CXXCatchStmt; 52 class CXXConstructExpr; 53 class CXXDeleteExpr; 54 class CXXNewExpr; 55 class CXXThisExpr; 56 class Decl; 57 class DeclStmt; 58 class GCCAsmStmt; 59 class LambdaExpr; 60 class LocationContext; 61 class MaterializeTemporaryExpr; 62 class MSAsmStmt; 63 class NamedDecl; 64 class ObjCAtSynchronizedStmt; 65 class ObjCForCollectionStmt; 66 class ObjCIvarRefExpr; 67 class ObjCMessageExpr; 68 class ReturnStmt; 69 class Stmt; 70 71 namespace cross_tu { 72 73 class CrossTranslationUnitContext; 74 75 } // namespace cross_tu 76 77 namespace ento { 78 79 class AnalysisManager; 80 class BasicValueFactory; 81 class CallEvent; 82 class CheckerManager; 83 class ConstraintManager; 84 class ExplodedNodeSet; 85 class ExplodedNode; 86 class IndirectGotoNodeBuilder; 87 class MemRegion; 88 struct NodeBuilderContext; 89 class NodeBuilderWithSinks; 90 class ProgramState; 91 class ProgramStateManager; 92 class RegionAndSymbolInvalidationTraits; 93 class SymbolManager; 94 class SwitchNodeBuilder; 95 96 /// Hints for figuring out of a call should be inlined during evalCall(). 97 struct EvalCallOptions { 98 /// This call is a constructor or a destructor for which we do not currently 99 /// compute the this-region correctly. 100 bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false; 101 102 /// This call is a constructor or a destructor for a single element within 103 /// an array, a part of array construction or destruction. 104 bool IsArrayCtorOrDtor = false; 105 106 /// This call is a constructor or a destructor of a temporary value. 107 bool IsTemporaryCtorOrDtor = false; 108 109 /// This call is a constructor for a temporary that is lifetime-extended 110 /// by binding it to a reference-type field within an aggregate, 111 /// for example 'A { const C &c; }; A a = { C() };' 112 bool IsTemporaryLifetimeExtendedViaAggregate = false; 113 114 /// This call is a pre-C++17 elidable constructor that we failed to elide 115 /// because we failed to compute the target region into which 116 /// this constructor would have been ultimately elided. Analysis that 117 /// we perform in this case is still correct but it behaves differently, 118 /// as if copy elision is disabled. 119 bool IsElidableCtorThatHasNotBeenElided = false; 120 EvalCallOptionsEvalCallOptions121 EvalCallOptions() {} 122 }; 123 124 class ExprEngine { 125 void anchor(); 126 127 public: 128 /// The modes of inlining, which override the default analysis-wide settings. 129 enum InliningModes { 130 /// Follow the default settings for inlining callees. 131 Inline_Regular = 0, 132 133 /// Do minimal inlining of callees. 134 Inline_Minimal = 0x1 135 }; 136 137 private: 138 cross_tu::CrossTranslationUnitContext &CTU; 139 bool IsCTUEnabled; 140 141 AnalysisManager &AMgr; 142 143 AnalysisDeclContextManager &AnalysisDeclContexts; 144 145 CoreEngine Engine; 146 147 /// G - the simulation graph. 148 ExplodedGraph &G; 149 150 /// StateMgr - Object that manages the data for all created states. 151 ProgramStateManager StateMgr; 152 153 /// SymMgr - Object that manages the symbol information. 154 SymbolManager &SymMgr; 155 156 /// MRMgr - MemRegionManager object that creates memory regions. 157 MemRegionManager &MRMgr; 158 159 /// svalBuilder - SValBuilder object that creates SVals from expressions. 160 SValBuilder &svalBuilder; 161 162 unsigned int currStmtIdx = 0; 163 const NodeBuilderContext *currBldrCtx = nullptr; 164 165 /// Helper object to determine if an Objective-C message expression 166 /// implicitly never returns. 167 ObjCNoReturn ObjCNoRet; 168 169 /// The BugReporter associated with this engine. It is important that 170 /// this object be placed at the very end of member variables so that its 171 /// destructor is called before the rest of the ExprEngine is destroyed. 172 PathSensitiveBugReporter BR; 173 174 /// The functions which have been analyzed through inlining. This is owned by 175 /// AnalysisConsumer. It can be null. 176 SetOfConstDecls *VisitedCallees; 177 178 /// The flag, which specifies the mode of inlining for the engine. 179 InliningModes HowToInline; 180 181 public: 182 ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, 183 SetOfConstDecls *VisitedCalleesIn, 184 FunctionSummariesTy *FS, InliningModes HowToInlineIn); 185 186 virtual ~ExprEngine() = default; 187 188 /// Returns true if there is still simulation state on the worklist. 189 bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { 190 return Engine.ExecuteWorkList(L, Steps, nullptr); 191 } 192 193 /// Execute the work list with an initial state. Nodes that reaches the exit 194 /// of the function are added into the Dst set, which represent the exit 195 /// state of the function call. Returns true if there is still simulation 196 /// state on the worklist. ExecuteWorkListWithInitialState(const LocationContext * L,unsigned Steps,ProgramStateRef InitState,ExplodedNodeSet & Dst)197 bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, 198 ProgramStateRef InitState, 199 ExplodedNodeSet &Dst) { 200 return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); 201 } 202 203 /// getContext - Return the ASTContext associated with this analysis. getContext()204 ASTContext &getContext() const { return AMgr.getASTContext(); } 205 getAnalysisManager()206 AnalysisManager &getAnalysisManager() { return AMgr; } 207 getAnalysisDeclContextManager()208 AnalysisDeclContextManager &getAnalysisDeclContextManager() { 209 return AMgr.getAnalysisDeclContextManager(); 210 } 211 getCheckerManager()212 CheckerManager &getCheckerManager() const { 213 return *AMgr.getCheckerManager(); 214 } 215 getSValBuilder()216 SValBuilder &getSValBuilder() { return svalBuilder; } 217 getBugReporter()218 BugReporter &getBugReporter() { return BR; } 219 220 cross_tu::CrossTranslationUnitContext * getCrossTranslationUnitContext()221 getCrossTranslationUnitContext() { 222 return &CTU; 223 } 224 getBuilderContext()225 const NodeBuilderContext &getBuilderContext() { 226 assert(currBldrCtx); 227 return *currBldrCtx; 228 } 229 230 const Stmt *getStmt() const; 231 getRootLocationContext()232 const LocationContext *getRootLocationContext() const { 233 assert(G.roots_begin() != G.roots_end()); 234 return (*G.roots_begin())->getLocation().getLocationContext(); 235 } 236 237 void GenerateAutoTransition(ExplodedNode *N); 238 void enqueueEndOfPath(ExplodedNodeSet &S); 239 void GenerateCallExitNode(ExplodedNode *N); 240 241 242 /// Dump graph to the specified filename. 243 /// If filename is empty, generate a temporary one. 244 /// \return The filename the graph is written into. 245 std::string DumpGraph(bool trim = false, StringRef Filename=""); 246 247 /// Dump the graph consisting of the given nodes to a specified filename. 248 /// Generate a temporary filename if it's not provided. 249 /// \return The filename the graph is written into. 250 std::string DumpGraph(ArrayRef<const ExplodedNode *> Nodes, 251 StringRef Filename = ""); 252 253 /// Visualize the ExplodedGraph created by executing the simulation. 254 void ViewGraph(bool trim = false); 255 256 /// Visualize a trimmed ExplodedGraph that only contains paths to the given 257 /// nodes. 258 void ViewGraph(ArrayRef<const ExplodedNode *> Nodes); 259 260 /// getInitialState - Return the initial state used for the root vertex 261 /// in the ExplodedGraph. 262 ProgramStateRef getInitialState(const LocationContext *InitLoc); 263 getGraph()264 ExplodedGraph &getGraph() { return G; } getGraph()265 const ExplodedGraph &getGraph() const { return G; } 266 267 /// Run the analyzer's garbage collection - remove dead symbols and 268 /// bindings from the state. 269 /// 270 /// Checkers can participate in this process with two callbacks: 271 /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation 272 /// class for more information. 273 /// 274 /// \param Node The predecessor node, from which the processing should start. 275 /// \param Out The returned set of output nodes. 276 /// \param ReferenceStmt The statement which is about to be processed. 277 /// Everything needed for this statement should be considered live. 278 /// A null statement means that everything in child LocationContexts 279 /// is dead. 280 /// \param LC The location context of the \p ReferenceStmt. A null location 281 /// context means that we have reached the end of analysis and that 282 /// all statements and local variables should be considered dead. 283 /// \param DiagnosticStmt Used as a location for any warnings that should 284 /// occur while removing the dead (e.g. leaks). By default, the 285 /// \p ReferenceStmt is used. 286 /// \param K Denotes whether this is a pre- or post-statement purge. This 287 /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an 288 /// entire location context is being cleared, in which case the 289 /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise, 290 /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default) 291 /// and \p ReferenceStmt must be valid (non-null). 292 void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, 293 const Stmt *ReferenceStmt, const LocationContext *LC, 294 const Stmt *DiagnosticStmt = nullptr, 295 ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind); 296 297 /// processCFGElement - Called by CoreEngine. Used to generate new successor 298 /// nodes by processing the 'effects' of a CFG element. 299 void processCFGElement(const CFGElement E, ExplodedNode *Pred, 300 unsigned StmtIdx, NodeBuilderContext *Ctx); 301 302 void ProcessStmt(const Stmt *S, ExplodedNode *Pred); 303 304 void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred); 305 306 void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred); 307 308 void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); 309 310 void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred); 311 312 void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, 313 ExplodedNode *Pred, ExplodedNodeSet &Dst); 314 void ProcessDeleteDtor(const CFGDeleteDtor D, 315 ExplodedNode *Pred, ExplodedNodeSet &Dst); 316 void ProcessBaseDtor(const CFGBaseDtor D, 317 ExplodedNode *Pred, ExplodedNodeSet &Dst); 318 void ProcessMemberDtor(const CFGMemberDtor D, 319 ExplodedNode *Pred, ExplodedNodeSet &Dst); 320 void ProcessTemporaryDtor(const CFGTemporaryDtor D, 321 ExplodedNode *Pred, ExplodedNodeSet &Dst); 322 323 /// Called by CoreEngine when processing the entrance of a CFGBlock. 324 void processCFGBlockEntrance(const BlockEdge &L, 325 NodeBuilderWithSinks &nodeBuilder, 326 ExplodedNode *Pred); 327 328 /// ProcessBranch - Called by CoreEngine. Used to generate successor 329 /// nodes by processing the 'effects' of a branch condition. 330 void processBranch(const Stmt *Condition, 331 NodeBuilderContext& BuilderCtx, 332 ExplodedNode *Pred, 333 ExplodedNodeSet &Dst, 334 const CFGBlock *DstT, 335 const CFGBlock *DstF); 336 337 /// Called by CoreEngine. 338 /// Used to generate successor nodes for temporary destructors depending 339 /// on whether the corresponding constructor was visited. 340 void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, 341 NodeBuilderContext &BldCtx, 342 ExplodedNode *Pred, ExplodedNodeSet &Dst, 343 const CFGBlock *DstT, 344 const CFGBlock *DstF); 345 346 /// Called by CoreEngine. Used to processing branching behavior 347 /// at static initializers. 348 void processStaticInitializer(const DeclStmt *DS, 349 NodeBuilderContext& BuilderCtx, 350 ExplodedNode *Pred, 351 ExplodedNodeSet &Dst, 352 const CFGBlock *DstT, 353 const CFGBlock *DstF); 354 355 /// processIndirectGoto - Called by CoreEngine. Used to generate successor 356 /// nodes by processing the 'effects' of a computed goto jump. 357 void processIndirectGoto(IndirectGotoNodeBuilder& builder); 358 359 /// ProcessSwitch - Called by CoreEngine. Used to generate successor 360 /// nodes by processing the 'effects' of a switch statement. 361 void processSwitch(SwitchNodeBuilder& builder); 362 363 /// Called by CoreEngine. Used to notify checkers that processing a 364 /// function has begun. Called for both inlined and top-level functions. 365 void processBeginOfFunction(NodeBuilderContext &BC, 366 ExplodedNode *Pred, ExplodedNodeSet &Dst, 367 const BlockEdge &L); 368 369 /// Called by CoreEngine. Used to notify checkers that processing a 370 /// function has ended. Called for both inlined and top-level functions. 371 void processEndOfFunction(NodeBuilderContext& BC, 372 ExplodedNode *Pred, 373 const ReturnStmt *RS = nullptr); 374 375 /// Remove dead bindings/symbols before exiting a function. 376 void removeDeadOnEndOfFunction(NodeBuilderContext& BC, 377 ExplodedNode *Pred, 378 ExplodedNodeSet &Dst); 379 380 /// Generate the entry node of the callee. 381 void processCallEnter(NodeBuilderContext& BC, CallEnter CE, 382 ExplodedNode *Pred); 383 384 /// Generate the sequence of nodes that simulate the call exit and the post 385 /// visit for CallExpr. 386 void processCallExit(ExplodedNode *Pred); 387 388 /// Called by CoreEngine when the analysis worklist has terminated. 389 void processEndWorklist(); 390 391 /// evalAssume - Callback function invoked by the ConstraintManager when 392 /// making assumptions about state values. 393 ProgramStateRef processAssume(ProgramStateRef state, SVal cond, 394 bool assumption); 395 396 /// processRegionChanges - Called by ProgramStateManager whenever a change is made 397 /// to the store. Used to update checkers that track region values. 398 ProgramStateRef 399 processRegionChanges(ProgramStateRef state, 400 const InvalidatedSymbols *invalidated, 401 ArrayRef<const MemRegion *> ExplicitRegions, 402 ArrayRef<const MemRegion *> Regions, 403 const LocationContext *LCtx, 404 const CallEvent *Call); 405 406 inline ProgramStateRef processRegionChange(ProgramStateRef state,const MemRegion * MR,const LocationContext * LCtx)407 processRegionChange(ProgramStateRef state, 408 const MemRegion* MR, 409 const LocationContext *LCtx) { 410 return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr); 411 } 412 413 /// printJson - Called by ProgramStateManager to print checker-specific data. 414 void printJson(raw_ostream &Out, ProgramStateRef State, 415 const LocationContext *LCtx, const char *NL, 416 unsigned int Space, bool IsDot) const; 417 getStateManager()418 ProgramStateManager &getStateManager() { return StateMgr; } 419 getStoreManager()420 StoreManager &getStoreManager() { return StateMgr.getStoreManager(); } 421 getConstraintManager()422 ConstraintManager &getConstraintManager() { 423 return StateMgr.getConstraintManager(); 424 } 425 426 // FIXME: Remove when we migrate over to just using SValBuilder. getBasicVals()427 BasicValueFactory &getBasicVals() { 428 return StateMgr.getBasicVals(); 429 } 430 getSymbolManager()431 SymbolManager &getSymbolManager() { return SymMgr; } getRegionManager()432 MemRegionManager &getRegionManager() { return MRMgr; } 433 getDataTags()434 DataTag::Factory &getDataTags() { return Engine.getDataTags(); } 435 436 // Functions for external checking of whether we have unfinished work wasBlocksExhausted()437 bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } hasEmptyWorkList()438 bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); } hasWorkRemaining()439 bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); } 440 getCoreEngine()441 const CoreEngine &getCoreEngine() const { return Engine; } 442 443 public: 444 /// Visit - Transfer function logic for all statements. Dispatches to 445 /// other functions that handle specific kinds of statements. 446 void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); 447 448 /// VisitArrayInitLoopExpr - Transfer function for array init loop. 449 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred, 450 ExplodedNodeSet &Dst); 451 452 /// VisitArraySubscriptExpr - Transfer function for array accesses. 453 void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, 454 ExplodedNode *Pred, 455 ExplodedNodeSet &Dst); 456 457 /// VisitGCCAsmStmt - Transfer function logic for inline asm. 458 void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, 459 ExplodedNodeSet &Dst); 460 461 /// VisitMSAsmStmt - Transfer function logic for MS inline asm. 462 void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, 463 ExplodedNodeSet &Dst); 464 465 /// VisitBlockExpr - Transfer function logic for BlockExprs. 466 void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, 467 ExplodedNodeSet &Dst); 468 469 /// VisitLambdaExpr - Transfer function logic for LambdaExprs. 470 void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, 471 ExplodedNodeSet &Dst); 472 473 /// VisitBinaryOperator - Transfer function logic for binary operators. 474 void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred, 475 ExplodedNodeSet &Dst); 476 477 478 /// VisitCall - Transfer function for function calls. 479 void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, 480 ExplodedNodeSet &Dst); 481 482 /// VisitCast - Transfer function logic for all casts (implicit and explicit). 483 void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, 484 ExplodedNodeSet &Dst); 485 486 /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. 487 void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, 488 ExplodedNode *Pred, ExplodedNodeSet &Dst); 489 490 /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs. 491 void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, 492 ExplodedNode *Pred, ExplodedNodeSet &Dst); 493 494 /// VisitDeclStmt - Transfer function logic for DeclStmts. 495 void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, 496 ExplodedNodeSet &Dst); 497 498 /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose 499 void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, 500 ExplodedNode *Pred, ExplodedNodeSet &Dst); 501 502 void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, 503 ExplodedNodeSet &Dst); 504 505 /// VisitLogicalExpr - Transfer function logic for '&&', '||' 506 void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, 507 ExplodedNodeSet &Dst); 508 509 /// VisitMemberExpr - Transfer function for member expressions. 510 void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, 511 ExplodedNodeSet &Dst); 512 513 /// VisitAtomicExpr - Transfer function for builtin atomic expressions 514 void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, 515 ExplodedNodeSet &Dst); 516 517 /// Transfer function logic for ObjCAtSynchronizedStmts. 518 void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, 519 ExplodedNode *Pred, ExplodedNodeSet &Dst); 520 521 /// Transfer function logic for computing the lvalue of an Objective-C ivar. 522 void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, 523 ExplodedNodeSet &Dst); 524 525 /// VisitObjCForCollectionStmt - Transfer function logic for 526 /// ObjCForCollectionStmt. 527 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, 528 ExplodedNode *Pred, ExplodedNodeSet &Dst); 529 530 void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, 531 ExplodedNodeSet &Dst); 532 533 /// VisitReturnStmt - Transfer function logic for return statements. 534 void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, 535 ExplodedNodeSet &Dst); 536 537 /// VisitOffsetOfExpr - Transfer function for offsetof. 538 void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, 539 ExplodedNodeSet &Dst); 540 541 /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. 542 void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, 543 ExplodedNode *Pred, ExplodedNodeSet &Dst); 544 545 /// VisitUnaryOperator - Transfer function logic for unary operators. 546 void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, 547 ExplodedNodeSet &Dst); 548 549 /// Handle ++ and -- (both pre- and post-increment). 550 void VisitIncrementDecrementOperator(const UnaryOperator* U, 551 ExplodedNode *Pred, 552 ExplodedNodeSet &Dst); 553 554 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, 555 ExplodedNodeSet &PreVisit, 556 ExplodedNodeSet &Dst); 557 558 void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, 559 ExplodedNodeSet &Dst); 560 561 void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 562 ExplodedNodeSet & Dst); 563 564 void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, 565 ExplodedNodeSet &Dst); 566 567 void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, 568 ExplodedNode *Pred, ExplodedNodeSet &Dst); 569 570 void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, 571 const Stmt *S, bool IsBaseDtor, 572 ExplodedNode *Pred, ExplodedNodeSet &Dst, 573 EvalCallOptions &Options); 574 575 void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, 576 ExplodedNode *Pred, 577 ExplodedNodeSet &Dst); 578 579 void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 580 ExplodedNodeSet &Dst); 581 582 void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, 583 ExplodedNodeSet &Dst); 584 585 /// Create a C++ temporary object for an rvalue. 586 void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 587 ExplodedNode *Pred, 588 ExplodedNodeSet &Dst); 589 590 /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic 591 /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) 592 /// with those assumptions. 593 void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 594 const Expr *Ex); 595 596 static std::pair<const ProgramPointTag *, const ProgramPointTag *> 597 geteagerlyAssumeBinOpBifurcationTags(); 598 599 ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex, 600 const LocationContext *LCtx, QualType T, 601 QualType ExTy, const CastExpr *CastE, 602 StmtNodeBuilder &Bldr, 603 ExplodedNode *Pred); 604 605 ProgramStateRef handleLVectorSplat(ProgramStateRef state, 606 const LocationContext *LCtx, 607 const CastExpr *CastE, 608 StmtNodeBuilder &Bldr, 609 ExplodedNode *Pred); 610 611 void handleUOExtension(ExplodedNodeSet::iterator I, 612 const UnaryOperator* U, 613 StmtNodeBuilder &Bldr); 614 615 public: evalBinOp(ProgramStateRef ST,BinaryOperator::Opcode Op,SVal LHS,SVal RHS,QualType T)616 SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, 617 SVal LHS, SVal RHS, QualType T) { 618 return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T); 619 } 620 621 /// Retreives which element is being constructed in a non-POD type array. 622 static std::optional<unsigned> 623 getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, 624 const LocationContext *LCtx); 625 626 /// Retreives which element is being destructed in a non-POD type array. 627 static std::optional<unsigned> 628 getPendingArrayDestruction(ProgramStateRef State, 629 const LocationContext *LCtx); 630 631 /// Retreives the size of the array in the pending ArrayInitLoopExpr. 632 static std::optional<unsigned> 633 getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, 634 const LocationContext *LCtx); 635 636 /// By looking at a certain item that may be potentially part of an object's 637 /// ConstructionContext, retrieve such object's location. A particular 638 /// statement can be transparently passed as \p Item in most cases. 639 static std::optional<SVal> 640 getObjectUnderConstruction(ProgramStateRef State, 641 const ConstructionContextItem &Item, 642 const LocationContext *LC); 643 644 /// Call PointerEscape callback when a value escapes as a result of bind. 645 ProgramStateRef processPointerEscapedOnBind( 646 ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals, 647 const LocationContext *LCtx, PointerEscapeKind Kind, 648 const CallEvent *Call); 649 650 /// Call PointerEscape callback when a value escapes as a result of 651 /// region invalidation. 652 /// \param[in] ITraits Specifies invalidation traits for regions/symbols. 653 ProgramStateRef notifyCheckersOfPointerEscape( 654 ProgramStateRef State, 655 const InvalidatedSymbols *Invalidated, 656 ArrayRef<const MemRegion *> ExplicitRegions, 657 const CallEvent *Call, 658 RegionAndSymbolInvalidationTraits &ITraits); 659 660 private: 661 /// evalBind - Handle the semantics of binding a value to a specific location. 662 /// This method is used by evalStore, VisitDeclStmt, and others. 663 void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, 664 SVal location, SVal Val, bool atDeclInit = false, 665 const ProgramPoint *PP = nullptr); 666 667 ProgramStateRef 668 processPointerEscapedOnBind(ProgramStateRef State, 669 SVal Loc, SVal Val, 670 const LocationContext *LCtx); 671 672 /// A simple wrapper when you only need to notify checkers of pointer-escape 673 /// of some values. 674 ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef<SVal> Vs, 675 PointerEscapeKind K, 676 const CallEvent *Call = nullptr) const; 677 678 public: 679 // FIXME: 'tag' should be removed, and a LocationContext should be used 680 // instead. 681 // FIXME: Comment on the meaning of the arguments, when 'St' may not 682 // be the same as Pred->state, and when 'location' may not be the 683 // same as state->getLValue(Ex). 684 /// Simulate a read of the result of Ex. 685 void evalLoad(ExplodedNodeSet &Dst, 686 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 687 const Expr *BoundExpr, 688 ExplodedNode *Pred, 689 ProgramStateRef St, 690 SVal location, 691 const ProgramPointTag *tag = nullptr, 692 QualType LoadTy = QualType()); 693 694 // FIXME: 'tag' should be removed, and a LocationContext should be used 695 // instead. 696 void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, 697 ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, 698 const ProgramPointTag *tag = nullptr); 699 700 /// Return the CFG element corresponding to the worklist element 701 /// that is currently being processed by ExprEngine. getCurrentCFGElement()702 CFGElement getCurrentCFGElement() { 703 return (*currBldrCtx->getBlock())[currStmtIdx]; 704 } 705 706 /// Create a new state in which the call return value is binded to the 707 /// call origin expression. 708 ProgramStateRef bindReturnValue(const CallEvent &Call, 709 const LocationContext *LCtx, 710 ProgramStateRef State); 711 712 /// Evaluate a call, running pre- and post-call checkers and allowing checkers 713 /// to be responsible for handling the evaluation of the call itself. 714 void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, 715 const CallEvent &Call); 716 717 /// Default implementation of call evaluation. 718 void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, 719 const CallEvent &Call, 720 const EvalCallOptions &CallOpts = {}); 721 722 /// Find location of the object that is being constructed by a given 723 /// constructor. This should ideally always succeed but due to not being 724 /// fully implemented it sometimes indicates that it failed via its 725 /// out-parameter CallOpts; in such cases a fake temporary region is 726 /// returned, which is better than nothing but does not represent 727 /// the actual behavior of the program. The Idx parameter is used if we 728 /// construct an array of objects. In that case it points to the index 729 /// of the continuous memory region. 730 /// E.g.: 731 /// For `int arr[4]` this index can be 0,1,2,3. 732 /// For `int arr2[3][3]` this index can be 0,1,...,7,8. 733 /// A multi-dimensional array is also a continuous memory location in a 734 /// row major order, so for arr[0][0] Idx is 0 and for arr[2][2] Idx is 8. 735 SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State, 736 const NodeBuilderContext *BldrCtx, 737 const LocationContext *LCtx, 738 const ConstructionContext *CC, 739 EvalCallOptions &CallOpts, 740 unsigned Idx = 0); 741 742 /// Update the program state with all the path-sensitive information 743 /// that's necessary to perform construction of an object with a given 744 /// syntactic construction context. V and CallOpts have to be obtained from 745 /// computeObjectUnderConstruction() invoked with the same set of 746 /// the remaining arguments (E, State, LCtx, CC). 747 ProgramStateRef updateObjectsUnderConstruction( 748 SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx, 749 const ConstructionContext *CC, const EvalCallOptions &CallOpts); 750 751 /// A convenient wrapper around computeObjectUnderConstruction 752 /// and updateObjectsUnderConstruction. 753 std::pair<ProgramStateRef, SVal> handleConstructionContext( 754 const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx, 755 const LocationContext *LCtx, const ConstructionContext *CC, 756 EvalCallOptions &CallOpts, unsigned Idx = 0) { 757 758 SVal V = computeObjectUnderConstruction(E, State, BldrCtx, LCtx, CC, 759 CallOpts, Idx); 760 State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts); 761 762 return std::make_pair(State, V); 763 } 764 765 private: 766 ProgramStateRef finishArgumentConstruction(ProgramStateRef State, 767 const CallEvent &Call); 768 void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred, 769 const CallEvent &Call); 770 771 void evalLoadCommon(ExplodedNodeSet &Dst, 772 const Expr *NodeEx, /* Eventually will be a CFGStmt */ 773 const Expr *BoundEx, 774 ExplodedNode *Pred, 775 ProgramStateRef St, 776 SVal location, 777 const ProgramPointTag *tag, 778 QualType LoadTy); 779 780 void evalLocation(ExplodedNodeSet &Dst, 781 const Stmt *NodeEx, /* This will eventually be a CFGStmt */ 782 const Stmt *BoundEx, 783 ExplodedNode *Pred, 784 ProgramStateRef St, 785 SVal location, 786 bool isLoad); 787 788 /// Count the stack depth and determine if the call is recursive. 789 void examineStackFrames(const Decl *D, const LocationContext *LCtx, 790 bool &IsRecursive, unsigned &StackDepth); 791 792 enum CallInlinePolicy { 793 CIP_Allowed, 794 CIP_DisallowedOnce, 795 CIP_DisallowedAlways 796 }; 797 798 /// See if a particular call should be inlined, by only looking 799 /// at the call event and the current state of analysis. 800 CallInlinePolicy mayInlineCallKind(const CallEvent &Call, 801 const ExplodedNode *Pred, 802 AnalyzerOptions &Opts, 803 const EvalCallOptions &CallOpts); 804 805 /// See if the given AnalysisDeclContext is built for a function that we 806 /// should always inline simply because it's small enough. 807 /// Apart from "small" functions, we also have "large" functions 808 /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify 809 /// the remaining functions as "medium". 810 bool isSmall(AnalysisDeclContext *ADC) const; 811 812 /// See if the given AnalysisDeclContext is built for a function that we 813 /// should inline carefully because it looks pretty large. 814 bool isLarge(AnalysisDeclContext *ADC) const; 815 816 /// See if the given AnalysisDeclContext is built for a function that we 817 /// should never inline because it's legit gigantic. 818 bool isHuge(AnalysisDeclContext *ADC) const; 819 820 /// See if the given AnalysisDeclContext is built for a function that we 821 /// should inline, just by looking at the declaration of the function. 822 bool mayInlineDecl(AnalysisDeclContext *ADC) const; 823 824 /// Checks our policies and decides weither the given call should be inlined. 825 bool shouldInlineCall(const CallEvent &Call, const Decl *D, 826 const ExplodedNode *Pred, 827 const EvalCallOptions &CallOpts = {}); 828 829 /// Checks whether our policies allow us to inline a non-POD type array 830 /// construction. 831 bool shouldInlineArrayConstruction(const ProgramStateRef State, 832 const CXXConstructExpr *CE, 833 const LocationContext *LCtx); 834 835 /// Checks whether our policies allow us to inline a non-POD type array 836 /// destruction. 837 /// \param Size The size of the array. 838 bool shouldInlineArrayDestruction(uint64_t Size); 839 840 /// Prepares the program state for array destruction. If no error happens 841 /// the function binds a 'PendingArrayDestruction' entry to the state, which 842 /// it returns along with the index. If any error happens (we fail to read 843 /// the size, the index would be -1, etc.) the function will return the 844 /// original state along with an index of 0. The actual element count of the 845 /// array can be accessed by the optional 'ElementCountVal' parameter. \param 846 /// State The program state. \param Region The memory region where the array 847 /// is stored. \param ElementTy The type an element in the array. \param LCty 848 /// The location context. \param ElementCountVal A pointer to an optional 849 /// SVal. If specified, the size of the array will be returned in it. It can 850 /// be Unknown. 851 std::pair<ProgramStateRef, uint64_t> prepareStateForArrayDestruction( 852 const ProgramStateRef State, const MemRegion *Region, 853 const QualType &ElementTy, const LocationContext *LCtx, 854 SVal *ElementCountVal = nullptr); 855 856 /// Checks whether we construct an array of non-POD type, and decides if the 857 /// constructor should be inkoved once again. 858 bool shouldRepeatCtorCall(ProgramStateRef State, const CXXConstructExpr *E, 859 const LocationContext *LCtx); 860 861 void inlineCall(WorkList *WList, const CallEvent &Call, const Decl *D, 862 NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State); 863 864 void ctuBifurcate(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 865 ExplodedNode *Pred, ProgramStateRef State); 866 867 /// Returns true if the CTU analysis is running its second phase. isSecondPhaseCTU()868 bool isSecondPhaseCTU() { return IsCTUEnabled && !Engine.getCTUWorkList(); } 869 870 /// Conservatively evaluate call by invalidating regions and binding 871 /// a conjured return value. 872 void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, 873 ExplodedNode *Pred, ProgramStateRef State); 874 875 /// Either inline or process the call conservatively (or both), based 876 /// on DynamicDispatchBifurcation data. 877 void BifurcateCall(const MemRegion *BifurReg, 878 const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, 879 ExplodedNode *Pred); 880 881 bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); 882 883 /// Models a trivial copy or move constructor or trivial assignment operator 884 /// call with a simple bind. 885 void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 886 const CallEvent &Call); 887 888 /// If the value of the given expression \p InitWithAdjustments is a NonLoc, 889 /// copy it into a new temporary object region, and replace the value of the 890 /// expression with that. 891 /// 892 /// If \p Result is provided, the new region will be bound to this expression 893 /// instead of \p InitWithAdjustments. 894 /// 895 /// Returns the temporary region with adjustments into the optional 896 /// OutRegionWithAdjustments out-parameter if a new region was indeed needed, 897 /// otherwise sets it to nullptr. 898 ProgramStateRef createTemporaryRegionIfNeeded( 899 ProgramStateRef State, const LocationContext *LC, 900 const Expr *InitWithAdjustments, const Expr *Result = nullptr, 901 const SubRegion **OutRegionWithAdjustments = nullptr); 902 903 /// Returns a region representing the `Idx`th element of a (possibly 904 /// multi-dimensional) array, for the purposes of element construction or 905 /// destruction. 906 /// 907 /// On return, \p Ty will be set to the base type of the array. 908 /// 909 /// If the type is not an array type at all, the original value is returned. 910 /// Otherwise the "IsArray" flag is set. 911 static SVal makeElementRegion(ProgramStateRef State, SVal LValue, 912 QualType &Ty, bool &IsArray, unsigned Idx = 0); 913 914 /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG 915 /// block to find the constructor expression that directly constructed into 916 /// the storage for this statement. Returns null if the constructor for this 917 /// statement created a temporary object region rather than directly 918 /// constructing into an existing region. 919 const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); 920 921 /// Common code that handles either a CXXConstructExpr or a 922 /// CXXInheritedCtorInitExpr. 923 void handleConstructor(const Expr *E, ExplodedNode *Pred, 924 ExplodedNodeSet &Dst); 925 926 public: 927 /// Note whether this loop has any more iteratios to model. These methods are 928 /// essentially an interface for a GDM trait. Further reading in 929 /// ExprEngine::VisitObjCForCollectionStmt(). 930 [[nodiscard]] static ProgramStateRef 931 setWhetherHasMoreIteration(ProgramStateRef State, 932 const ObjCForCollectionStmt *O, 933 const LocationContext *LC, bool HasMoreIteraton); 934 935 [[nodiscard]] static ProgramStateRef 936 removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, 937 const LocationContext *LC); 938 939 [[nodiscard]] static bool hasMoreIteration(ProgramStateRef State, 940 const ObjCForCollectionStmt *O, 941 const LocationContext *LC); 942 943 private: 944 /// Assuming we construct an array of non-POD types, this method allows us 945 /// to store which element is to be constructed next. 946 static ProgramStateRef 947 setIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, 948 const LocationContext *LCtx, unsigned Idx); 949 950 static ProgramStateRef 951 removeIndexOfElementToConstruct(ProgramStateRef State, 952 const CXXConstructExpr *E, 953 const LocationContext *LCtx); 954 955 /// Assuming we destruct an array of non-POD types, this method allows us 956 /// to store which element is to be destructed next. 957 static ProgramStateRef setPendingArrayDestruction(ProgramStateRef State, 958 const LocationContext *LCtx, 959 unsigned Idx); 960 961 static ProgramStateRef 962 removePendingArrayDestruction(ProgramStateRef State, 963 const LocationContext *LCtx); 964 965 /// Sets the size of the array in a pending ArrayInitLoopExpr. 966 static ProgramStateRef setPendingInitLoop(ProgramStateRef State, 967 const CXXConstructExpr *E, 968 const LocationContext *LCtx, 969 unsigned Idx); 970 971 static ProgramStateRef removePendingInitLoop(ProgramStateRef State, 972 const CXXConstructExpr *E, 973 const LocationContext *LCtx); 974 975 static ProgramStateRef 976 removeStateTraitsUsedForArrayEvaluation(ProgramStateRef State, 977 const CXXConstructExpr *E, 978 const LocationContext *LCtx); 979 980 /// Store the location of a C++ object corresponding to a statement 981 /// until the statement is actually encountered. For example, if a DeclStmt 982 /// has CXXConstructExpr as its initializer, the object would be considered 983 /// to be "under construction" between CXXConstructExpr and DeclStmt. 984 /// This allows, among other things, to keep bindings to variable's fields 985 /// made within the constructor alive until its declaration actually 986 /// goes into scope. 987 static ProgramStateRef 988 addObjectUnderConstruction(ProgramStateRef State, 989 const ConstructionContextItem &Item, 990 const LocationContext *LC, SVal V); 991 992 /// Mark the object sa fully constructed, cleaning up the state trait 993 /// that tracks objects under construction. 994 static ProgramStateRef 995 finishObjectConstruction(ProgramStateRef State, 996 const ConstructionContextItem &Item, 997 const LocationContext *LC); 998 999 /// If the given expression corresponds to a temporary that was used for 1000 /// passing into an elidable copy/move constructor and that constructor 1001 /// was actually elided, track that we also need to elide the destructor. 1002 static ProgramStateRef elideDestructor(ProgramStateRef State, 1003 const CXXBindTemporaryExpr *BTE, 1004 const LocationContext *LC); 1005 1006 /// Stop tracking the destructor that corresponds to an elided constructor. 1007 static ProgramStateRef 1008 cleanupElidedDestructor(ProgramStateRef State, 1009 const CXXBindTemporaryExpr *BTE, 1010 const LocationContext *LC); 1011 1012 /// Returns true if the given expression corresponds to a temporary that 1013 /// was constructed for passing into an elidable copy/move constructor 1014 /// and that constructor was actually elided. 1015 static bool isDestructorElided(ProgramStateRef State, 1016 const CXXBindTemporaryExpr *BTE, 1017 const LocationContext *LC); 1018 1019 /// Check if all objects under construction have been fully constructed 1020 /// for the given context range (including FromLC, not including ToLC). 1021 /// This is useful for assertions. Also checks if elided destructors 1022 /// were cleaned up. 1023 static bool areAllObjectsFullyConstructed(ProgramStateRef State, 1024 const LocationContext *FromLC, 1025 const LocationContext *ToLC); 1026 }; 1027 1028 /// Traits for storing the call processing policy inside GDM. 1029 /// The GDM stores the corresponding CallExpr pointer. 1030 // FIXME: This does not use the nice trait macros because it must be accessible 1031 // from multiple translation units. 1032 struct ReplayWithoutInlining{}; 1033 template <> 1034 struct ProgramStateTrait<ReplayWithoutInlining> : 1035 public ProgramStatePartialTrait<const void*> { 1036 static void *GDMIndex(); 1037 }; 1038 1039 } // namespace ento 1040 1041 } // namespace clang 1042 1043 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H 1044