1 //===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===// 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 set of BugReporter "visitors" which can be used to 10 // enhance the diagnostics reported for a bug. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DeclBase.h" 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/Expr.h" 20 #include "clang/AST/ExprCXX.h" 21 #include "clang/AST/ExprObjC.h" 22 #include "clang/AST/Stmt.h" 23 #include "clang/AST/Type.h" 24 #include "clang/ASTMatchers/ASTMatchFinder.h" 25 #include "clang/Analysis/Analyses/Dominators.h" 26 #include "clang/Analysis/AnalysisDeclContext.h" 27 #include "clang/Analysis/CFG.h" 28 #include "clang/Analysis/CFGStmtMap.h" 29 #include "clang/Analysis/ProgramPoint.h" 30 #include "clang/Basic/IdentifierTable.h" 31 #include "clang/Basic/LLVM.h" 32 #include "clang/Basic/SourceLocation.h" 33 #include "clang/Basic/SourceManager.h" 34 #include "clang/Lex/Lexer.h" 35 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 36 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 37 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 38 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 39 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 40 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 41 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 42 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 43 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 44 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" 45 #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h" 46 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 47 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 48 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" 49 #include "llvm/ADT/ArrayRef.h" 50 #include "llvm/ADT/None.h" 51 #include "llvm/ADT/Optional.h" 52 #include "llvm/ADT/STLExtras.h" 53 #include "llvm/ADT/SmallPtrSet.h" 54 #include "llvm/ADT/SmallString.h" 55 #include "llvm/ADT/SmallVector.h" 56 #include "llvm/ADT/StringExtras.h" 57 #include "llvm/ADT/StringRef.h" 58 #include "llvm/Support/Casting.h" 59 #include "llvm/Support/ErrorHandling.h" 60 #include "llvm/Support/raw_ostream.h" 61 #include <cassert> 62 #include <deque> 63 #include <memory> 64 #include <string> 65 #include <utility> 66 67 using namespace clang; 68 using namespace ento; 69 70 //===----------------------------------------------------------------------===// 71 // Utility functions. 72 //===----------------------------------------------------------------------===// 73 74 static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) { 75 if (B->isAdditiveOp() && B->getType()->isPointerType()) { 76 if (B->getLHS()->getType()->isPointerType()) { 77 return B->getLHS(); 78 } else if (B->getRHS()->getType()->isPointerType()) { 79 return B->getRHS(); 80 } 81 } 82 return nullptr; 83 } 84 85 /// Given that expression S represents a pointer that would be dereferenced, 86 /// try to find a sub-expression from which the pointer came from. 87 /// This is used for tracking down origins of a null or undefined value: 88 /// "this is null because that is null because that is null" etc. 89 /// We wipe away field and element offsets because they merely add offsets. 90 /// We also wipe away all casts except lvalue-to-rvalue casts, because the 91 /// latter represent an actual pointer dereference; however, we remove 92 /// the final lvalue-to-rvalue cast before returning from this function 93 /// because it demonstrates more clearly from where the pointer rvalue was 94 /// loaded. Examples: 95 /// x->y.z ==> x (lvalue) 96 /// foo()->y.z ==> foo() (rvalue) 97 const Expr *bugreporter::getDerefExpr(const Stmt *S) { 98 const auto *E = dyn_cast<Expr>(S); 99 if (!E) 100 return nullptr; 101 102 while (true) { 103 if (const auto *CE = dyn_cast<CastExpr>(E)) { 104 if (CE->getCastKind() == CK_LValueToRValue) { 105 // This cast represents the load we're looking for. 106 break; 107 } 108 E = CE->getSubExpr(); 109 } else if (const auto *B = dyn_cast<BinaryOperator>(E)) { 110 // Pointer arithmetic: '*(x + 2)' -> 'x') etc. 111 if (const Expr *Inner = peelOffPointerArithmetic(B)) { 112 E = Inner; 113 } else { 114 // Probably more arithmetic can be pattern-matched here, 115 // but for now give up. 116 break; 117 } 118 } else if (const auto *U = dyn_cast<UnaryOperator>(E)) { 119 if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf || 120 (U->isIncrementDecrementOp() && U->getType()->isPointerType())) { 121 // Operators '*' and '&' don't actually mean anything. 122 // We look at casts instead. 123 E = U->getSubExpr(); 124 } else { 125 // Probably more arithmetic can be pattern-matched here, 126 // but for now give up. 127 break; 128 } 129 } 130 // Pattern match for a few useful cases: a[0], p->f, *p etc. 131 else if (const auto *ME = dyn_cast<MemberExpr>(E)) { 132 E = ME->getBase(); 133 } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) { 134 E = IvarRef->getBase(); 135 } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) { 136 E = AE->getBase(); 137 } else if (const auto *PE = dyn_cast<ParenExpr>(E)) { 138 E = PE->getSubExpr(); 139 } else if (const auto *FE = dyn_cast<FullExpr>(E)) { 140 E = FE->getSubExpr(); 141 } else { 142 // Other arbitrary stuff. 143 break; 144 } 145 } 146 147 // Special case: remove the final lvalue-to-rvalue cast, but do not recurse 148 // deeper into the sub-expression. This way we return the lvalue from which 149 // our pointer rvalue was loaded. 150 if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) 151 if (CE->getCastKind() == CK_LValueToRValue) 152 E = CE->getSubExpr(); 153 154 return E; 155 } 156 157 /// Comparing internal representations of symbolic values (via 158 /// SVal::operator==()) is a valid way to check if the value was updated, 159 /// unless it's a LazyCompoundVal that may have a different internal 160 /// representation every time it is loaded from the state. In this function we 161 /// do an approximate comparison for lazy compound values, checking that they 162 /// are the immediate snapshots of the tracked region's bindings within the 163 /// node's respective states but not really checking that these snapshots 164 /// actually contain the same set of bindings. 165 static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, 166 const ExplodedNode *RightNode, SVal RightVal) { 167 if (LeftVal == RightVal) 168 return true; 169 170 const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>(); 171 if (!LLCV) 172 return false; 173 174 const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>(); 175 if (!RLCV) 176 return false; 177 178 return LLCV->getRegion() == RLCV->getRegion() && 179 LLCV->getStore() == LeftNode->getState()->getStore() && 180 RLCV->getStore() == RightNode->getState()->getStore(); 181 } 182 183 static Optional<SVal> getSValForVar(const Expr *CondVarExpr, 184 const ExplodedNode *N) { 185 ProgramStateRef State = N->getState(); 186 const LocationContext *LCtx = N->getLocationContext(); 187 188 assert(CondVarExpr); 189 CondVarExpr = CondVarExpr->IgnoreImpCasts(); 190 191 // The declaration of the value may rely on a pointer so take its l-value. 192 // FIXME: As seen in VisitCommonDeclRefExpr, sometimes DeclRefExpr may 193 // evaluate to a FieldRegion when it refers to a declaration of a lambda 194 // capture variable. We most likely need to duplicate that logic here. 195 if (const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr)) 196 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) 197 return State->getSVal(State->getLValue(VD, LCtx)); 198 199 if (const auto *ME = dyn_cast<MemberExpr>(CondVarExpr)) 200 if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) 201 if (auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>()) 202 return State->getRawSVal(*FieldL, FD->getType()); 203 204 return None; 205 } 206 207 static Optional<const llvm::APSInt *> 208 getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) { 209 210 if (Optional<SVal> V = getSValForVar(CondVarExpr, N)) 211 if (auto CI = V->getAs<nonloc::ConcreteInt>()) 212 return &CI->getValue(); 213 return None; 214 } 215 216 static bool isVarAnInterestingCondition(const Expr *CondVarExpr, 217 const ExplodedNode *N, 218 const BugReport *B) { 219 // Even if this condition is marked as interesting, it isn't *that* 220 // interesting if it didn't happen in a nested stackframe, the user could just 221 // follow the arrows. 222 if (!B->getErrorNode()->getStackFrame()->isParentOf(N->getStackFrame())) 223 return false; 224 225 if (Optional<SVal> V = getSValForVar(CondVarExpr, N)) 226 if (Optional<bugreporter::TrackingKind> K = B->getInterestingnessKind(*V)) 227 return *K == bugreporter::TrackingKind::Condition; 228 229 return false; 230 } 231 232 static bool isInterestingExpr(const Expr *E, const ExplodedNode *N, 233 const BugReport *B) { 234 if (Optional<SVal> V = getSValForVar(E, N)) 235 return B->getInterestingnessKind(*V).hasValue(); 236 return false; 237 } 238 239 /// \return name of the macro inside the location \p Loc. 240 static StringRef getMacroName(SourceLocation Loc, 241 BugReporterContext &BRC) { 242 return Lexer::getImmediateMacroName( 243 Loc, 244 BRC.getSourceManager(), 245 BRC.getASTContext().getLangOpts()); 246 } 247 248 /// \return Whether given spelling location corresponds to an expansion 249 /// of a function-like macro. 250 static bool isFunctionMacroExpansion(SourceLocation Loc, 251 const SourceManager &SM) { 252 if (!Loc.isMacroID()) 253 return false; 254 while (SM.isMacroArgExpansion(Loc)) 255 Loc = SM.getImmediateExpansionRange(Loc).getBegin(); 256 std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc); 257 SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first); 258 const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion(); 259 return EInfo.isFunctionMacroExpansion(); 260 } 261 262 /// \return Whether \c RegionOfInterest was modified at \p N, 263 /// where \p ValueAfter is \c RegionOfInterest's value at the end of the 264 /// stack frame. 265 static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest, 266 const ExplodedNode *N, 267 SVal ValueAfter) { 268 ProgramStateRef State = N->getState(); 269 ProgramStateManager &Mgr = N->getState()->getStateManager(); 270 271 if (!N->getLocationAs<PostStore>() && !N->getLocationAs<PostInitializer>() && 272 !N->getLocationAs<PostStmt>()) 273 return false; 274 275 // Writing into region of interest. 276 if (auto PS = N->getLocationAs<PostStmt>()) 277 if (auto *BO = PS->getStmtAs<BinaryOperator>()) 278 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf( 279 N->getSVal(BO->getLHS()).getAsRegion())) 280 return true; 281 282 // SVal after the state is possibly different. 283 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest); 284 if (!Mgr.getSValBuilder() 285 .areEqual(State, ValueAtN, ValueAfter) 286 .isConstrainedTrue() && 287 (!ValueAtN.isUndef() || !ValueAfter.isUndef())) 288 return true; 289 290 return false; 291 } 292 293 //===----------------------------------------------------------------------===// 294 // Implementation of BugReporterVisitor. 295 //===----------------------------------------------------------------------===// 296 297 PathDiagnosticPieceRef BugReporterVisitor::getEndPath(BugReporterContext &, 298 const ExplodedNode *, 299 BugReport &) { 300 return nullptr; 301 } 302 303 void BugReporterVisitor::finalizeVisitor(BugReporterContext &, 304 const ExplodedNode *, BugReport &) {} 305 306 PathDiagnosticPieceRef 307 BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC, 308 const ExplodedNode *EndPathNode, 309 const BugReport &BR) { 310 PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath( 311 EndPathNode, BRC.getSourceManager()); 312 313 const auto &Ranges = BR.getRanges(); 314 315 // Only add the statement itself as a range if we didn't specify any 316 // special ranges for this report. 317 auto P = std::make_shared<PathDiagnosticEventPiece>( 318 L, BR.getDescription(), Ranges.begin() == Ranges.end()); 319 for (SourceRange Range : Ranges) 320 P->addRange(Range); 321 322 return P; 323 } 324 325 //===----------------------------------------------------------------------===// 326 // Implementation of NoStoreFuncVisitor. 327 //===----------------------------------------------------------------------===// 328 329 namespace { 330 331 /// Put a diagnostic on return statement of all inlined functions 332 /// for which the region of interest \p RegionOfInterest was passed into, 333 /// but not written inside, and it has caused an undefined read or a null 334 /// pointer dereference outside. 335 class NoStoreFuncVisitor final : public BugReporterVisitor { 336 const SubRegion *RegionOfInterest; 337 MemRegionManager &MmrMgr; 338 const SourceManager &SM; 339 const PrintingPolicy &PP; 340 bugreporter::TrackingKind TKind; 341 342 /// Recursion limit for dereferencing fields when looking for the 343 /// region of interest. 344 /// The limit of two indicates that we will dereference fields only once. 345 static const unsigned DEREFERENCE_LIMIT = 2; 346 347 /// Frames writing into \c RegionOfInterest. 348 /// This visitor generates a note only if a function does not write into 349 /// a region of interest. This information is not immediately available 350 /// by looking at the node associated with the exit from the function 351 /// (usually the return statement). To avoid recomputing the same information 352 /// many times (going up the path for each node and checking whether the 353 /// region was written into) we instead lazily compute the 354 /// stack frames along the path which write into the region of interest. 355 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion; 356 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated; 357 358 using RegionVector = SmallVector<const MemRegion *, 5>; 359 360 public: 361 NoStoreFuncVisitor(const SubRegion *R, bugreporter::TrackingKind TKind) 362 : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()), 363 SM(MmrMgr.getContext().getSourceManager()), 364 PP(MmrMgr.getContext().getPrintingPolicy()), TKind(TKind) {} 365 366 void Profile(llvm::FoldingSetNodeID &ID) const override { 367 static int Tag = 0; 368 ID.AddPointer(&Tag); 369 ID.AddPointer(RegionOfInterest); 370 } 371 372 void *getTag() const { 373 static int Tag = 0; 374 return static_cast<void *>(&Tag); 375 } 376 377 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, 378 BugReporterContext &BR, 379 BugReport &R) override; 380 381 private: 382 /// Attempts to find the region of interest in a given record decl, 383 /// by either following the base classes or fields. 384 /// Dereferences fields up to a given recursion limit. 385 /// Note that \p Vec is passed by value, leading to quadratic copying cost, 386 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT. 387 /// \return A chain fields leading to the region of interest or None. 388 const Optional<RegionVector> 389 findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State, 390 const MemRegion *R, const RegionVector &Vec = {}, 391 int depth = 0); 392 393 /// Check and lazily calculate whether the region of interest is 394 /// modified in the stack frame to which \p N belongs. 395 /// The calculation is cached in FramesModifyingRegion. 396 bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) { 397 const LocationContext *Ctx = N->getLocationContext(); 398 const StackFrameContext *SCtx = Ctx->getStackFrame(); 399 if (!FramesModifyingCalculated.count(SCtx)) 400 findModifyingFrames(N); 401 return FramesModifyingRegion.count(SCtx); 402 } 403 404 /// Write to \c FramesModifyingRegion all stack frames along 405 /// the path in the current stack frame which modify \c RegionOfInterest. 406 void findModifyingFrames(const ExplodedNode *N); 407 408 /// Consume the information on the no-store stack frame in order to 409 /// either emit a note or suppress the report enirely. 410 /// \return Diagnostics piece for region not modified in the current function, 411 /// if it decides to emit one. 412 PathDiagnosticPieceRef 413 maybeEmitNote(BugReport &R, const CallEvent &Call, const ExplodedNode *N, 414 const RegionVector &FieldChain, const MemRegion *MatchedRegion, 415 StringRef FirstElement, bool FirstIsReferenceType, 416 unsigned IndirectionLevel); 417 418 /// Pretty-print region \p MatchedRegion to \p os. 419 /// \return Whether printing succeeded. 420 bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType, 421 const MemRegion *MatchedRegion, 422 const RegionVector &FieldChain, 423 int IndirectionLevel, 424 llvm::raw_svector_ostream &os); 425 426 /// Print first item in the chain, return new separator. 427 static StringRef prettyPrintFirstElement(StringRef FirstElement, 428 bool MoreItemsExpected, 429 int IndirectionLevel, 430 llvm::raw_svector_ostream &os); 431 }; 432 433 } // end of anonymous namespace 434 435 /// \return Whether the method declaration \p Parent 436 /// syntactically has a binary operation writing into the ivar \p Ivar. 437 static bool potentiallyWritesIntoIvar(const Decl *Parent, 438 const ObjCIvarDecl *Ivar) { 439 using namespace ast_matchers; 440 const char *IvarBind = "Ivar"; 441 if (!Parent || !Parent->hasBody()) 442 return false; 443 StatementMatcher WriteIntoIvarM = binaryOperator( 444 hasOperatorName("="), 445 hasLHS(ignoringParenImpCasts( 446 objcIvarRefExpr(hasDeclaration(equalsNode(Ivar))).bind(IvarBind)))); 447 StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM)); 448 auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext()); 449 for (BoundNodes &Match : Matches) { 450 auto IvarRef = Match.getNodeAs<ObjCIvarRefExpr>(IvarBind); 451 if (IvarRef->isFreeIvar()) 452 return true; 453 454 const Expr *Base = IvarRef->getBase(); 455 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Base)) 456 Base = ICE->getSubExpr(); 457 458 if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) 459 if (const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl())) 460 if (ID->getParameterKind() == ImplicitParamDecl::ObjCSelf) 461 return true; 462 463 return false; 464 } 465 return false; 466 } 467 468 /// Get parameters associated with runtime definition in order 469 /// to get the correct parameter name. 470 static ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) { 471 // Use runtime definition, if available. 472 RuntimeDefinition RD = Call->getRuntimeDefinition(); 473 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl())) 474 return FD->parameters(); 475 if (const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl())) 476 return MD->parameters(); 477 478 return Call->parameters(); 479 } 480 481 /// \return whether \p Ty points to a const type, or is a const reference. 482 static bool isPointerToConst(QualType Ty) { 483 return !Ty->getPointeeType().isNull() && 484 Ty->getPointeeType().getCanonicalType().isConstQualified(); 485 } 486 487 /// Attempts to find the region of interest in a given CXX decl, 488 /// by either following the base classes or fields. 489 /// Dereferences fields up to a given recursion limit. 490 /// Note that \p Vec is passed by value, leading to quadratic copying cost, 491 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT. 492 /// \return A chain fields leading to the region of interest or None. 493 const Optional<NoStoreFuncVisitor::RegionVector> 494 NoStoreFuncVisitor::findRegionOfInterestInRecord( 495 const RecordDecl *RD, ProgramStateRef State, const MemRegion *R, 496 const NoStoreFuncVisitor::RegionVector &Vec /* = {} */, 497 int depth /* = 0 */) { 498 499 if (depth == DEREFERENCE_LIMIT) // Limit the recursion depth. 500 return None; 501 502 if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD)) 503 if (!RDX->hasDefinition()) 504 return None; 505 506 // Recursively examine the base classes. 507 // Note that following base classes does not increase the recursion depth. 508 if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD)) 509 for (const auto II : RDX->bases()) 510 if (const RecordDecl *RRD = II.getType()->getAsRecordDecl()) 511 if (Optional<RegionVector> Out = 512 findRegionOfInterestInRecord(RRD, State, R, Vec, depth)) 513 return Out; 514 515 for (const FieldDecl *I : RD->fields()) { 516 QualType FT = I->getType(); 517 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R)); 518 const SVal V = State->getSVal(FR); 519 const MemRegion *VR = V.getAsRegion(); 520 521 RegionVector VecF = Vec; 522 VecF.push_back(FR); 523 524 if (RegionOfInterest == VR) 525 return VecF; 526 527 if (const RecordDecl *RRD = FT->getAsRecordDecl()) 528 if (auto Out = 529 findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1)) 530 return Out; 531 532 QualType PT = FT->getPointeeType(); 533 if (PT.isNull() || PT->isVoidType() || !VR) 534 continue; 535 536 if (const RecordDecl *RRD = PT->getAsRecordDecl()) 537 if (Optional<RegionVector> Out = 538 findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1)) 539 return Out; 540 } 541 542 return None; 543 } 544 545 PathDiagnosticPieceRef NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, 546 BugReporterContext &BR, 547 BugReport &R) { 548 549 const LocationContext *Ctx = N->getLocationContext(); 550 const StackFrameContext *SCtx = Ctx->getStackFrame(); 551 ProgramStateRef State = N->getState(); 552 auto CallExitLoc = N->getLocationAs<CallExitBegin>(); 553 554 // No diagnostic if region was modified inside the frame. 555 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N)) 556 return nullptr; 557 558 CallEventRef<> Call = 559 BR.getStateManager().getCallEventManager().getCaller(SCtx, State); 560 561 // Region of interest corresponds to an IVar, exiting a method 562 // which could have written into that IVar, but did not. 563 if (const auto *MC = dyn_cast<ObjCMethodCall>(Call)) { 564 if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) { 565 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion(); 566 if (RegionOfInterest->isSubRegionOf(SelfRegion) && 567 potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(), 568 IvarR->getDecl())) 569 return maybeEmitNote(R, *Call, N, {}, SelfRegion, "self", 570 /*FirstIsReferenceType=*/false, 1); 571 } 572 } 573 574 if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) { 575 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion(); 576 if (RegionOfInterest->isSubRegionOf(ThisR) && 577 !CCall->getDecl()->isImplicit()) 578 return maybeEmitNote(R, *Call, N, {}, ThisR, "this", 579 /*FirstIsReferenceType=*/false, 1); 580 581 // Do not generate diagnostics for not modified parameters in 582 // constructors. 583 return nullptr; 584 } 585 586 ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call); 587 for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) { 588 const ParmVarDecl *PVD = parameters[I]; 589 SVal V = Call->getArgSVal(I); 590 bool ParamIsReferenceType = PVD->getType()->isReferenceType(); 591 std::string ParamName = PVD->getNameAsString(); 592 593 int IndirectionLevel = 1; 594 QualType T = PVD->getType(); 595 while (const MemRegion *MR = V.getAsRegion()) { 596 if (RegionOfInterest->isSubRegionOf(MR) && !isPointerToConst(T)) 597 return maybeEmitNote(R, *Call, N, {}, MR, ParamName, 598 ParamIsReferenceType, IndirectionLevel); 599 600 QualType PT = T->getPointeeType(); 601 if (PT.isNull() || PT->isVoidType()) 602 break; 603 604 if (const RecordDecl *RD = PT->getAsRecordDecl()) 605 if (Optional<RegionVector> P = 606 findRegionOfInterestInRecord(RD, State, MR)) 607 return maybeEmitNote(R, *Call, N, *P, RegionOfInterest, ParamName, 608 ParamIsReferenceType, IndirectionLevel); 609 610 V = State->getSVal(MR, PT); 611 T = PT; 612 IndirectionLevel++; 613 } 614 } 615 616 return nullptr; 617 } 618 619 void NoStoreFuncVisitor::findModifyingFrames(const ExplodedNode *N) { 620 assert(N->getLocationAs<CallExitBegin>()); 621 ProgramStateRef LastReturnState = N->getState(); 622 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest); 623 const LocationContext *Ctx = N->getLocationContext(); 624 const StackFrameContext *OriginalSCtx = Ctx->getStackFrame(); 625 626 do { 627 ProgramStateRef State = N->getState(); 628 auto CallExitLoc = N->getLocationAs<CallExitBegin>(); 629 if (CallExitLoc) { 630 LastReturnState = State; 631 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest); 632 } 633 634 FramesModifyingCalculated.insert(N->getLocationContext()->getStackFrame()); 635 636 if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) { 637 const StackFrameContext *SCtx = N->getStackFrame(); 638 while (!SCtx->inTopFrame()) { 639 auto p = FramesModifyingRegion.insert(SCtx); 640 if (!p.second) 641 break; // Frame and all its parents already inserted. 642 SCtx = SCtx->getParent()->getStackFrame(); 643 } 644 } 645 646 // Stop calculation at the call to the current function. 647 if (auto CE = N->getLocationAs<CallEnter>()) 648 if (CE->getCalleeContext() == OriginalSCtx) 649 break; 650 651 N = N->getFirstPred(); 652 } while (N); 653 } 654 655 static llvm::StringLiteral WillBeUsedForACondition = 656 ", which participates in a condition later"; 657 658 PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote( 659 BugReport &R, const CallEvent &Call, const ExplodedNode *N, 660 const RegionVector &FieldChain, const MemRegion *MatchedRegion, 661 StringRef FirstElement, bool FirstIsReferenceType, 662 unsigned IndirectionLevel) { 663 // Optimistically suppress uninitialized value bugs that result 664 // from system headers having a chance to initialize the value 665 // but failing to do so. It's too unlikely a system header's fault. 666 // It's much more likely a situation in which the function has a failure 667 // mode that the user decided not to check. If we want to hunt such 668 // omitted checks, we should provide an explicit function-specific note 669 // describing the precondition under which the function isn't supposed to 670 // initialize its out-parameter, and additionally check that such 671 // precondition can actually be fulfilled on the current path. 672 if (Call.isInSystemHeader()) { 673 // We make an exception for system header functions that have no branches. 674 // Such functions unconditionally fail to initialize the variable. 675 // If they call other functions that have more paths within them, 676 // this suppression would still apply when we visit these inner functions. 677 // One common example of a standard function that doesn't ever initialize 678 // its out parameter is operator placement new; it's up to the follow-up 679 // constructor (if any) to initialize the memory. 680 if (!N->getStackFrame()->getCFG()->isLinear()) 681 R.markInvalid(getTag(), nullptr); 682 return nullptr; 683 } 684 685 PathDiagnosticLocation L = 686 PathDiagnosticLocation::create(N->getLocation(), SM); 687 688 // For now this shouldn't trigger, but once it does (as we add more 689 // functions to the body farm), we'll need to decide if these reports 690 // are worth suppressing as well. 691 if (!L.hasValidLocation()) 692 return nullptr; 693 694 SmallString<256> sbuf; 695 llvm::raw_svector_ostream os(sbuf); 696 os << "Returning without writing to '"; 697 698 // Do not generate the note if failed to pretty-print. 699 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion, 700 FieldChain, IndirectionLevel, os)) 701 return nullptr; 702 703 os << "'"; 704 if (TKind == bugreporter::TrackingKind::Condition) 705 os << WillBeUsedForACondition; 706 return std::make_shared<PathDiagnosticEventPiece>(L, os.str()); 707 } 708 709 bool NoStoreFuncVisitor::prettyPrintRegionName(StringRef FirstElement, 710 bool FirstIsReferenceType, 711 const MemRegion *MatchedRegion, 712 const RegionVector &FieldChain, 713 int IndirectionLevel, 714 llvm::raw_svector_ostream &os) { 715 716 if (FirstIsReferenceType) 717 IndirectionLevel--; 718 719 RegionVector RegionSequence; 720 721 // Add the regions in the reverse order, then reverse the resulting array. 722 assert(RegionOfInterest->isSubRegionOf(MatchedRegion)); 723 const MemRegion *R = RegionOfInterest; 724 while (R != MatchedRegion) { 725 RegionSequence.push_back(R); 726 R = cast<SubRegion>(R)->getSuperRegion(); 727 } 728 std::reverse(RegionSequence.begin(), RegionSequence.end()); 729 RegionSequence.append(FieldChain.begin(), FieldChain.end()); 730 731 StringRef Sep; 732 for (const MemRegion *R : RegionSequence) { 733 734 // Just keep going up to the base region. 735 // Element regions may appear due to casts. 736 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R)) 737 continue; 738 739 if (Sep.empty()) 740 Sep = prettyPrintFirstElement(FirstElement, 741 /*MoreItemsExpected=*/true, 742 IndirectionLevel, os); 743 744 os << Sep; 745 746 // Can only reasonably pretty-print DeclRegions. 747 if (!isa<DeclRegion>(R)) 748 return false; 749 750 const auto *DR = cast<DeclRegion>(R); 751 Sep = DR->getValueType()->isAnyPointerType() ? "->" : "."; 752 DR->getDecl()->getDeclName().print(os, PP); 753 } 754 755 if (Sep.empty()) 756 prettyPrintFirstElement(FirstElement, 757 /*MoreItemsExpected=*/false, IndirectionLevel, os); 758 return true; 759 } 760 761 StringRef NoStoreFuncVisitor::prettyPrintFirstElement( 762 StringRef FirstElement, bool MoreItemsExpected, int IndirectionLevel, 763 llvm::raw_svector_ostream &os) { 764 StringRef Out = "."; 765 766 if (IndirectionLevel > 0 && MoreItemsExpected) { 767 IndirectionLevel--; 768 Out = "->"; 769 } 770 771 if (IndirectionLevel > 0 && MoreItemsExpected) 772 os << "("; 773 774 for (int i = 0; i < IndirectionLevel; i++) 775 os << "*"; 776 os << FirstElement; 777 778 if (IndirectionLevel > 0 && MoreItemsExpected) 779 os << ")"; 780 781 return Out; 782 } 783 784 //===----------------------------------------------------------------------===// 785 // Implementation of MacroNullReturnSuppressionVisitor. 786 //===----------------------------------------------------------------------===// 787 788 namespace { 789 790 /// Suppress null-pointer-dereference bugs where dereferenced null was returned 791 /// the macro. 792 class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor { 793 const SubRegion *RegionOfInterest; 794 const SVal ValueAtDereference; 795 796 // Do not invalidate the reports where the value was modified 797 // after it got assigned to from the macro. 798 bool WasModified = false; 799 800 public: 801 MacroNullReturnSuppressionVisitor(const SubRegion *R, const SVal V) 802 : RegionOfInterest(R), ValueAtDereference(V) {} 803 804 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, 805 BugReporterContext &BRC, 806 BugReport &BR) override { 807 if (WasModified) 808 return nullptr; 809 810 auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>(); 811 if (!BugPoint) 812 return nullptr; 813 814 const SourceManager &SMgr = BRC.getSourceManager(); 815 if (auto Loc = matchAssignment(N)) { 816 if (isFunctionMacroExpansion(*Loc, SMgr)) { 817 std::string MacroName = getMacroName(*Loc, BRC); 818 SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc(); 819 if (!BugLoc.isMacroID() || getMacroName(BugLoc, BRC) != MacroName) 820 BR.markInvalid(getTag(), MacroName.c_str()); 821 } 822 } 823 824 if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference)) 825 WasModified = true; 826 827 return nullptr; 828 } 829 830 static void addMacroVisitorIfNecessary( 831 const ExplodedNode *N, const MemRegion *R, 832 bool EnableNullFPSuppression, BugReport &BR, 833 const SVal V) { 834 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options; 835 if (EnableNullFPSuppression && 836 Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>()) 837 BR.addVisitor(std::make_unique<MacroNullReturnSuppressionVisitor>( 838 R->getAs<SubRegion>(), V)); 839 } 840 841 void* getTag() const { 842 static int Tag = 0; 843 return static_cast<void *>(&Tag); 844 } 845 846 void Profile(llvm::FoldingSetNodeID &ID) const override { 847 ID.AddPointer(getTag()); 848 } 849 850 private: 851 /// \return Source location of right hand side of an assignment 852 /// into \c RegionOfInterest, empty optional if none found. 853 Optional<SourceLocation> matchAssignment(const ExplodedNode *N) { 854 const Stmt *S = PathDiagnosticLocation::getStmt(N); 855 ProgramStateRef State = N->getState(); 856 auto *LCtx = N->getLocationContext(); 857 if (!S) 858 return None; 859 860 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 861 if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) 862 if (const Expr *RHS = VD->getInit()) 863 if (RegionOfInterest->isSubRegionOf( 864 State->getLValue(VD, LCtx).getAsRegion())) 865 return RHS->getBeginLoc(); 866 } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) { 867 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion(); 868 const Expr *RHS = BO->getRHS(); 869 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) { 870 return RHS->getBeginLoc(); 871 } 872 } 873 return None; 874 } 875 }; 876 877 } // end of anonymous namespace 878 879 namespace { 880 881 /// Emits an extra note at the return statement of an interesting stack frame. 882 /// 883 /// The returned value is marked as an interesting value, and if it's null, 884 /// adds a visitor to track where it became null. 885 /// 886 /// This visitor is intended to be used when another visitor discovers that an 887 /// interesting value comes from an inlined function call. 888 class ReturnVisitor : public BugReporterVisitor { 889 const StackFrameContext *CalleeSFC; 890 enum { 891 Initial, 892 MaybeUnsuppress, 893 Satisfied 894 } Mode = Initial; 895 896 bool EnableNullFPSuppression; 897 bool ShouldInvalidate = true; 898 AnalyzerOptions& Options; 899 bugreporter::TrackingKind TKind; 900 901 public: 902 ReturnVisitor(const StackFrameContext *Frame, bool Suppressed, 903 AnalyzerOptions &Options, bugreporter::TrackingKind TKind) 904 : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed), 905 Options(Options), TKind(TKind) {} 906 907 static void *getTag() { 908 static int Tag = 0; 909 return static_cast<void *>(&Tag); 910 } 911 912 void Profile(llvm::FoldingSetNodeID &ID) const override { 913 ID.AddPointer(ReturnVisitor::getTag()); 914 ID.AddPointer(CalleeSFC); 915 ID.AddBoolean(EnableNullFPSuppression); 916 } 917 918 /// Adds a ReturnVisitor if the given statement represents a call that was 919 /// inlined. 920 /// 921 /// This will search back through the ExplodedGraph, starting from the given 922 /// node, looking for when the given statement was processed. If it turns out 923 /// the statement is a call that was inlined, we add the visitor to the 924 /// bug report, so it can print a note later. 925 static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S, 926 BugReport &BR, 927 bool InEnableNullFPSuppression, 928 bugreporter::TrackingKind TKind) { 929 if (!CallEvent::isCallStmt(S)) 930 return; 931 932 // First, find when we processed the statement. 933 // If we work with a 'CXXNewExpr' that is going to be purged away before 934 // its call take place. We would catch that purge in the last condition 935 // as a 'StmtPoint' so we have to bypass it. 936 const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S); 937 938 // This is moving forward when we enter into another context. 939 const StackFrameContext *CurrentSFC = Node->getStackFrame(); 940 941 do { 942 // If that is satisfied we found our statement as an inlined call. 943 if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>()) 944 if (CEE->getCalleeContext()->getCallSite() == S) 945 break; 946 947 // Try to move forward to the end of the call-chain. 948 Node = Node->getFirstPred(); 949 if (!Node) 950 break; 951 952 const StackFrameContext *PredSFC = Node->getStackFrame(); 953 954 // If that is satisfied we found our statement. 955 // FIXME: This code currently bypasses the call site for the 956 // conservatively evaluated allocator. 957 if (!BypassCXXNewExprEval) 958 if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>()) 959 // See if we do not enter into another context. 960 if (SP->getStmt() == S && CurrentSFC == PredSFC) 961 break; 962 963 CurrentSFC = PredSFC; 964 } while (Node->getStackFrame() == CurrentSFC); 965 966 // Next, step over any post-statement checks. 967 while (Node && Node->getLocation().getAs<PostStmt>()) 968 Node = Node->getFirstPred(); 969 if (!Node) 970 return; 971 972 // Finally, see if we inlined the call. 973 Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>(); 974 if (!CEE) 975 return; 976 977 const StackFrameContext *CalleeContext = CEE->getCalleeContext(); 978 if (CalleeContext->getCallSite() != S) 979 return; 980 981 // Check the return value. 982 ProgramStateRef State = Node->getState(); 983 SVal RetVal = Node->getSVal(S); 984 985 // Handle cases where a reference is returned and then immediately used. 986 if (cast<Expr>(S)->isGLValue()) 987 if (Optional<Loc> LValue = RetVal.getAs<Loc>()) 988 RetVal = State->getSVal(*LValue); 989 990 // See if the return value is NULL. If so, suppress the report. 991 AnalyzerOptions &Options = State->getAnalysisManager().options; 992 993 bool EnableNullFPSuppression = false; 994 if (InEnableNullFPSuppression && 995 Options.ShouldSuppressNullReturnPaths) 996 if (Optional<Loc> RetLoc = RetVal.getAs<Loc>()) 997 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue(); 998 999 BR.addVisitor(std::make_unique<ReturnVisitor>(CalleeContext, 1000 EnableNullFPSuppression, 1001 Options, TKind)); 1002 } 1003 1004 PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N, 1005 BugReporterContext &BRC, 1006 BugReport &BR) { 1007 // Only print a message at the interesting return statement. 1008 if (N->getLocationContext() != CalleeSFC) 1009 return nullptr; 1010 1011 Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>(); 1012 if (!SP) 1013 return nullptr; 1014 1015 const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); 1016 if (!Ret) 1017 return nullptr; 1018 1019 // Okay, we're at the right return statement, but do we have the return 1020 // value available? 1021 ProgramStateRef State = N->getState(); 1022 SVal V = State->getSVal(Ret, CalleeSFC); 1023 if (V.isUnknownOrUndef()) 1024 return nullptr; 1025 1026 // Don't print any more notes after this one. 1027 Mode = Satisfied; 1028 1029 const Expr *RetE = Ret->getRetValue(); 1030 assert(RetE && "Tracking a return value for a void function"); 1031 1032 // Handle cases where a reference is returned and then immediately used. 1033 Optional<Loc> LValue; 1034 if (RetE->isGLValue()) { 1035 if ((LValue = V.getAs<Loc>())) { 1036 SVal RValue = State->getRawSVal(*LValue, RetE->getType()); 1037 if (RValue.getAs<DefinedSVal>()) 1038 V = RValue; 1039 } 1040 } 1041 1042 // Ignore aggregate rvalues. 1043 if (V.getAs<nonloc::LazyCompoundVal>() || 1044 V.getAs<nonloc::CompoundVal>()) 1045 return nullptr; 1046 1047 RetE = RetE->IgnoreParenCasts(); 1048 1049 // Let's track the return value. 1050 bugreporter::trackExpressionValue( 1051 N, RetE, BR, TKind, EnableNullFPSuppression); 1052 1053 // Build an appropriate message based on the return value. 1054 SmallString<64> Msg; 1055 llvm::raw_svector_ostream Out(Msg); 1056 1057 bool WouldEventBeMeaningless = false; 1058 1059 if (State->isNull(V).isConstrainedTrue()) { 1060 if (V.getAs<Loc>()) { 1061 1062 // If we have counter-suppression enabled, make sure we keep visiting 1063 // future nodes. We want to emit a path note as well, in case 1064 // the report is resurrected as valid later on. 1065 if (EnableNullFPSuppression && 1066 Options.ShouldAvoidSuppressingNullArgumentPaths) 1067 Mode = MaybeUnsuppress; 1068 1069 if (RetE->getType()->isObjCObjectPointerType()) { 1070 Out << "Returning nil"; 1071 } else { 1072 Out << "Returning null pointer"; 1073 } 1074 } else { 1075 Out << "Returning zero"; 1076 } 1077 1078 } else { 1079 if (auto CI = V.getAs<nonloc::ConcreteInt>()) { 1080 Out << "Returning the value " << CI->getValue(); 1081 } else { 1082 // There is nothing interesting about returning a value, when it is 1083 // plain value without any constraints, and the function is guaranteed 1084 // to return that every time. We could use CFG::isLinear() here, but 1085 // constexpr branches are obvious to the compiler, not necesserily to 1086 // the programmer. 1087 if (N->getCFG().size() == 3) 1088 WouldEventBeMeaningless = true; 1089 1090 if (V.getAs<Loc>()) 1091 Out << "Returning pointer"; 1092 else 1093 Out << "Returning value"; 1094 } 1095 } 1096 1097 if (LValue) { 1098 if (const MemRegion *MR = LValue->getAsRegion()) { 1099 if (MR->canPrintPretty()) { 1100 Out << " (reference to "; 1101 MR->printPretty(Out); 1102 Out << ")"; 1103 } 1104 } 1105 } else { 1106 // FIXME: We should have a more generalized location printing mechanism. 1107 if (const auto *DR = dyn_cast<DeclRefExpr>(RetE)) 1108 if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) 1109 Out << " (loaded from '" << *DD << "')"; 1110 } 1111 1112 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), CalleeSFC); 1113 if (!L.isValid() || !L.asLocation().isValid()) 1114 return nullptr; 1115 1116 if (TKind == bugreporter::TrackingKind::Condition) 1117 Out << WillBeUsedForACondition; 1118 1119 auto EventPiece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str()); 1120 1121 // If we determined that the note is meaningless, make it prunable, and 1122 // don't mark the stackframe interesting. 1123 if (WouldEventBeMeaningless) 1124 EventPiece->setPrunable(true); 1125 else 1126 BR.markInteresting(CalleeSFC); 1127 1128 return EventPiece; 1129 } 1130 1131 PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N, 1132 BugReporterContext &BRC, 1133 BugReport &BR) { 1134 #ifndef NDEBUG 1135 assert(Options.ShouldAvoidSuppressingNullArgumentPaths); 1136 #endif 1137 1138 // Are we at the entry node for this call? 1139 Optional<CallEnter> CE = N->getLocationAs<CallEnter>(); 1140 if (!CE) 1141 return nullptr; 1142 1143 if (CE->getCalleeContext() != CalleeSFC) 1144 return nullptr; 1145 1146 Mode = Satisfied; 1147 1148 // Don't automatically suppress a report if one of the arguments is 1149 // known to be a null pointer. Instead, start tracking /that/ null 1150 // value back to its origin. 1151 ProgramStateManager &StateMgr = BRC.getStateManager(); 1152 CallEventManager &CallMgr = StateMgr.getCallEventManager(); 1153 1154 ProgramStateRef State = N->getState(); 1155 CallEventRef<> Call = CallMgr.getCaller(CalleeSFC, State); 1156 for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) { 1157 Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>(); 1158 if (!ArgV) 1159 continue; 1160 1161 const Expr *ArgE = Call->getArgExpr(I); 1162 if (!ArgE) 1163 continue; 1164 1165 // Is it possible for this argument to be non-null? 1166 if (!State->isNull(*ArgV).isConstrainedTrue()) 1167 continue; 1168 1169 if (trackExpressionValue(N, ArgE, BR, TKind, EnableNullFPSuppression)) 1170 ShouldInvalidate = false; 1171 1172 // If we /can't/ track the null pointer, we should err on the side of 1173 // false negatives, and continue towards marking this report invalid. 1174 // (We will still look at the other arguments, though.) 1175 } 1176 1177 return nullptr; 1178 } 1179 1180 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, 1181 BugReporterContext &BRC, 1182 BugReport &BR) override { 1183 switch (Mode) { 1184 case Initial: 1185 return visitNodeInitial(N, BRC, BR); 1186 case MaybeUnsuppress: 1187 return visitNodeMaybeUnsuppress(N, BRC, BR); 1188 case Satisfied: 1189 return nullptr; 1190 } 1191 1192 llvm_unreachable("Invalid visit mode!"); 1193 } 1194 1195 void finalizeVisitor(BugReporterContext &, const ExplodedNode *, 1196 BugReport &BR) override { 1197 if (EnableNullFPSuppression && ShouldInvalidate) 1198 BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC); 1199 } 1200 }; 1201 1202 } // end of anonymous namespace 1203 1204 //===----------------------------------------------------------------------===// 1205 // Implementation of FindLastStoreBRVisitor. 1206 //===----------------------------------------------------------------------===// 1207 1208 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 1209 static int tag = 0; 1210 ID.AddPointer(&tag); 1211 ID.AddPointer(R); 1212 ID.Add(V); 1213 ID.AddInteger(static_cast<int>(TKind)); 1214 ID.AddBoolean(EnableNullFPSuppression); 1215 } 1216 1217 /// Returns true if \p N represents the DeclStmt declaring and initializing 1218 /// \p VR. 1219 static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) { 1220 Optional<PostStmt> P = N->getLocationAs<PostStmt>(); 1221 if (!P) 1222 return false; 1223 1224 const DeclStmt *DS = P->getStmtAs<DeclStmt>(); 1225 if (!DS) 1226 return false; 1227 1228 if (DS->getSingleDecl() != VR->getDecl()) 1229 return false; 1230 1231 const MemSpaceRegion *VarSpace = VR->getMemorySpace(); 1232 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace); 1233 if (!FrameSpace) { 1234 // If we ever directly evaluate global DeclStmts, this assertion will be 1235 // invalid, but this still seems preferable to silently accepting an 1236 // initialization that may be for a path-sensitive variable. 1237 assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion"); 1238 return true; 1239 } 1240 1241 assert(VR->getDecl()->hasLocalStorage()); 1242 const LocationContext *LCtx = N->getLocationContext(); 1243 return FrameSpace->getStackFrame() == LCtx->getStackFrame(); 1244 } 1245 1246 /// Show diagnostics for initializing or declaring a region \p R with a bad value. 1247 static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os, 1248 const MemRegion *R, SVal V, const DeclStmt *DS) { 1249 if (R->canPrintPretty()) { 1250 R->printPretty(os); 1251 os << " "; 1252 } 1253 1254 if (V.getAs<loc::ConcreteInt>()) { 1255 bool b = false; 1256 if (R->isBoundable()) { 1257 if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { 1258 if (TR->getValueType()->isObjCObjectPointerType()) { 1259 os << action << "nil"; 1260 b = true; 1261 } 1262 } 1263 } 1264 if (!b) 1265 os << action << "a null pointer value"; 1266 1267 } else if (auto CVal = V.getAs<nonloc::ConcreteInt>()) { 1268 os << action << CVal->getValue(); 1269 } else if (DS) { 1270 if (V.isUndef()) { 1271 if (isa<VarRegion>(R)) { 1272 const auto *VD = cast<VarDecl>(DS->getSingleDecl()); 1273 if (VD->getInit()) { 1274 os << (R->canPrintPretty() ? "initialized" : "Initializing") 1275 << " to a garbage value"; 1276 } else { 1277 os << (R->canPrintPretty() ? "declared" : "Declaring") 1278 << " without an initial value"; 1279 } 1280 } 1281 } else { 1282 os << (R->canPrintPretty() ? "initialized" : "Initialized") 1283 << " here"; 1284 } 1285 } 1286 } 1287 1288 /// Display diagnostics for passing bad region as a parameter. 1289 static void showBRParamDiagnostics(llvm::raw_svector_ostream& os, 1290 const VarRegion *VR, 1291 SVal V) { 1292 const auto *Param = cast<ParmVarDecl>(VR->getDecl()); 1293 1294 os << "Passing "; 1295 1296 if (V.getAs<loc::ConcreteInt>()) { 1297 if (Param->getType()->isObjCObjectPointerType()) 1298 os << "nil object reference"; 1299 else 1300 os << "null pointer value"; 1301 } else if (V.isUndef()) { 1302 os << "uninitialized value"; 1303 } else if (auto CI = V.getAs<nonloc::ConcreteInt>()) { 1304 os << "the value " << CI->getValue(); 1305 } else { 1306 os << "value"; 1307 } 1308 1309 // Printed parameter indexes are 1-based, not 0-based. 1310 unsigned Idx = Param->getFunctionScopeIndex() + 1; 1311 os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter"; 1312 if (VR->canPrintPretty()) { 1313 os << " "; 1314 VR->printPretty(os); 1315 } 1316 } 1317 1318 /// Show default diagnostics for storing bad region. 1319 static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os, 1320 const MemRegion *R, 1321 SVal V) { 1322 if (V.getAs<loc::ConcreteInt>()) { 1323 bool b = false; 1324 if (R->isBoundable()) { 1325 if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { 1326 if (TR->getValueType()->isObjCObjectPointerType()) { 1327 os << "nil object reference stored"; 1328 b = true; 1329 } 1330 } 1331 } 1332 if (!b) { 1333 if (R->canPrintPretty()) 1334 os << "Null pointer value stored"; 1335 else 1336 os << "Storing null pointer value"; 1337 } 1338 1339 } else if (V.isUndef()) { 1340 if (R->canPrintPretty()) 1341 os << "Uninitialized value stored"; 1342 else 1343 os << "Storing uninitialized value"; 1344 1345 } else if (auto CV = V.getAs<nonloc::ConcreteInt>()) { 1346 if (R->canPrintPretty()) 1347 os << "The value " << CV->getValue() << " is assigned"; 1348 else 1349 os << "Assigning " << CV->getValue(); 1350 1351 } else { 1352 if (R->canPrintPretty()) 1353 os << "Value assigned"; 1354 else 1355 os << "Assigning value"; 1356 } 1357 1358 if (R->canPrintPretty()) { 1359 os << " to "; 1360 R->printPretty(os); 1361 } 1362 } 1363 1364 PathDiagnosticPieceRef 1365 FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, 1366 BugReporterContext &BRC, BugReport &BR) { 1367 if (Satisfied) 1368 return nullptr; 1369 1370 const ExplodedNode *StoreSite = nullptr; 1371 const ExplodedNode *Pred = Succ->getFirstPred(); 1372 const Expr *InitE = nullptr; 1373 bool IsParam = false; 1374 1375 // First see if we reached the declaration of the region. 1376 if (const auto *VR = dyn_cast<VarRegion>(R)) { 1377 if (isInitializationOfVar(Pred, VR)) { 1378 StoreSite = Pred; 1379 InitE = VR->getDecl()->getInit(); 1380 } 1381 } 1382 1383 // If this is a post initializer expression, initializing the region, we 1384 // should track the initializer expression. 1385 if (Optional<PostInitializer> PIP = Pred->getLocationAs<PostInitializer>()) { 1386 const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue(); 1387 if (FieldReg == R) { 1388 StoreSite = Pred; 1389 InitE = PIP->getInitializer()->getInit(); 1390 } 1391 } 1392 1393 // Otherwise, see if this is the store site: 1394 // (1) Succ has this binding and Pred does not, i.e. this is 1395 // where the binding first occurred. 1396 // (2) Succ has this binding and is a PostStore node for this region, i.e. 1397 // the same binding was re-assigned here. 1398 if (!StoreSite) { 1399 if (Succ->getState()->getSVal(R) != V) 1400 return nullptr; 1401 1402 if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) { 1403 Optional<PostStore> PS = Succ->getLocationAs<PostStore>(); 1404 if (!PS || PS->getLocationValue() != R) 1405 return nullptr; 1406 } 1407 1408 StoreSite = Succ; 1409 1410 // If this is an assignment expression, we can track the value 1411 // being assigned. 1412 if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>()) 1413 if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) 1414 if (BO->isAssignmentOp()) 1415 InitE = BO->getRHS(); 1416 1417 // If this is a call entry, the variable should be a parameter. 1418 // FIXME: Handle CXXThisRegion as well. (This is not a priority because 1419 // 'this' should never be NULL, but this visitor isn't just for NULL and 1420 // UndefinedVal.) 1421 if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) { 1422 if (const auto *VR = dyn_cast<VarRegion>(R)) { 1423 1424 const auto *Param = cast<ParmVarDecl>(VR->getDecl()); 1425 1426 ProgramStateManager &StateMgr = BRC.getStateManager(); 1427 CallEventManager &CallMgr = StateMgr.getCallEventManager(); 1428 1429 CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), 1430 Succ->getState()); 1431 InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); 1432 IsParam = true; 1433 } 1434 } 1435 1436 // If this is a CXXTempObjectRegion, the Expr responsible for its creation 1437 // is wrapped inside of it. 1438 if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R)) 1439 InitE = TmpR->getExpr(); 1440 } 1441 1442 if (!StoreSite) 1443 return nullptr; 1444 Satisfied = true; 1445 1446 // If we have an expression that provided the value, try to track where it 1447 // came from. 1448 if (InitE) { 1449 if (!IsParam) 1450 InitE = InitE->IgnoreParenCasts(); 1451 1452 bugreporter::trackExpressionValue( 1453 StoreSite, InitE, BR, TKind, EnableNullFPSuppression); 1454 } 1455 1456 if (TKind == TrackingKind::Condition && 1457 !OriginSFC->isParentOf(StoreSite->getStackFrame())) 1458 return nullptr; 1459 1460 // Okay, we've found the binding. Emit an appropriate message. 1461 SmallString<256> sbuf; 1462 llvm::raw_svector_ostream os(sbuf); 1463 1464 if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) { 1465 const Stmt *S = PS->getStmt(); 1466 const char *action = nullptr; 1467 const auto *DS = dyn_cast<DeclStmt>(S); 1468 const auto *VR = dyn_cast<VarRegion>(R); 1469 1470 if (DS) { 1471 action = R->canPrintPretty() ? "initialized to " : 1472 "Initializing to "; 1473 } else if (isa<BlockExpr>(S)) { 1474 action = R->canPrintPretty() ? "captured by block as " : 1475 "Captured by block as "; 1476 if (VR) { 1477 // See if we can get the BlockVarRegion. 1478 ProgramStateRef State = StoreSite->getState(); 1479 SVal V = StoreSite->getSVal(S); 1480 if (const auto *BDR = 1481 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { 1482 if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { 1483 if (auto KV = State->getSVal(OriginalR).getAs<KnownSVal>()) 1484 BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>( 1485 *KV, OriginalR, EnableNullFPSuppression, TKind, OriginSFC)); 1486 } 1487 } 1488 } 1489 } 1490 if (action) 1491 showBRDiagnostics(action, os, R, V, DS); 1492 1493 } else if (StoreSite->getLocation().getAs<CallEnter>()) { 1494 if (const auto *VR = dyn_cast<VarRegion>(R)) 1495 showBRParamDiagnostics(os, VR, V); 1496 } 1497 1498 if (os.str().empty()) 1499 showBRDefaultDiagnostics(os, R, V); 1500 1501 if (TKind == bugreporter::TrackingKind::Condition) 1502 os << WillBeUsedForACondition; 1503 1504 // Construct a new PathDiagnosticPiece. 1505 ProgramPoint P = StoreSite->getLocation(); 1506 PathDiagnosticLocation L; 1507 if (P.getAs<CallEnter>() && InitE) 1508 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(), 1509 P.getLocationContext()); 1510 1511 if (!L.isValid() || !L.asLocation().isValid()) 1512 L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); 1513 1514 if (!L.isValid() || !L.asLocation().isValid()) 1515 return nullptr; 1516 1517 return std::make_shared<PathDiagnosticEventPiece>(L, os.str()); 1518 } 1519 1520 //===----------------------------------------------------------------------===// 1521 // Implementation of TrackConstraintBRVisitor. 1522 //===----------------------------------------------------------------------===// 1523 1524 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 1525 static int tag = 0; 1526 ID.AddPointer(&tag); 1527 ID.AddBoolean(Assumption); 1528 ID.Add(Constraint); 1529 } 1530 1531 /// Return the tag associated with this visitor. This tag will be used 1532 /// to make all PathDiagnosticPieces created by this visitor. 1533 const char *TrackConstraintBRVisitor::getTag() { 1534 return "TrackConstraintBRVisitor"; 1535 } 1536 1537 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const { 1538 if (IsZeroCheck) 1539 return N->getState()->isNull(Constraint).isUnderconstrained(); 1540 return (bool)N->getState()->assume(Constraint, !Assumption); 1541 } 1542 1543 PathDiagnosticPieceRef 1544 TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 1545 BugReporterContext &BRC, BugReport &) { 1546 const ExplodedNode *PrevN = N->getFirstPred(); 1547 if (IsSatisfied) 1548 return nullptr; 1549 1550 // Start tracking after we see the first state in which the value is 1551 // constrained. 1552 if (!IsTrackingTurnedOn) 1553 if (!isUnderconstrained(N)) 1554 IsTrackingTurnedOn = true; 1555 if (!IsTrackingTurnedOn) 1556 return nullptr; 1557 1558 // Check if in the previous state it was feasible for this constraint 1559 // to *not* be true. 1560 if (isUnderconstrained(PrevN)) { 1561 IsSatisfied = true; 1562 1563 // As a sanity check, make sure that the negation of the constraint 1564 // was infeasible in the current state. If it is feasible, we somehow 1565 // missed the transition point. 1566 assert(!isUnderconstrained(N)); 1567 1568 // We found the transition point for the constraint. We now need to 1569 // pretty-print the constraint. (work-in-progress) 1570 SmallString<64> sbuf; 1571 llvm::raw_svector_ostream os(sbuf); 1572 1573 if (Constraint.getAs<Loc>()) { 1574 os << "Assuming pointer value is "; 1575 os << (Assumption ? "non-null" : "null"); 1576 } 1577 1578 if (os.str().empty()) 1579 return nullptr; 1580 1581 // Construct a new PathDiagnosticPiece. 1582 ProgramPoint P = N->getLocation(); 1583 PathDiagnosticLocation L = 1584 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 1585 if (!L.isValid()) 1586 return nullptr; 1587 1588 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str()); 1589 X->setTag(getTag()); 1590 return std::move(X); 1591 } 1592 1593 return nullptr; 1594 } 1595 1596 //===----------------------------------------------------------------------===// 1597 // Implementation of SuppressInlineDefensiveChecksVisitor. 1598 //===----------------------------------------------------------------------===// 1599 1600 SuppressInlineDefensiveChecksVisitor:: 1601 SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) 1602 : V(Value) { 1603 // Check if the visitor is disabled. 1604 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options; 1605 if (!Options.ShouldSuppressInlinedDefensiveChecks) 1606 IsSatisfied = true; 1607 1608 assert(N->getState()->isNull(V).isConstrainedTrue() && 1609 "The visitor only tracks the cases where V is constrained to 0"); 1610 } 1611 1612 void SuppressInlineDefensiveChecksVisitor::Profile( 1613 llvm::FoldingSetNodeID &ID) const { 1614 static int id = 0; 1615 ID.AddPointer(&id); 1616 ID.Add(V); 1617 } 1618 1619 const char *SuppressInlineDefensiveChecksVisitor::getTag() { 1620 return "IDCVisitor"; 1621 } 1622 1623 PathDiagnosticPieceRef SuppressInlineDefensiveChecksVisitor::VisitNode( 1624 const ExplodedNode *Succ, BugReporterContext &BRC, BugReport &BR) { 1625 const ExplodedNode *Pred = Succ->getFirstPred(); 1626 if (IsSatisfied) 1627 return nullptr; 1628 1629 // Start tracking after we see the first state in which the value is null. 1630 if (!IsTrackingTurnedOn) 1631 if (Succ->getState()->isNull(V).isConstrainedTrue()) 1632 IsTrackingTurnedOn = true; 1633 if (!IsTrackingTurnedOn) 1634 return nullptr; 1635 1636 // Check if in the previous state it was feasible for this value 1637 // to *not* be null. 1638 if (!Pred->getState()->isNull(V).isConstrainedTrue()) { 1639 IsSatisfied = true; 1640 1641 assert(Succ->getState()->isNull(V).isConstrainedTrue()); 1642 1643 // Check if this is inlined defensive checks. 1644 const LocationContext *CurLC =Succ->getLocationContext(); 1645 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext(); 1646 if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) { 1647 BR.markInvalid("Suppress IDC", CurLC); 1648 return nullptr; 1649 } 1650 1651 // Treat defensive checks in function-like macros as if they were an inlined 1652 // defensive check. If the bug location is not in a macro and the 1653 // terminator for the current location is in a macro then suppress the 1654 // warning. 1655 auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>(); 1656 1657 if (!BugPoint) 1658 return nullptr; 1659 1660 ProgramPoint CurPoint = Succ->getLocation(); 1661 const Stmt *CurTerminatorStmt = nullptr; 1662 if (auto BE = CurPoint.getAs<BlockEdge>()) { 1663 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt(); 1664 } else if (auto SP = CurPoint.getAs<StmtPoint>()) { 1665 const Stmt *CurStmt = SP->getStmt(); 1666 if (!CurStmt->getBeginLoc().isMacroID()) 1667 return nullptr; 1668 1669 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap(); 1670 CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt(); 1671 } else { 1672 return nullptr; 1673 } 1674 1675 if (!CurTerminatorStmt) 1676 return nullptr; 1677 1678 SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc(); 1679 if (TerminatorLoc.isMacroID()) { 1680 SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc(); 1681 1682 // Suppress reports unless we are in that same macro. 1683 if (!BugLoc.isMacroID() || 1684 getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) { 1685 BR.markInvalid("Suppress Macro IDC", CurLC); 1686 } 1687 return nullptr; 1688 } 1689 } 1690 return nullptr; 1691 } 1692 1693 //===----------------------------------------------------------------------===// 1694 // TrackControlDependencyCondBRVisitor. 1695 //===----------------------------------------------------------------------===// 1696 1697 namespace { 1698 /// Tracks the expressions that are a control dependency of the node that was 1699 /// supplied to the constructor. 1700 /// For example: 1701 /// 1702 /// cond = 1; 1703 /// if (cond) 1704 /// 10 / 0; 1705 /// 1706 /// An error is emitted at line 3. This visitor realizes that the branch 1707 /// on line 2 is a control dependency of line 3, and tracks it's condition via 1708 /// trackExpressionValue(). 1709 class TrackControlDependencyCondBRVisitor final : public BugReporterVisitor { 1710 const ExplodedNode *Origin; 1711 ControlDependencyCalculator ControlDeps; 1712 llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks; 1713 1714 public: 1715 TrackControlDependencyCondBRVisitor(const ExplodedNode *O) 1716 : Origin(O), ControlDeps(&O->getCFG()) {} 1717 1718 void Profile(llvm::FoldingSetNodeID &ID) const override { 1719 static int x = 0; 1720 ID.AddPointer(&x); 1721 } 1722 1723 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, 1724 BugReporterContext &BRC, 1725 BugReport &BR) override; 1726 }; 1727 } // end of anonymous namespace 1728 1729 static std::shared_ptr<PathDiagnosticEventPiece> 1730 constructDebugPieceForTrackedCondition(const Expr *Cond, 1731 const ExplodedNode *N, 1732 BugReporterContext &BRC) { 1733 1734 if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE || 1735 !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug) 1736 return nullptr; 1737 1738 std::string ConditionText = Lexer::getSourceText( 1739 CharSourceRange::getTokenRange(Cond->getSourceRange()), 1740 BRC.getSourceManager(), 1741 BRC.getASTContext().getLangOpts()); 1742 1743 return std::make_shared<PathDiagnosticEventPiece>( 1744 PathDiagnosticLocation::createBegin( 1745 Cond, BRC.getSourceManager(), N->getLocationContext()), 1746 (Twine() + "Tracking condition '" + ConditionText + "'").str()); 1747 } 1748 1749 static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) { 1750 if (B->succ_size() != 2) 1751 return false; 1752 1753 const CFGBlock *Then = B->succ_begin()->getReachableBlock(); 1754 const CFGBlock *Else = (B->succ_begin() + 1)->getReachableBlock(); 1755 1756 if (!Then || !Else) 1757 return false; 1758 1759 if (Then->isInevitablySinking() != Else->isInevitablySinking()) 1760 return true; 1761 1762 // For the following condition the following CFG would be built: 1763 // 1764 // -------------> 1765 // / \ 1766 // [B1] -> [B2] -> [B3] -> [sink] 1767 // assert(A && B || C); \ \ 1768 // -----------> [go on with the execution] 1769 // 1770 // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block 1771 // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we 1772 // reached the end of the condition! 1773 if (const Stmt *ElseCond = Else->getTerminatorCondition()) 1774 if (const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond)) 1775 if (BinOp->isLogicalOp()) 1776 return isAssertlikeBlock(Else, Context); 1777 1778 return false; 1779 } 1780 1781 PathDiagnosticPieceRef TrackControlDependencyCondBRVisitor::VisitNode( 1782 const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { 1783 // We can only reason about control dependencies within the same stack frame. 1784 if (Origin->getStackFrame() != N->getStackFrame()) 1785 return nullptr; 1786 1787 CFGBlock *NB = const_cast<CFGBlock *>(N->getCFGBlock()); 1788 1789 // Skip if we already inspected this block. 1790 if (!VisitedBlocks.insert(NB).second) 1791 return nullptr; 1792 1793 CFGBlock *OriginB = const_cast<CFGBlock *>(Origin->getCFGBlock()); 1794 1795 // TODO: Cache CFGBlocks for each ExplodedNode. 1796 if (!OriginB || !NB) 1797 return nullptr; 1798 1799 if (isAssertlikeBlock(NB, BRC.getASTContext())) 1800 return nullptr; 1801 1802 if (ControlDeps.isControlDependent(OriginB, NB)) { 1803 if (const Expr *Condition = NB->getLastCondition()) { 1804 // Keeping track of the already tracked conditions on a visitor level 1805 // isn't sufficient, because a new visitor is created for each tracked 1806 // expression, hence the BugReport level set. 1807 if (BR.addTrackedCondition(N)) { 1808 bugreporter::trackExpressionValue( 1809 N, Condition, BR, bugreporter::TrackingKind::Condition, 1810 /*EnableNullFPSuppression=*/false); 1811 return constructDebugPieceForTrackedCondition(Condition, N, BRC); 1812 } 1813 } 1814 } 1815 1816 return nullptr; 1817 } 1818 1819 //===----------------------------------------------------------------------===// 1820 // Implementation of trackExpressionValue. 1821 //===----------------------------------------------------------------------===// 1822 1823 static const MemRegion *getLocationRegionIfReference(const Expr *E, 1824 const ExplodedNode *N) { 1825 if (const auto *DR = dyn_cast<DeclRefExpr>(E)) { 1826 if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) { 1827 if (!VD->getType()->isReferenceType()) 1828 return nullptr; 1829 ProgramStateManager &StateMgr = N->getState()->getStateManager(); 1830 MemRegionManager &MRMgr = StateMgr.getRegionManager(); 1831 return MRMgr.getVarRegion(VD, N->getLocationContext()); 1832 } 1833 } 1834 1835 // FIXME: This does not handle other kinds of null references, 1836 // for example, references from FieldRegions: 1837 // struct Wrapper { int &ref; }; 1838 // Wrapper w = { *(int *)0 }; 1839 // w.ref = 1; 1840 1841 return nullptr; 1842 } 1843 1844 /// \return A subexpression of {@code Ex} which represents the 1845 /// expression-of-interest. 1846 static const Expr *peelOffOuterExpr(const Expr *Ex, 1847 const ExplodedNode *N) { 1848 Ex = Ex->IgnoreParenCasts(); 1849 if (const auto *FE = dyn_cast<FullExpr>(Ex)) 1850 return peelOffOuterExpr(FE->getSubExpr(), N); 1851 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex)) 1852 return peelOffOuterExpr(OVE->getSourceExpr(), N); 1853 if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) { 1854 const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); 1855 if (PropRef && PropRef->isMessagingGetter()) { 1856 const Expr *GetterMessageSend = 1857 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1); 1858 assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts())); 1859 return peelOffOuterExpr(GetterMessageSend, N); 1860 } 1861 } 1862 1863 // Peel off the ternary operator. 1864 if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) { 1865 // Find a node where the branching occurred and find out which branch 1866 // we took (true/false) by looking at the ExplodedGraph. 1867 const ExplodedNode *NI = N; 1868 do { 1869 ProgramPoint ProgPoint = NI->getLocation(); 1870 if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) { 1871 const CFGBlock *srcBlk = BE->getSrc(); 1872 if (const Stmt *term = srcBlk->getTerminatorStmt()) { 1873 if (term == CO) { 1874 bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst()); 1875 if (TookTrueBranch) 1876 return peelOffOuterExpr(CO->getTrueExpr(), N); 1877 else 1878 return peelOffOuterExpr(CO->getFalseExpr(), N); 1879 } 1880 } 1881 } 1882 NI = NI->getFirstPred(); 1883 } while (NI); 1884 } 1885 1886 if (auto *BO = dyn_cast<BinaryOperator>(Ex)) 1887 if (const Expr *SubEx = peelOffPointerArithmetic(BO)) 1888 return peelOffOuterExpr(SubEx, N); 1889 1890 if (auto *UO = dyn_cast<UnaryOperator>(Ex)) { 1891 if (UO->getOpcode() == UO_LNot) 1892 return peelOffOuterExpr(UO->getSubExpr(), N); 1893 1894 // FIXME: There's a hack in our Store implementation that always computes 1895 // field offsets around null pointers as if they are always equal to 0. 1896 // The idea here is to report accesses to fields as null dereferences 1897 // even though the pointer value that's being dereferenced is actually 1898 // the offset of the field rather than exactly 0. 1899 // See the FIXME in StoreManager's getLValueFieldOrIvar() method. 1900 // This code interacts heavily with this hack; otherwise the value 1901 // would not be null at all for most fields, so we'd be unable to track it. 1902 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue()) 1903 if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr())) 1904 return peelOffOuterExpr(DerefEx, N); 1905 } 1906 1907 return Ex; 1908 } 1909 1910 /// Find the ExplodedNode where the lvalue (the value of 'Ex') 1911 /// was computed. 1912 static const ExplodedNode* findNodeForExpression(const ExplodedNode *N, 1913 const Expr *Inner) { 1914 while (N) { 1915 if (PathDiagnosticLocation::getStmt(N) == Inner) 1916 return N; 1917 N = N->getFirstPred(); 1918 } 1919 return N; 1920 } 1921 1922 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode, 1923 const Expr *E, BugReport &report, 1924 bugreporter::TrackingKind TKind, 1925 bool EnableNullFPSuppression) { 1926 1927 if (!E || !InputNode) 1928 return false; 1929 1930 const Expr *Inner = peelOffOuterExpr(E, InputNode); 1931 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner); 1932 if (!LVNode) 1933 return false; 1934 1935 ProgramStateRef LVState = LVNode->getState(); 1936 const StackFrameContext *SFC = LVNode->getStackFrame(); 1937 1938 // We only track expressions if we believe that they are important. Chances 1939 // are good that control dependencies to the tracking point are also improtant 1940 // because of this, let's explain why we believe control reached this point. 1941 // TODO: Shouldn't we track control dependencies of every bug location, rather 1942 // than only tracked expressions? 1943 if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions) 1944 report.addVisitor(std::make_unique<TrackControlDependencyCondBRVisitor>( 1945 InputNode)); 1946 1947 // The message send could be nil due to the receiver being nil. 1948 // At this point in the path, the receiver should be live since we are at the 1949 // message send expr. If it is nil, start tracking it. 1950 if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode)) 1951 trackExpressionValue( 1952 LVNode, Receiver, report, TKind, EnableNullFPSuppression); 1953 1954 // Track the index if this is an array subscript. 1955 if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner)) 1956 trackExpressionValue( 1957 LVNode, Arr->getIdx(), report, TKind, /*EnableNullFPSuppression*/false); 1958 1959 // See if the expression we're interested refers to a variable. 1960 // If so, we can track both its contents and constraints on its value. 1961 if (ExplodedGraph::isInterestingLValueExpr(Inner)) { 1962 SVal LVal = LVNode->getSVal(Inner); 1963 1964 const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode); 1965 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue(); 1966 1967 // If this is a C++ reference to a null pointer, we are tracking the 1968 // pointer. In addition, we should find the store at which the reference 1969 // got initialized. 1970 if (RR && !LVIsNull) 1971 if (auto KV = LVal.getAs<KnownSVal>()) 1972 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>( 1973 *KV, RR, EnableNullFPSuppression, TKind, SFC)); 1974 1975 // In case of C++ references, we want to differentiate between a null 1976 // reference and reference to null pointer. 1977 // If the LVal is null, check if we are dealing with null reference. 1978 // For those, we want to track the location of the reference. 1979 const MemRegion *R = (RR && LVIsNull) ? RR : 1980 LVNode->getSVal(Inner).getAsRegion(); 1981 1982 if (R) { 1983 1984 // Mark both the variable region and its contents as interesting. 1985 SVal V = LVState->getRawSVal(loc::MemRegionVal(R)); 1986 report.addVisitor( 1987 std::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R), TKind)); 1988 1989 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary( 1990 LVNode, R, EnableNullFPSuppression, report, V); 1991 1992 report.markInteresting(V, TKind); 1993 report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(R)); 1994 1995 // If the contents are symbolic, find out when they became null. 1996 if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true)) 1997 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>( 1998 V.castAs<DefinedSVal>(), false)); 1999 2000 // Add visitor, which will suppress inline defensive checks. 2001 if (auto DV = V.getAs<DefinedSVal>()) 2002 if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() && 2003 EnableNullFPSuppression) 2004 report.addVisitor( 2005 std::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV, 2006 LVNode)); 2007 2008 if (auto KV = V.getAs<KnownSVal>()) 2009 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>( 2010 *KV, R, EnableNullFPSuppression, TKind, SFC)); 2011 return true; 2012 } 2013 } 2014 2015 // If the expression is not an "lvalue expression", we can still 2016 // track the constraints on its contents. 2017 SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext()); 2018 2019 ReturnVisitor::addVisitorIfNecessary( 2020 LVNode, Inner, report, EnableNullFPSuppression, TKind); 2021 2022 // Is it a symbolic value? 2023 if (auto L = V.getAs<loc::MemRegionVal>()) { 2024 report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(L->getRegion())); 2025 2026 // FIXME: this is a hack for fixing a later crash when attempting to 2027 // dereference a void* pointer. 2028 // We should not try to dereference pointers at all when we don't care 2029 // what is written inside the pointer. 2030 bool CanDereference = true; 2031 if (const auto *SR = L->getRegionAs<SymbolicRegion>()) { 2032 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType()) 2033 CanDereference = false; 2034 } else if (L->getRegionAs<AllocaRegion>()) 2035 CanDereference = false; 2036 2037 // At this point we are dealing with the region's LValue. 2038 // However, if the rvalue is a symbolic region, we should track it as well. 2039 // Try to use the correct type when looking up the value. 2040 SVal RVal; 2041 if (ExplodedGraph::isInterestingLValueExpr(Inner)) 2042 RVal = LVState->getRawSVal(L.getValue(), Inner->getType()); 2043 else if (CanDereference) 2044 RVal = LVState->getSVal(L->getRegion()); 2045 2046 if (CanDereference) 2047 if (auto KV = RVal.getAs<KnownSVal>()) 2048 report.addVisitor(std::make_unique<FindLastStoreBRVisitor>( 2049 *KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC)); 2050 2051 const MemRegion *RegionRVal = RVal.getAsRegion(); 2052 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { 2053 report.markInteresting(RegionRVal, TKind); 2054 report.addVisitor(std::make_unique<TrackConstraintBRVisitor>( 2055 loc::MemRegionVal(RegionRVal), /*assumption=*/false)); 2056 } 2057 } 2058 return true; 2059 } 2060 2061 //===----------------------------------------------------------------------===// 2062 // Implementation of NulReceiverBRVisitor. 2063 //===----------------------------------------------------------------------===// 2064 2065 const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S, 2066 const ExplodedNode *N) { 2067 const auto *ME = dyn_cast<ObjCMessageExpr>(S); 2068 if (!ME) 2069 return nullptr; 2070 if (const Expr *Receiver = ME->getInstanceReceiver()) { 2071 ProgramStateRef state = N->getState(); 2072 SVal V = N->getSVal(Receiver); 2073 if (state->isNull(V).isConstrainedTrue()) 2074 return Receiver; 2075 } 2076 return nullptr; 2077 } 2078 2079 PathDiagnosticPieceRef NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 2080 BugReporterContext &BRC, 2081 BugReport &BR) { 2082 Optional<PreStmt> P = N->getLocationAs<PreStmt>(); 2083 if (!P) 2084 return nullptr; 2085 2086 const Stmt *S = P->getStmt(); 2087 const Expr *Receiver = getNilReceiver(S, N); 2088 if (!Receiver) 2089 return nullptr; 2090 2091 llvm::SmallString<256> Buf; 2092 llvm::raw_svector_ostream OS(Buf); 2093 2094 if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) { 2095 OS << "'"; 2096 ME->getSelector().print(OS); 2097 OS << "' not called"; 2098 } 2099 else { 2100 OS << "No method is called"; 2101 } 2102 OS << " because the receiver is nil"; 2103 2104 // The receiver was nil, and hence the method was skipped. 2105 // Register a BugReporterVisitor to issue a message telling us how 2106 // the receiver was null. 2107 bugreporter::trackExpressionValue( 2108 N, Receiver, BR, bugreporter::TrackingKind::Thorough, 2109 /*EnableNullFPSuppression*/ false); 2110 // Issue a message saying that the method was skipped. 2111 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 2112 N->getLocationContext()); 2113 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str()); 2114 } 2115 2116 //===----------------------------------------------------------------------===// 2117 // Visitor that tries to report interesting diagnostics from conditions. 2118 //===----------------------------------------------------------------------===// 2119 2120 /// Return the tag associated with this visitor. This tag will be used 2121 /// to make all PathDiagnosticPieces created by this visitor. 2122 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; } 2123 2124 PathDiagnosticPieceRef ConditionBRVisitor::VisitNode(const ExplodedNode *N, 2125 BugReporterContext &BRC, 2126 BugReport &BR) { 2127 auto piece = VisitNodeImpl(N, BRC, BR); 2128 if (piece) { 2129 piece->setTag(getTag()); 2130 if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get())) 2131 ev->setPrunable(true, /* override */ false); 2132 } 2133 return piece; 2134 } 2135 2136 PathDiagnosticPieceRef 2137 ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 2138 BugReporterContext &BRC, BugReport &BR) { 2139 ProgramPoint ProgPoint = N->getLocation(); 2140 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags = 2141 ExprEngine::geteagerlyAssumeBinOpBifurcationTags(); 2142 2143 // If an assumption was made on a branch, it should be caught 2144 // here by looking at the state transition. 2145 if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) { 2146 const CFGBlock *SrcBlock = BE->getSrc(); 2147 if (const Stmt *Term = SrcBlock->getTerminatorStmt()) { 2148 // If the tag of the previous node is 'Eagerly Assume...' the current 2149 // 'BlockEdge' has the same constraint information. We do not want to 2150 // report the value as it is just an assumption on the predecessor node 2151 // which will be caught in the next VisitNode() iteration as a 'PostStmt'. 2152 const ProgramPointTag *PreviousNodeTag = 2153 N->getFirstPred()->getLocation().getTag(); 2154 if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second) 2155 return nullptr; 2156 2157 return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC); 2158 } 2159 return nullptr; 2160 } 2161 2162 if (Optional<PostStmt> PS = ProgPoint.getAs<PostStmt>()) { 2163 const ProgramPointTag *CurrentNodeTag = PS->getTag(); 2164 if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second) 2165 return nullptr; 2166 2167 bool TookTrue = CurrentNodeTag == Tags.first; 2168 return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue); 2169 } 2170 2171 return nullptr; 2172 } 2173 2174 PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator( 2175 const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk, 2176 const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) { 2177 const Expr *Cond = nullptr; 2178 2179 // In the code below, Term is a CFG terminator and Cond is a branch condition 2180 // expression upon which the decision is made on this terminator. 2181 // 2182 // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator, 2183 // and "x == 0" is the respective condition. 2184 // 2185 // Another example: in "if (x && y)", we've got two terminators and two 2186 // conditions due to short-circuit nature of operator "&&": 2187 // 1. The "if (x && y)" statement is a terminator, 2188 // and "y" is the respective condition. 2189 // 2. Also "x && ..." is another terminator, 2190 // and "x" is its condition. 2191 2192 switch (Term->getStmtClass()) { 2193 // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit 2194 // more tricky because there are more than two branches to account for. 2195 default: 2196 return nullptr; 2197 case Stmt::IfStmtClass: 2198 Cond = cast<IfStmt>(Term)->getCond(); 2199 break; 2200 case Stmt::ConditionalOperatorClass: 2201 Cond = cast<ConditionalOperator>(Term)->getCond(); 2202 break; 2203 case Stmt::BinaryOperatorClass: 2204 // When we encounter a logical operator (&& or ||) as a CFG terminator, 2205 // then the condition is actually its LHS; otherwise, we'd encounter 2206 // the parent, such as if-statement, as a terminator. 2207 const auto *BO = cast<BinaryOperator>(Term); 2208 assert(BO->isLogicalOp() && 2209 "CFG terminator is not a short-circuit operator!"); 2210 Cond = BO->getLHS(); 2211 break; 2212 } 2213 2214 Cond = Cond->IgnoreParens(); 2215 2216 // However, when we encounter a logical operator as a branch condition, 2217 // then the condition is actually its RHS, because LHS would be 2218 // the condition for the logical operator terminator. 2219 while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) { 2220 if (!InnerBO->isLogicalOp()) 2221 break; 2222 Cond = InnerBO->getRHS()->IgnoreParens(); 2223 } 2224 2225 assert(Cond); 2226 assert(srcBlk->succ_size() == 2); 2227 const bool TookTrue = *(srcBlk->succ_begin()) == dstBlk; 2228 return VisitTrueTest(Cond, BRC, R, N, TookTrue); 2229 } 2230 2231 PathDiagnosticPieceRef 2232 ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, 2233 BugReport &R, const ExplodedNode *N, 2234 bool TookTrue) { 2235 ProgramStateRef CurrentState = N->getState(); 2236 ProgramStateRef PrevState = N->getFirstPred()->getState(); 2237 const LocationContext *LCtx = N->getLocationContext(); 2238 2239 // If the constraint information is changed between the current and the 2240 // previous program state we assuming the newly seen constraint information. 2241 // If we cannot evaluate the condition (and the constraints are the same) 2242 // the analyzer has no information about the value and just assuming it. 2243 bool IsAssuming = 2244 !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) || 2245 CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef(); 2246 2247 // These will be modified in code below, but we need to preserve the original 2248 // values in case we want to throw the generic message. 2249 const Expr *CondTmp = Cond; 2250 bool TookTrueTmp = TookTrue; 2251 2252 while (true) { 2253 CondTmp = CondTmp->IgnoreParenCasts(); 2254 switch (CondTmp->getStmtClass()) { 2255 default: 2256 break; 2257 case Stmt::BinaryOperatorClass: 2258 if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp), 2259 BRC, R, N, TookTrueTmp, IsAssuming)) 2260 return P; 2261 break; 2262 case Stmt::DeclRefExprClass: 2263 if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp), 2264 BRC, R, N, TookTrueTmp, IsAssuming)) 2265 return P; 2266 break; 2267 case Stmt::MemberExprClass: 2268 if (auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp), 2269 BRC, R, N, TookTrueTmp, IsAssuming)) 2270 return P; 2271 break; 2272 case Stmt::UnaryOperatorClass: { 2273 const auto *UO = cast<UnaryOperator>(CondTmp); 2274 if (UO->getOpcode() == UO_LNot) { 2275 TookTrueTmp = !TookTrueTmp; 2276 CondTmp = UO->getSubExpr(); 2277 continue; 2278 } 2279 break; 2280 } 2281 } 2282 break; 2283 } 2284 2285 // Condition too complex to explain? Just say something so that the user 2286 // knew we've made some path decision at this point. 2287 // If it is too complex and we know the evaluation of the condition do not 2288 // repeat the note from 'BugReporter.cpp' 2289 if (!IsAssuming) 2290 return nullptr; 2291 2292 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 2293 if (!Loc.isValid() || !Loc.asLocation().isValid()) 2294 return nullptr; 2295 2296 return std::make_shared<PathDiagnosticEventPiece>( 2297 Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage); 2298 } 2299 2300 bool ConditionBRVisitor::patternMatch(const Expr *Ex, 2301 const Expr *ParentEx, 2302 raw_ostream &Out, 2303 BugReporterContext &BRC, 2304 BugReport &report, 2305 const ExplodedNode *N, 2306 Optional<bool> &prunable, 2307 bool IsSameFieldName) { 2308 const Expr *OriginalExpr = Ex; 2309 Ex = Ex->IgnoreParenCasts(); 2310 2311 if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) || 2312 isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) || 2313 isa<FloatingLiteral>(Ex)) { 2314 // Use heuristics to determine if the expression is a macro 2315 // expanding to a literal and if so, use the macro's name. 2316 SourceLocation BeginLoc = OriginalExpr->getBeginLoc(); 2317 SourceLocation EndLoc = OriginalExpr->getEndLoc(); 2318 if (BeginLoc.isMacroID() && EndLoc.isMacroID()) { 2319 const SourceManager &SM = BRC.getSourceManager(); 2320 const LangOptions &LO = BRC.getASTContext().getLangOpts(); 2321 if (Lexer::isAtStartOfMacroExpansion(BeginLoc, SM, LO) && 2322 Lexer::isAtEndOfMacroExpansion(EndLoc, SM, LO)) { 2323 CharSourceRange R = Lexer::getAsCharRange({BeginLoc, EndLoc}, SM, LO); 2324 Out << Lexer::getSourceText(R, SM, LO); 2325 return false; 2326 } 2327 } 2328 } 2329 2330 if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) { 2331 const bool quotes = isa<VarDecl>(DR->getDecl()); 2332 if (quotes) { 2333 Out << '\''; 2334 const LocationContext *LCtx = N->getLocationContext(); 2335 const ProgramState *state = N->getState().get(); 2336 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 2337 LCtx).getAsRegion()) { 2338 if (report.isInteresting(R)) 2339 prunable = false; 2340 else { 2341 const ProgramState *state = N->getState().get(); 2342 SVal V = state->getSVal(R); 2343 if (report.isInteresting(V)) 2344 prunable = false; 2345 } 2346 } 2347 } 2348 Out << DR->getDecl()->getDeclName().getAsString(); 2349 if (quotes) 2350 Out << '\''; 2351 return quotes; 2352 } 2353 2354 if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) { 2355 QualType OriginalTy = OriginalExpr->getType(); 2356 if (OriginalTy->isPointerType()) { 2357 if (IL->getValue() == 0) { 2358 Out << "null"; 2359 return false; 2360 } 2361 } 2362 else if (OriginalTy->isObjCObjectPointerType()) { 2363 if (IL->getValue() == 0) { 2364 Out << "nil"; 2365 return false; 2366 } 2367 } 2368 2369 Out << IL->getValue(); 2370 return false; 2371 } 2372 2373 if (const auto *ME = dyn_cast<MemberExpr>(Ex)) { 2374 if (!IsSameFieldName) 2375 Out << "field '" << ME->getMemberDecl()->getName() << '\''; 2376 else 2377 Out << '\'' 2378 << Lexer::getSourceText( 2379 CharSourceRange::getTokenRange(Ex->getSourceRange()), 2380 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0) 2381 << '\''; 2382 } 2383 2384 return false; 2385 } 2386 2387 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( 2388 const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC, 2389 BugReport &R, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { 2390 bool shouldInvert = false; 2391 Optional<bool> shouldPrune; 2392 2393 // Check if the field name of the MemberExprs is ambiguous. Example: 2394 // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'. 2395 bool IsSameFieldName = false; 2396 const auto *LhsME = dyn_cast<MemberExpr>(BExpr->getLHS()->IgnoreParenCasts()); 2397 const auto *RhsME = dyn_cast<MemberExpr>(BExpr->getRHS()->IgnoreParenCasts()); 2398 2399 if (LhsME && RhsME) 2400 IsSameFieldName = 2401 LhsME->getMemberDecl()->getName() == RhsME->getMemberDecl()->getName(); 2402 2403 SmallString<128> LhsString, RhsString; 2404 { 2405 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 2406 const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, BRC, R, 2407 N, shouldPrune, IsSameFieldName); 2408 const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, BRC, R, 2409 N, shouldPrune, IsSameFieldName); 2410 2411 shouldInvert = !isVarLHS && isVarRHS; 2412 } 2413 2414 BinaryOperator::Opcode Op = BExpr->getOpcode(); 2415 2416 if (BinaryOperator::isAssignmentOp(Op)) { 2417 // For assignment operators, all that we care about is that the LHS 2418 // evaluates to "true" or "false". 2419 return VisitConditionVariable(LhsString, BExpr->getLHS(), BRC, R, N, 2420 TookTrue); 2421 } 2422 2423 // For non-assignment operations, we require that we can understand 2424 // both the LHS and RHS. 2425 if (LhsString.empty() || RhsString.empty() || 2426 !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp) 2427 return nullptr; 2428 2429 // Should we invert the strings if the LHS is not a variable name? 2430 SmallString<256> buf; 2431 llvm::raw_svector_ostream Out(buf); 2432 Out << (IsAssuming ? "Assuming " : "") 2433 << (shouldInvert ? RhsString : LhsString) << " is "; 2434 2435 // Do we need to invert the opcode? 2436 if (shouldInvert) 2437 switch (Op) { 2438 default: break; 2439 case BO_LT: Op = BO_GT; break; 2440 case BO_GT: Op = BO_LT; break; 2441 case BO_LE: Op = BO_GE; break; 2442 case BO_GE: Op = BO_LE; break; 2443 } 2444 2445 if (!TookTrue) 2446 switch (Op) { 2447 case BO_EQ: Op = BO_NE; break; 2448 case BO_NE: Op = BO_EQ; break; 2449 case BO_LT: Op = BO_GE; break; 2450 case BO_GT: Op = BO_LE; break; 2451 case BO_LE: Op = BO_GT; break; 2452 case BO_GE: Op = BO_LT; break; 2453 default: 2454 return nullptr; 2455 } 2456 2457 switch (Op) { 2458 case BO_EQ: 2459 Out << "equal to "; 2460 break; 2461 case BO_NE: 2462 Out << "not equal to "; 2463 break; 2464 default: 2465 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 2466 break; 2467 } 2468 2469 Out << (shouldInvert ? LhsString : RhsString); 2470 const LocationContext *LCtx = N->getLocationContext(); 2471 const SourceManager &SM = BRC.getSourceManager(); 2472 2473 if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) || 2474 isVarAnInterestingCondition(BExpr->getRHS(), N, &R)) 2475 Out << WillBeUsedForACondition; 2476 2477 // Convert 'field ...' to 'Field ...' if it is a MemberExpr. 2478 std::string Message = Out.str(); 2479 Message[0] = toupper(Message[0]); 2480 2481 // If we know the value create a pop-up note to the value part of 'BExpr'. 2482 if (!IsAssuming) { 2483 PathDiagnosticLocation Loc; 2484 if (!shouldInvert) { 2485 if (LhsME && LhsME->getMemberLoc().isValid()) 2486 Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM); 2487 else 2488 Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx); 2489 } else { 2490 if (RhsME && RhsME->getMemberLoc().isValid()) 2491 Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM); 2492 else 2493 Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx); 2494 } 2495 2496 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message); 2497 } 2498 2499 PathDiagnosticLocation Loc(Cond, SM, LCtx); 2500 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message); 2501 if (shouldPrune.hasValue()) 2502 event->setPrunable(shouldPrune.getValue()); 2503 return event; 2504 } 2505 2506 PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable( 2507 StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC, 2508 BugReport &report, const ExplodedNode *N, bool TookTrue) { 2509 // FIXME: If there's already a constraint tracker for this variable, 2510 // we shouldn't emit anything here (c.f. the double note in 2511 // test/Analysis/inlining/path-notes.c) 2512 SmallString<256> buf; 2513 llvm::raw_svector_ostream Out(buf); 2514 Out << "Assuming " << LhsString << " is "; 2515 2516 if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true)) 2517 return nullptr; 2518 2519 const LocationContext *LCtx = N->getLocationContext(); 2520 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 2521 2522 if (isVarAnInterestingCondition(CondVarExpr, N, &report)) 2523 Out << WillBeUsedForACondition; 2524 2525 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str()); 2526 2527 if (isInterestingExpr(CondVarExpr, N, &report)) 2528 event->setPrunable(false); 2529 2530 return event; 2531 } 2532 2533 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( 2534 const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC, 2535 BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { 2536 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); 2537 if (!VD) 2538 return nullptr; 2539 2540 SmallString<256> Buf; 2541 llvm::raw_svector_ostream Out(Buf); 2542 2543 Out << (IsAssuming ? "Assuming '" : "'") << VD->getDeclName() << "' is "; 2544 2545 if (!printValue(DRE, Out, N, TookTrue, IsAssuming)) 2546 return nullptr; 2547 2548 const LocationContext *LCtx = N->getLocationContext(); 2549 2550 if (isVarAnInterestingCondition(DRE, N, &report)) 2551 Out << WillBeUsedForACondition; 2552 2553 // If we know the value create a pop-up note to the 'DRE'. 2554 if (!IsAssuming) { 2555 PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx); 2556 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str()); 2557 } 2558 2559 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 2560 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str()); 2561 2562 if (isInterestingExpr(DRE, N, &report)) 2563 event->setPrunable(false); 2564 2565 return std::move(event); 2566 } 2567 2568 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( 2569 const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC, 2570 BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { 2571 SmallString<256> Buf; 2572 llvm::raw_svector_ostream Out(Buf); 2573 2574 Out << (IsAssuming ? "Assuming field '" : "Field '") 2575 << ME->getMemberDecl()->getName() << "' is "; 2576 2577 if (!printValue(ME, Out, N, TookTrue, IsAssuming)) 2578 return nullptr; 2579 2580 const LocationContext *LCtx = N->getLocationContext(); 2581 PathDiagnosticLocation Loc; 2582 2583 // If we know the value create a pop-up note to the member of the MemberExpr. 2584 if (!IsAssuming && ME->getMemberLoc().isValid()) 2585 Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager()); 2586 else 2587 Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx); 2588 2589 if (!Loc.isValid() || !Loc.asLocation().isValid()) 2590 return nullptr; 2591 2592 if (isVarAnInterestingCondition(ME, N, &report)) 2593 Out << WillBeUsedForACondition; 2594 2595 // If we know the value create a pop-up note. 2596 if (!IsAssuming) 2597 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str()); 2598 2599 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str()); 2600 if (isInterestingExpr(ME, N, &report)) 2601 event->setPrunable(false); 2602 return event; 2603 } 2604 2605 bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out, 2606 const ExplodedNode *N, bool TookTrue, 2607 bool IsAssuming) { 2608 QualType Ty = CondVarExpr->getType(); 2609 2610 if (Ty->isPointerType()) { 2611 Out << (TookTrue ? "non-null" : "null"); 2612 return true; 2613 } 2614 2615 if (Ty->isObjCObjectPointerType()) { 2616 Out << (TookTrue ? "non-nil" : "nil"); 2617 return true; 2618 } 2619 2620 if (!Ty->isIntegralOrEnumerationType()) 2621 return false; 2622 2623 Optional<const llvm::APSInt *> IntValue; 2624 if (!IsAssuming) 2625 IntValue = getConcreteIntegerValue(CondVarExpr, N); 2626 2627 if (IsAssuming || !IntValue.hasValue()) { 2628 if (Ty->isBooleanType()) 2629 Out << (TookTrue ? "true" : "false"); 2630 else 2631 Out << (TookTrue ? "not equal to 0" : "0"); 2632 } else { 2633 if (Ty->isBooleanType()) 2634 Out << (IntValue.getValue()->getBoolValue() ? "true" : "false"); 2635 else 2636 Out << *IntValue.getValue(); 2637 } 2638 2639 return true; 2640 } 2641 2642 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage; 2643 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage; 2644 2645 bool ConditionBRVisitor::isPieceMessageGeneric( 2646 const PathDiagnosticPiece *Piece) { 2647 return Piece->getString() == GenericTrueMessage || 2648 Piece->getString() == GenericFalseMessage; 2649 } 2650 2651 //===----------------------------------------------------------------------===// 2652 // Implementation of LikelyFalsePositiveSuppressionBRVisitor. 2653 //===----------------------------------------------------------------------===// 2654 2655 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor( 2656 BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { 2657 // Here we suppress false positives coming from system headers. This list is 2658 // based on known issues. 2659 const AnalyzerOptions &Options = BRC.getAnalyzerOptions(); 2660 const Decl *D = N->getLocationContext()->getDecl(); 2661 2662 if (AnalysisDeclContext::isInStdNamespace(D)) { 2663 // Skip reports within the 'std' namespace. Although these can sometimes be 2664 // the user's fault, we currently don't report them very well, and 2665 // Note that this will not help for any other data structure libraries, like 2666 // TR1, Boost, or llvm/ADT. 2667 if (Options.ShouldSuppressFromCXXStandardLibrary) { 2668 BR.markInvalid(getTag(), nullptr); 2669 return; 2670 } else { 2671 // If the complete 'std' suppression is not enabled, suppress reports 2672 // from the 'std' namespace that are known to produce false positives. 2673 2674 // The analyzer issues a false use-after-free when std::list::pop_front 2675 // or std::list::pop_back are called multiple times because we cannot 2676 // reason about the internal invariants of the data structure. 2677 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { 2678 const CXXRecordDecl *CD = MD->getParent(); 2679 if (CD->getName() == "list") { 2680 BR.markInvalid(getTag(), nullptr); 2681 return; 2682 } 2683 } 2684 2685 // The analyzer issues a false positive when the constructor of 2686 // std::__independent_bits_engine from algorithms is used. 2687 if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) { 2688 const CXXRecordDecl *CD = MD->getParent(); 2689 if (CD->getName() == "__independent_bits_engine") { 2690 BR.markInvalid(getTag(), nullptr); 2691 return; 2692 } 2693 } 2694 2695 for (const LocationContext *LCtx = N->getLocationContext(); LCtx; 2696 LCtx = LCtx->getParent()) { 2697 const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); 2698 if (!MD) 2699 continue; 2700 2701 const CXXRecordDecl *CD = MD->getParent(); 2702 // The analyzer issues a false positive on 2703 // std::basic_string<uint8_t> v; v.push_back(1); 2704 // and 2705 // std::u16string s; s += u'a'; 2706 // because we cannot reason about the internal invariants of the 2707 // data structure. 2708 if (CD->getName() == "basic_string") { 2709 BR.markInvalid(getTag(), nullptr); 2710 return; 2711 } 2712 2713 // The analyzer issues a false positive on 2714 // std::shared_ptr<int> p(new int(1)); p = nullptr; 2715 // because it does not reason properly about temporary destructors. 2716 if (CD->getName() == "shared_ptr") { 2717 BR.markInvalid(getTag(), nullptr); 2718 return; 2719 } 2720 } 2721 } 2722 } 2723 2724 // Skip reports within the sys/queue.h macros as we do not have the ability to 2725 // reason about data structure shapes. 2726 const SourceManager &SM = BRC.getSourceManager(); 2727 FullSourceLoc Loc = BR.getLocation(SM).asLocation(); 2728 while (Loc.isMacroID()) { 2729 Loc = Loc.getSpellingLoc(); 2730 if (SM.getFilename(Loc).endswith("sys/queue.h")) { 2731 BR.markInvalid(getTag(), nullptr); 2732 return; 2733 } 2734 } 2735 } 2736 2737 //===----------------------------------------------------------------------===// 2738 // Implementation of UndefOrNullArgVisitor. 2739 //===----------------------------------------------------------------------===// 2740 2741 PathDiagnosticPieceRef UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, 2742 BugReporterContext &BRC, 2743 BugReport &BR) { 2744 ProgramStateRef State = N->getState(); 2745 ProgramPoint ProgLoc = N->getLocation(); 2746 2747 // We are only interested in visiting CallEnter nodes. 2748 Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>(); 2749 if (!CEnter) 2750 return nullptr; 2751 2752 // Check if one of the arguments is the region the visitor is tracking. 2753 CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); 2754 CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); 2755 unsigned Idx = 0; 2756 ArrayRef<ParmVarDecl *> parms = Call->parameters(); 2757 2758 for (const auto ParamDecl : parms) { 2759 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); 2760 ++Idx; 2761 2762 // Are we tracking the argument or its subregion? 2763 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts())) 2764 continue; 2765 2766 // Check the function parameter type. 2767 assert(ParamDecl && "Formal parameter has no decl?"); 2768 QualType T = ParamDecl->getType(); 2769 2770 if (!(T->isAnyPointerType() || T->isReferenceType())) { 2771 // Function can only change the value passed in by address. 2772 continue; 2773 } 2774 2775 // If it is a const pointer value, the function does not intend to 2776 // change the value. 2777 if (T->getPointeeType().isConstQualified()) 2778 continue; 2779 2780 // Mark the call site (LocationContext) as interesting if the value of the 2781 // argument is undefined or '0'/'NULL'. 2782 SVal BoundVal = State->getSVal(R); 2783 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { 2784 BR.markInteresting(CEnter->getCalleeContext()); 2785 return nullptr; 2786 } 2787 } 2788 return nullptr; 2789 } 2790 2791 //===----------------------------------------------------------------------===// 2792 // Implementation of FalsePositiveRefutationBRVisitor. 2793 //===----------------------------------------------------------------------===// 2794 2795 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor() 2796 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {} 2797 2798 void FalsePositiveRefutationBRVisitor::finalizeVisitor( 2799 BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { 2800 // Collect new constraints 2801 VisitNode(EndPathNode, BRC, BR); 2802 2803 // Create a refutation manager 2804 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver(); 2805 ASTContext &Ctx = BRC.getASTContext(); 2806 2807 // Add constraints to the solver 2808 for (const auto &I : Constraints) { 2809 const SymbolRef Sym = I.first; 2810 auto RangeIt = I.second.begin(); 2811 2812 llvm::SMTExprRef Constraints = SMTConv::getRangeExpr( 2813 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(), 2814 /*InRange=*/true); 2815 while ((++RangeIt) != I.second.end()) { 2816 Constraints = RefutationSolver->mkOr( 2817 Constraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym, 2818 RangeIt->From(), RangeIt->To(), 2819 /*InRange=*/true)); 2820 } 2821 2822 RefutationSolver->addConstraint(Constraints); 2823 } 2824 2825 // And check for satisfiability 2826 Optional<bool> isSat = RefutationSolver->check(); 2827 if (!isSat.hasValue()) 2828 return; 2829 2830 if (!isSat.getValue()) 2831 BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext()); 2832 } 2833 2834 PathDiagnosticPieceRef 2835 FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N, 2836 BugReporterContext &, BugReport &) { 2837 // Collect new constraints 2838 const ConstraintRangeTy &NewCs = N->getState()->get<ConstraintRange>(); 2839 ConstraintRangeTy::Factory &CF = 2840 N->getState()->get_context<ConstraintRange>(); 2841 2842 // Add constraints if we don't have them yet 2843 for (auto const &C : NewCs) { 2844 const SymbolRef &Sym = C.first; 2845 if (!Constraints.contains(Sym)) { 2846 Constraints = CF.add(Constraints, Sym, C.second); 2847 } 2848 } 2849 2850 return nullptr; 2851 } 2852 2853 void FalsePositiveRefutationBRVisitor::Profile( 2854 llvm::FoldingSetNodeID &ID) const { 2855 static int Tag = 0; 2856 ID.AddPointer(&Tag); 2857 } 2858 2859 //===----------------------------------------------------------------------===// 2860 // Implementation of TagVisitor. 2861 //===----------------------------------------------------------------------===// 2862 2863 int NoteTag::Kind = 0; 2864 2865 void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 2866 static int Tag = 0; 2867 ID.AddPointer(&Tag); 2868 } 2869 2870 PathDiagnosticPieceRef TagVisitor::VisitNode(const ExplodedNode *N, 2871 BugReporterContext &BRC, 2872 BugReport &R) { 2873 ProgramPoint PP = N->getLocation(); 2874 const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag()); 2875 if (!T) 2876 return nullptr; 2877 2878 if (Optional<std::string> Msg = T->generateMessage(BRC, R)) { 2879 PathDiagnosticLocation Loc = 2880 PathDiagnosticLocation::create(PP, BRC.getSourceManager()); 2881 auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg); 2882 Piece->setPrunable(T->isPrunable()); 2883 return Piece; 2884 } 2885 2886 return nullptr; 2887 } 2888