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