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