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