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