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