BugReporterVisitors.cpp revision cfa88f893915ceb8ae4ce2f17c46c24a4d67502f
1// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// 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#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 15#include "clang/AST/Expr.h" 16#include "clang/AST/ExprObjC.h" 17#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 18#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 19#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 20#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 21#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 22#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 23#include "llvm/ADT/SmallString.h" 24#include "llvm/ADT/StringExtras.h" 25#include "llvm/Support/raw_ostream.h" 26 27using namespace clang; 28using namespace ento; 29 30//===----------------------------------------------------------------------===// 31// Utility functions. 32//===----------------------------------------------------------------------===// 33 34bool bugreporter::isDeclRefExprToReference(const Expr *E) { 35 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 36 return DRE->getDecl()->getType()->isReferenceType(); 37 } 38 return false; 39} 40 41const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) { 42 // Pattern match for a few useful cases (do something smarter later): 43 // a[0], p->f, *p 44 const PostStmt *Loc = N->getLocationAs<PostStmt>(); 45 if (!Loc) 46 return 0; 47 48 const Expr *S = dyn_cast<Expr>(Loc->getStmt()); 49 if (!S) 50 return 0; 51 S = S->IgnoreParenCasts(); 52 53 while (true) { 54 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) { 55 assert(B->isAssignmentOp()); 56 S = B->getLHS()->IgnoreParenCasts(); 57 continue; 58 } 59 else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) { 60 if (U->getOpcode() == UO_Deref) 61 return U->getSubExpr()->IgnoreParenCasts(); 62 } 63 else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { 64 if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) { 65 return ME->getBase()->IgnoreParenCasts(); 66 } 67 } 68 else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(S)) { 69 return IvarRef->getBase()->IgnoreParenCasts(); 70 } 71 else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) { 72 return AE->getBase(); 73 } 74 break; 75 } 76 77 return NULL; 78} 79 80const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { 81 const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 82 if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) 83 return BE->getRHS(); 84 return NULL; 85} 86 87const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { 88 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 89 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) 90 return RS->getRetValue(); 91 return NULL; 92} 93 94//===----------------------------------------------------------------------===// 95// Definitions for bug reporter visitors. 96//===----------------------------------------------------------------------===// 97 98PathDiagnosticPiece* 99BugReporterVisitor::getEndPath(BugReporterContext &BRC, 100 const ExplodedNode *EndPathNode, 101 BugReport &BR) { 102 return 0; 103} 104 105PathDiagnosticPiece* 106BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, 107 const ExplodedNode *EndPathNode, 108 BugReport &BR) { 109 PathDiagnosticLocation L = 110 PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); 111 112 BugReport::ranges_iterator Beg, End; 113 llvm::tie(Beg, End) = BR.getRanges(); 114 115 // Only add the statement itself as a range if we didn't specify any 116 // special ranges for this report. 117 PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, 118 BR.getDescription(), 119 Beg == End); 120 for (; Beg != End; ++Beg) 121 P->addRange(*Beg); 122 123 return P; 124} 125 126 127namespace { 128/// Emits an extra note at the return statement of an interesting stack frame. 129/// 130/// The returned value is marked as an interesting value, and if it's null, 131/// adds a visitor to track where it became null. 132/// 133/// This visitor is intended to be used when another visitor discovers that an 134/// interesting value comes from an inlined function call. 135class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> { 136 const StackFrameContext *StackFrame; 137 enum { 138 Initial, 139 MaybeSuppress, 140 Satisfied 141 } Mode; 142 143public: 144 ReturnVisitor(const StackFrameContext *Frame) 145 : StackFrame(Frame), Mode(Initial) {} 146 147 static void *getTag() { 148 static int Tag = 0; 149 return static_cast<void *>(&Tag); 150 } 151 152 virtual void Profile(llvm::FoldingSetNodeID &ID) const { 153 ID.AddPointer(ReturnVisitor::getTag()); 154 ID.AddPointer(StackFrame); 155 } 156 157 /// Adds a ReturnVisitor if the given statement represents a call that was 158 /// inlined. 159 /// 160 /// This will search back through the ExplodedGraph, starting from the given 161 /// node, looking for when the given statement was processed. If it turns out 162 /// the statement is a call that was inlined, we add the visitor to the 163 /// bug report, so it can print a note later. 164 static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S, 165 BugReport &BR) { 166 if (!CallEvent::isCallStmt(S)) 167 return; 168 169 // First, find when we processed the statement. 170 do { 171 if (const CallExitEnd *CEE = Node->getLocationAs<CallExitEnd>()) 172 if (CEE->getCalleeContext()->getCallSite() == S) 173 break; 174 if (const StmtPoint *SP = Node->getLocationAs<StmtPoint>()) 175 if (SP->getStmt() == S) 176 break; 177 178 Node = Node->getFirstPred(); 179 } while (Node); 180 181 // Next, step over any post-statement checks. 182 while (Node && isa<PostStmt>(Node->getLocation())) 183 Node = Node->getFirstPred(); 184 185 // Finally, see if we inlined the call. 186 if (Node) { 187 if (const CallExitEnd *CEE = Node->getLocationAs<CallExitEnd>()) { 188 const StackFrameContext *CalleeContext = CEE->getCalleeContext(); 189 if (CalleeContext->getCallSite() == S) { 190 BR.markInteresting(CalleeContext); 191 BR.addVisitor(new ReturnVisitor(CalleeContext)); 192 } 193 } 194 } 195 } 196 197 /// Returns true if any counter-suppression heuristics are enabled for 198 /// ReturnVisitor. 199 static bool hasCounterSuppression(AnalyzerOptions &Options) { 200 return Options.shouldAvoidSuppressingNullArgumentPaths(); 201 } 202 203 PathDiagnosticPiece *visitNodeInitial(const ExplodedNode *N, 204 const ExplodedNode *PrevN, 205 BugReporterContext &BRC, 206 BugReport &BR) { 207 // Only print a message at the interesting return statement. 208 if (N->getLocationContext() != StackFrame) 209 return 0; 210 211 const StmtPoint *SP = N->getLocationAs<StmtPoint>(); 212 if (!SP) 213 return 0; 214 215 const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); 216 if (!Ret) 217 return 0; 218 219 // Okay, we're at the right return statement, but do we have the return 220 // value available? 221 ProgramStateRef State = N->getState(); 222 SVal V = State->getSVal(Ret, StackFrame); 223 if (V.isUnknownOrUndef()) 224 return 0; 225 226 // Don't print any more notes after this one. 227 Mode = Satisfied; 228 229 const Expr *RetE = Ret->getRetValue(); 230 assert(RetE && "Tracking a return value for a void function"); 231 RetE = RetE->IgnoreParenCasts(); 232 233 // If we can't prove the return value is 0, just mark it interesting, and 234 // make sure to track it into any further inner functions. 235 if (State->assume(cast<DefinedSVal>(V), true)) { 236 BR.markInteresting(V); 237 ReturnVisitor::addVisitorIfNecessary(N, RetE, BR); 238 return 0; 239 } 240 241 // If we're returning 0, we should track where that 0 came from. 242 bugreporter::trackNullOrUndefValue(N, RetE, BR); 243 244 // Build an appropriate message based on the return value. 245 SmallString<64> Msg; 246 llvm::raw_svector_ostream Out(Msg); 247 248 if (isa<Loc>(V)) { 249 // If we are pruning null-return paths as unlikely error paths, mark the 250 // report invalid. We still want to emit a path note, however, in case 251 // the report is resurrected as valid later on. 252 ExprEngine &Eng = BRC.getBugReporter().getEngine(); 253 AnalyzerOptions &Options = Eng.getAnalysisManager().options; 254 if (Options.shouldPruneNullReturnPaths()) { 255 if (hasCounterSuppression(Options)) 256 Mode = MaybeSuppress; 257 else 258 BR.markInvalid(ReturnVisitor::getTag(), StackFrame); 259 } 260 261 if (RetE->getType()->isObjCObjectPointerType()) 262 Out << "Returning nil"; 263 else 264 Out << "Returning null pointer"; 265 } else { 266 Out << "Returning zero"; 267 } 268 269 // FIXME: We should have a more generalized location printing mechanism. 270 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE)) 271 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) 272 Out << " (loaded from '" << *DD << "')"; 273 274 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame); 275 return new PathDiagnosticEventPiece(L, Out.str()); 276 } 277 278 PathDiagnosticPiece *visitNodeMaybeSuppress(const ExplodedNode *N, 279 const ExplodedNode *PrevN, 280 BugReporterContext &BRC, 281 BugReport &BR) { 282 // Are we at the entry node for this call? 283 const CallEnter *CE = N->getLocationAs<CallEnter>(); 284 if (!CE) 285 return 0; 286 287 if (CE->getCalleeContext() != StackFrame) 288 return 0; 289 290 Mode = Satisfied; 291 292 ExprEngine &Eng = BRC.getBugReporter().getEngine(); 293 AnalyzerOptions &Options = Eng.getAnalysisManager().options; 294 if (Options.shouldAvoidSuppressingNullArgumentPaths()) { 295 // Don't automatically suppress a report if one of the arguments is 296 // known to be a null pointer. Instead, start tracking /that/ null 297 // value back to its origin. 298 ProgramStateManager &StateMgr = BRC.getStateManager(); 299 CallEventManager &CallMgr = StateMgr.getCallEventManager(); 300 301 ProgramStateRef State = N->getState(); 302 CallEventRef<> Call = CallMgr.getCaller(StackFrame, State); 303 for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) { 304 SVal ArgV = Call->getArgSVal(I); 305 if (!isa<Loc>(ArgV)) 306 continue; 307 308 const Expr *ArgE = Call->getArgExpr(I); 309 if (!ArgE) 310 continue; 311 312 // Is it possible for this argument to be non-null? 313 if (State->assume(cast<Loc>(ArgV), true)) 314 continue; 315 316 if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true)) 317 return 0; 318 319 // If we /can't/ track the null pointer, we should err on the side of 320 // false negatives, and continue towards marking this report invalid. 321 // (We will still look at the other arguments, though.) 322 } 323 } 324 325 // There is no reason not to suppress this report; go ahead and do it. 326 BR.markInvalid(ReturnVisitor::getTag(), StackFrame); 327 return 0; 328 } 329 330 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 331 const ExplodedNode *PrevN, 332 BugReporterContext &BRC, 333 BugReport &BR) { 334 switch (Mode) { 335 case Initial: 336 return visitNodeInitial(N, PrevN, BRC, BR); 337 case MaybeSuppress: 338 return visitNodeMaybeSuppress(N, PrevN, BRC, BR); 339 case Satisfied: 340 return 0; 341 } 342 343 llvm_unreachable("Invalid visit mode!"); 344 } 345}; 346} // end anonymous namespace 347 348 349void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { 350 static int tag = 0; 351 ID.AddPointer(&tag); 352 ID.AddPointer(R); 353 ID.Add(V); 354} 355 356PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, 357 const ExplodedNode *Pred, 358 BugReporterContext &BRC, 359 BugReport &BR) { 360 361 if (satisfied) 362 return NULL; 363 364 const ExplodedNode *StoreSite = 0; 365 const Expr *InitE = 0; 366 bool IsParam = false; 367 368 // First see if we reached the declaration of the region. 369 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 370 if (const PostStmt *P = Pred->getLocationAs<PostStmt>()) { 371 if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) { 372 if (DS->getSingleDecl() == VR->getDecl()) { 373 StoreSite = Pred; 374 InitE = VR->getDecl()->getInit(); 375 } 376 } 377 } 378 } 379 380 // Otherwise, check that Succ has this binding and Pred does not, i.e. this is 381 // where the binding first occurred. 382 if (!StoreSite) { 383 if (Succ->getState()->getSVal(R) != V) 384 return NULL; 385 if (Pred->getState()->getSVal(R) == V) 386 return NULL; 387 388 StoreSite = Succ; 389 390 // If this is an assignment expression, we can track the value 391 // being assigned. 392 if (const PostStmt *P = Succ->getLocationAs<PostStmt>()) 393 if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) 394 if (BO->isAssignmentOp()) 395 InitE = BO->getRHS(); 396 397 // If this is a call entry, the variable should be a parameter. 398 // FIXME: Handle CXXThisRegion as well. (This is not a priority because 399 // 'this' should never be NULL, but this visitor isn't just for NULL and 400 // UndefinedVal.) 401 if (const CallEnter *CE = Succ->getLocationAs<CallEnter>()) { 402 const VarRegion *VR = cast<VarRegion>(R); 403 const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 404 405 ProgramStateManager &StateMgr = BRC.getStateManager(); 406 CallEventManager &CallMgr = StateMgr.getCallEventManager(); 407 408 CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), 409 Succ->getState()); 410 InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); 411 IsParam = true; 412 } 413 } 414 415 if (!StoreSite) 416 return NULL; 417 satisfied = true; 418 419 // If we have an expression that provided the value, try to track where it 420 // came from. 421 if (InitE) { 422 if (V.isUndef() || isa<loc::ConcreteInt>(V)) { 423 if (!IsParam) 424 InitE = InitE->IgnoreParenCasts(); 425 bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam); 426 } else { 427 ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), 428 BR); 429 } 430 } 431 432 if (!R->canPrintPretty()) 433 return 0; 434 435 // Okay, we've found the binding. Emit an appropriate message. 436 SmallString<256> sbuf; 437 llvm::raw_svector_ostream os(sbuf); 438 439 if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) { 440 if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { 441 442 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 443 os << "Variable '" << *VR->getDecl() << "' "; 444 } 445 else 446 return NULL; 447 448 if (isa<loc::ConcreteInt>(V)) { 449 bool b = false; 450 if (R->isBoundable()) { 451 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 452 if (TR->getValueType()->isObjCObjectPointerType()) { 453 os << "initialized to nil"; 454 b = true; 455 } 456 } 457 } 458 459 if (!b) 460 os << "initialized to a null pointer value"; 461 } 462 else if (isa<nonloc::ConcreteInt>(V)) { 463 os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); 464 } 465 else if (V.isUndef()) { 466 if (isa<VarRegion>(R)) { 467 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 468 if (VD->getInit()) 469 os << "initialized to a garbage value"; 470 else 471 os << "declared without an initial value"; 472 } 473 } 474 else { 475 os << "initialized here"; 476 } 477 } 478 } else if (isa<CallEnter>(StoreSite->getLocation())) { 479 const ParmVarDecl *Param = cast<ParmVarDecl>(cast<VarRegion>(R)->getDecl()); 480 481 os << "Passing "; 482 483 if (isa<loc::ConcreteInt>(V)) { 484 if (Param->getType()->isObjCObjectPointerType()) 485 os << "nil object reference"; 486 else 487 os << "null pointer value"; 488 } else if (V.isUndef()) { 489 os << "uninitialized value"; 490 } else if (isa<nonloc::ConcreteInt>(V)) { 491 os << "the value " << cast<nonloc::ConcreteInt>(V).getValue(); 492 } else { 493 os << "value"; 494 } 495 496 // Printed parameter indexes are 1-based, not 0-based. 497 unsigned Idx = Param->getFunctionScopeIndex() + 1; 498 os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter '"; 499 500 R->printPretty(os); 501 os << '\''; 502 } 503 504 if (os.str().empty()) { 505 if (isa<loc::ConcreteInt>(V)) { 506 bool b = false; 507 if (R->isBoundable()) { 508 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 509 if (TR->getValueType()->isObjCObjectPointerType()) { 510 os << "nil object reference stored to "; 511 b = true; 512 } 513 } 514 } 515 516 if (!b) 517 os << "Null pointer value stored to "; 518 } 519 else if (V.isUndef()) { 520 os << "Uninitialized value stored to "; 521 } 522 else if (isa<nonloc::ConcreteInt>(V)) { 523 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() 524 << " is assigned to "; 525 } 526 else 527 os << "Value assigned to "; 528 529 os << '\''; 530 R->printPretty(os); 531 os << '\''; 532 } 533 534 // Construct a new PathDiagnosticPiece. 535 ProgramPoint P = StoreSite->getLocation(); 536 PathDiagnosticLocation L; 537 if (isa<CallEnter>(P)) 538 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(), 539 P.getLocationContext()); 540 else 541 L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); 542 if (!L.isValid()) 543 return NULL; 544 return new PathDiagnosticEventPiece(L, os.str()); 545} 546 547void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 548 static int tag = 0; 549 ID.AddPointer(&tag); 550 ID.AddBoolean(Assumption); 551 ID.Add(Constraint); 552} 553 554/// Return the tag associated with this visitor. This tag will be used 555/// to make all PathDiagnosticPieces created by this visitor. 556const char *TrackConstraintBRVisitor::getTag() { 557 return "TrackConstraintBRVisitor"; 558} 559 560PathDiagnosticPiece * 561TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 562 const ExplodedNode *PrevN, 563 BugReporterContext &BRC, 564 BugReport &BR) { 565 if (isSatisfied) 566 return NULL; 567 568 // Check if in the previous state it was feasible for this constraint 569 // to *not* be true. 570 if (PrevN->getState()->assume(Constraint, !Assumption)) { 571 572 isSatisfied = true; 573 574 // As a sanity check, make sure that the negation of the constraint 575 // was infeasible in the current state. If it is feasible, we somehow 576 // missed the transition point. 577 if (N->getState()->assume(Constraint, !Assumption)) 578 return NULL; 579 580 // We found the transition point for the constraint. We now need to 581 // pretty-print the constraint. (work-in-progress) 582 std::string sbuf; 583 llvm::raw_string_ostream os(sbuf); 584 585 if (isa<Loc>(Constraint)) { 586 os << "Assuming pointer value is "; 587 os << (Assumption ? "non-null" : "null"); 588 } 589 590 if (os.str().empty()) 591 return NULL; 592 593 // Construct a new PathDiagnosticPiece. 594 ProgramPoint P = N->getLocation(); 595 PathDiagnosticLocation L = 596 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 597 if (!L.isValid()) 598 return NULL; 599 600 PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str()); 601 X->setTag(getTag()); 602 return X; 603 } 604 605 return NULL; 606} 607 608bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, 609 BugReport &report, bool IsArg) { 610 if (!S || !N) 611 return false; 612 613 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) 614 S = OVE->getSourceExpr(); 615 616 if (IsArg) { 617 assert(isa<CallEnter>(N->getLocation()) && "Tracking arg but not at call"); 618 } else { 619 // Walk through nodes until we get one that matches the statement exactly. 620 do { 621 const ProgramPoint &pp = N->getLocation(); 622 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { 623 if (ps->getStmt() == S) 624 break; 625 } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&pp)) { 626 if (CEE->getCalleeContext()->getCallSite() == S) 627 break; 628 } 629 N = N->getFirstPred(); 630 } while (N); 631 632 if (!N) 633 return false; 634 } 635 636 ProgramStateRef state = N->getState(); 637 638 // See if the expression we're interested refers to a variable. 639 // If so, we can track both its contents and constraints on its value. 640 if (const Expr *Ex = dyn_cast<Expr>(S)) { 641 // Strip off parens and casts. Note that this will never have issues with 642 // C++ user-defined implicit conversions, because those have a constructor 643 // or function call inside. 644 Ex = Ex->IgnoreParenCasts(); 645 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 646 // FIXME: Right now we only track VarDecls because it's non-trivial to 647 // get a MemRegion for any other DeclRefExprs. <rdar://problem/12114812> 648 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 649 ProgramStateManager &StateMgr = state->getStateManager(); 650 MemRegionManager &MRMgr = StateMgr.getRegionManager(); 651 const VarRegion *R = MRMgr.getVarRegion(VD, N->getLocationContext()); 652 653 // Mark both the variable region and its contents as interesting. 654 SVal V = state->getRawSVal(loc::MemRegionVal(R)); 655 656 // If the value matches the default for the variable region, that 657 // might mean that it's been cleared out of the state. Fall back to 658 // the full argument expression (with casts and such intact). 659 if (IsArg) { 660 bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant(); 661 if (!UseArgValue) { 662 const SymbolRegionValue *SRV = 663 dyn_cast_or_null<SymbolRegionValue>(V.getAsLocSymbol()); 664 if (SRV) 665 UseArgValue = (SRV->getRegion() == R); 666 } 667 if (UseArgValue) 668 V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 669 } 670 671 report.markInteresting(R); 672 report.markInteresting(V); 673 report.addVisitor(new UndefOrNullArgVisitor(R)); 674 675 // If the contents are symbolic, find out when they became null. 676 if (V.getAsLocSymbol()) { 677 BugReporterVisitor *ConstraintTracker 678 = new TrackConstraintBRVisitor(cast<DefinedSVal>(V), false); 679 report.addVisitor(ConstraintTracker); 680 } 681 682 report.addVisitor(new FindLastStoreBRVisitor(V, R)); 683 return true; 684 } 685 } 686 } 687 688 // If the expression does NOT refer to a variable, we can still track 689 // constraints on its contents. 690 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 691 692 // Uncomment this to find cases where we aren't properly getting the 693 // base value that was dereferenced. 694 // assert(!V.isUnknownOrUndef()); 695 696 // Is it a symbolic value? 697 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) { 698 // At this point we are dealing with the region's LValue. 699 // However, if the rvalue is a symbolic region, we should track it as well. 700 SVal RVal = state->getSVal(L->getRegion()); 701 const MemRegion *RegionRVal = RVal.getAsRegion(); 702 report.addVisitor(new UndefOrNullArgVisitor(L->getRegion())); 703 704 705 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { 706 report.markInteresting(RegionRVal); 707 report.addVisitor(new TrackConstraintBRVisitor( 708 loc::MemRegionVal(RegionRVal), false)); 709 } 710 } else { 711 // Otherwise, if the value came from an inlined function call, 712 // we should at least make sure that function isn't pruned in our output. 713 if (const Expr *E = dyn_cast<Expr>(S)) 714 S = E->IgnoreParenCasts(); 715 ReturnVisitor::addVisitorIfNecessary(N, S, report); 716 } 717 718 return true; 719} 720 721BugReporterVisitor * 722FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N, 723 const MemRegion *R) { 724 assert(R && "The memory region is null."); 725 726 ProgramStateRef state = N->getState(); 727 SVal V = state->getSVal(R); 728 if (V.isUnknown()) 729 return 0; 730 731 return new FindLastStoreBRVisitor(V, R); 732} 733 734 735PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 736 const ExplodedNode *PrevN, 737 BugReporterContext &BRC, 738 BugReport &BR) { 739 const PostStmt *P = N->getLocationAs<PostStmt>(); 740 if (!P) 741 return 0; 742 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 743 if (!ME) 744 return 0; 745 const Expr *Receiver = ME->getInstanceReceiver(); 746 if (!Receiver) 747 return 0; 748 ProgramStateRef state = N->getState(); 749 const SVal &V = state->getSVal(Receiver, N->getLocationContext()); 750 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); 751 if (!DV) 752 return 0; 753 state = state->assume(*DV, true); 754 if (state) 755 return 0; 756 757 // The receiver was nil, and hence the method was skipped. 758 // Register a BugReporterVisitor to issue a message telling us how 759 // the receiver was null. 760 bugreporter::trackNullOrUndefValue(N, Receiver, BR); 761 // Issue a message saying that the method was skipped. 762 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 763 N->getLocationContext()); 764 return new PathDiagnosticEventPiece(L, "No method is called " 765 "because the receiver is nil"); 766} 767 768// Registers every VarDecl inside a Stmt with a last store visitor. 769void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 770 const Stmt *S) { 771 const ExplodedNode *N = BR.getErrorNode(); 772 std::deque<const Stmt *> WorkList; 773 WorkList.push_back(S); 774 775 while (!WorkList.empty()) { 776 const Stmt *Head = WorkList.front(); 777 WorkList.pop_front(); 778 779 ProgramStateRef state = N->getState(); 780 ProgramStateManager &StateMgr = state->getStateManager(); 781 782 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 783 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 784 const VarRegion *R = 785 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 786 787 // What did we load? 788 SVal V = state->getSVal(S, N->getLocationContext()); 789 790 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { 791 // Register a new visitor with the BugReport. 792 BR.addVisitor(new FindLastStoreBRVisitor(V, R)); 793 } 794 } 795 } 796 797 for (Stmt::const_child_iterator I = Head->child_begin(); 798 I != Head->child_end(); ++I) 799 WorkList.push_back(*I); 800 } 801} 802 803//===----------------------------------------------------------------------===// 804// Visitor that tries to report interesting diagnostics from conditions. 805//===----------------------------------------------------------------------===// 806 807/// Return the tag associated with this visitor. This tag will be used 808/// to make all PathDiagnosticPieces created by this visitor. 809const char *ConditionBRVisitor::getTag() { 810 return "ConditionBRVisitor"; 811} 812 813PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 814 const ExplodedNode *Prev, 815 BugReporterContext &BRC, 816 BugReport &BR) { 817 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR); 818 if (piece) { 819 piece->setTag(getTag()); 820 if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece)) 821 ev->setPrunable(true, /* override */ false); 822 } 823 return piece; 824} 825 826PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 827 const ExplodedNode *Prev, 828 BugReporterContext &BRC, 829 BugReport &BR) { 830 831 ProgramPoint progPoint = N->getLocation(); 832 ProgramStateRef CurrentState = N->getState(); 833 ProgramStateRef PrevState = Prev->getState(); 834 835 // Compare the GDMs of the state, because that is where constraints 836 // are managed. Note that ensure that we only look at nodes that 837 // were generated by the analyzer engine proper, not checkers. 838 if (CurrentState->getGDM().getRoot() == 839 PrevState->getGDM().getRoot()) 840 return 0; 841 842 // If an assumption was made on a branch, it should be caught 843 // here by looking at the state transition. 844 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) { 845 const CFGBlock *srcBlk = BE->getSrc(); 846 if (const Stmt *term = srcBlk->getTerminator()) 847 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); 848 return 0; 849 } 850 851 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) { 852 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 853 // violation. 854 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 855 cast<GRBugReporter>(BRC.getBugReporter()). 856 getEngine().geteagerlyAssumeBinOpBifurcationTags(); 857 858 const ProgramPointTag *tag = PS->getTag(); 859 if (tag == tags.first) 860 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 861 BRC, BR, N); 862 if (tag == tags.second) 863 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 864 BRC, BR, N); 865 866 return 0; 867 } 868 869 return 0; 870} 871 872PathDiagnosticPiece * 873ConditionBRVisitor::VisitTerminator(const Stmt *Term, 874 const ExplodedNode *N, 875 const CFGBlock *srcBlk, 876 const CFGBlock *dstBlk, 877 BugReport &R, 878 BugReporterContext &BRC) { 879 const Expr *Cond = 0; 880 881 switch (Term->getStmtClass()) { 882 default: 883 return 0; 884 case Stmt::IfStmtClass: 885 Cond = cast<IfStmt>(Term)->getCond(); 886 break; 887 case Stmt::ConditionalOperatorClass: 888 Cond = cast<ConditionalOperator>(Term)->getCond(); 889 break; 890 } 891 892 assert(Cond); 893 assert(srcBlk->succ_size() == 2); 894 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 895 return VisitTrueTest(Cond, tookTrue, BRC, R, N); 896} 897 898PathDiagnosticPiece * 899ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 900 bool tookTrue, 901 BugReporterContext &BRC, 902 BugReport &R, 903 const ExplodedNode *N) { 904 905 const Expr *Ex = Cond; 906 907 while (true) { 908 Ex = Ex->IgnoreParenCasts(); 909 switch (Ex->getStmtClass()) { 910 default: 911 return 0; 912 case Stmt::BinaryOperatorClass: 913 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, 914 R, N); 915 case Stmt::DeclRefExprClass: 916 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, 917 R, N); 918 case Stmt::UnaryOperatorClass: { 919 const UnaryOperator *UO = cast<UnaryOperator>(Ex); 920 if (UO->getOpcode() == UO_LNot) { 921 tookTrue = !tookTrue; 922 Ex = UO->getSubExpr(); 923 continue; 924 } 925 return 0; 926 } 927 } 928 } 929} 930 931bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out, 932 BugReporterContext &BRC, 933 BugReport &report, 934 const ExplodedNode *N, 935 llvm::Optional<bool> &prunable) { 936 const Expr *OriginalExpr = Ex; 937 Ex = Ex->IgnoreParenCasts(); 938 939 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 940 const bool quotes = isa<VarDecl>(DR->getDecl()); 941 if (quotes) { 942 Out << '\''; 943 const LocationContext *LCtx = N->getLocationContext(); 944 const ProgramState *state = N->getState().getPtr(); 945 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 946 LCtx).getAsRegion()) { 947 if (report.isInteresting(R)) 948 prunable = false; 949 else { 950 const ProgramState *state = N->getState().getPtr(); 951 SVal V = state->getSVal(R); 952 if (report.isInteresting(V)) 953 prunable = false; 954 } 955 } 956 } 957 Out << DR->getDecl()->getDeclName().getAsString(); 958 if (quotes) 959 Out << '\''; 960 return quotes; 961 } 962 963 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 964 QualType OriginalTy = OriginalExpr->getType(); 965 if (OriginalTy->isPointerType()) { 966 if (IL->getValue() == 0) { 967 Out << "null"; 968 return false; 969 } 970 } 971 else if (OriginalTy->isObjCObjectPointerType()) { 972 if (IL->getValue() == 0) { 973 Out << "nil"; 974 return false; 975 } 976 } 977 978 Out << IL->getValue(); 979 return false; 980 } 981 982 return false; 983} 984 985PathDiagnosticPiece * 986ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 987 const BinaryOperator *BExpr, 988 const bool tookTrue, 989 BugReporterContext &BRC, 990 BugReport &R, 991 const ExplodedNode *N) { 992 993 bool shouldInvert = false; 994 llvm::Optional<bool> shouldPrune; 995 996 SmallString<128> LhsString, RhsString; 997 { 998 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 999 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, 1000 shouldPrune); 1001 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, 1002 shouldPrune); 1003 1004 shouldInvert = !isVarLHS && isVarRHS; 1005 } 1006 1007 BinaryOperator::Opcode Op = BExpr->getOpcode(); 1008 1009 if (BinaryOperator::isAssignmentOp(Op)) { 1010 // For assignment operators, all that we care about is that the LHS 1011 // evaluates to "true" or "false". 1012 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 1013 BRC, R, N); 1014 } 1015 1016 // For non-assignment operations, we require that we can understand 1017 // both the LHS and RHS. 1018 if (LhsString.empty() || RhsString.empty()) 1019 return 0; 1020 1021 // Should we invert the strings if the LHS is not a variable name? 1022 SmallString<256> buf; 1023 llvm::raw_svector_ostream Out(buf); 1024 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 1025 1026 // Do we need to invert the opcode? 1027 if (shouldInvert) 1028 switch (Op) { 1029 default: break; 1030 case BO_LT: Op = BO_GT; break; 1031 case BO_GT: Op = BO_LT; break; 1032 case BO_LE: Op = BO_GE; break; 1033 case BO_GE: Op = BO_LE; break; 1034 } 1035 1036 if (!tookTrue) 1037 switch (Op) { 1038 case BO_EQ: Op = BO_NE; break; 1039 case BO_NE: Op = BO_EQ; break; 1040 case BO_LT: Op = BO_GE; break; 1041 case BO_GT: Op = BO_LE; break; 1042 case BO_LE: Op = BO_GT; break; 1043 case BO_GE: Op = BO_LT; break; 1044 default: 1045 return 0; 1046 } 1047 1048 switch (Op) { 1049 case BO_EQ: 1050 Out << "equal to "; 1051 break; 1052 case BO_NE: 1053 Out << "not equal to "; 1054 break; 1055 default: 1056 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 1057 break; 1058 } 1059 1060 Out << (shouldInvert ? LhsString : RhsString); 1061 const LocationContext *LCtx = N->getLocationContext(); 1062 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 1063 PathDiagnosticEventPiece *event = 1064 new PathDiagnosticEventPiece(Loc, Out.str()); 1065 if (shouldPrune.hasValue()) 1066 event->setPrunable(shouldPrune.getValue()); 1067 return event; 1068} 1069 1070PathDiagnosticPiece * 1071ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 1072 const Expr *CondVarExpr, 1073 const bool tookTrue, 1074 BugReporterContext &BRC, 1075 BugReport &report, 1076 const ExplodedNode *N) { 1077 // FIXME: If there's already a constraint tracker for this variable, 1078 // we shouldn't emit anything here (c.f. the double note in 1079 // test/Analysis/inlining/path-notes.c) 1080 SmallString<256> buf; 1081 llvm::raw_svector_ostream Out(buf); 1082 Out << "Assuming " << LhsString << " is "; 1083 1084 QualType Ty = CondVarExpr->getType(); 1085 1086 if (Ty->isPointerType()) 1087 Out << (tookTrue ? "not null" : "null"); 1088 else if (Ty->isObjCObjectPointerType()) 1089 Out << (tookTrue ? "not nil" : "nil"); 1090 else if (Ty->isBooleanType()) 1091 Out << (tookTrue ? "true" : "false"); 1092 else if (Ty->isIntegerType()) 1093 Out << (tookTrue ? "non-zero" : "zero"); 1094 else 1095 return 0; 1096 1097 const LocationContext *LCtx = N->getLocationContext(); 1098 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 1099 PathDiagnosticEventPiece *event = 1100 new PathDiagnosticEventPiece(Loc, Out.str()); 1101 1102 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { 1103 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 1104 const ProgramState *state = N->getState().getPtr(); 1105 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1106 if (report.isInteresting(R)) 1107 event->setPrunable(false); 1108 } 1109 } 1110 } 1111 1112 return event; 1113} 1114 1115PathDiagnosticPiece * 1116ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 1117 const DeclRefExpr *DR, 1118 const bool tookTrue, 1119 BugReporterContext &BRC, 1120 BugReport &report, 1121 const ExplodedNode *N) { 1122 1123 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 1124 if (!VD) 1125 return 0; 1126 1127 SmallString<256> Buf; 1128 llvm::raw_svector_ostream Out(Buf); 1129 1130 Out << "Assuming '"; 1131 VD->getDeclName().printName(Out); 1132 Out << "' is "; 1133 1134 QualType VDTy = VD->getType(); 1135 1136 if (VDTy->isPointerType()) 1137 Out << (tookTrue ? "non-null" : "null"); 1138 else if (VDTy->isObjCObjectPointerType()) 1139 Out << (tookTrue ? "non-nil" : "nil"); 1140 else if (VDTy->isScalarType()) 1141 Out << (tookTrue ? "not equal to 0" : "0"); 1142 else 1143 return 0; 1144 1145 const LocationContext *LCtx = N->getLocationContext(); 1146 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 1147 PathDiagnosticEventPiece *event = 1148 new PathDiagnosticEventPiece(Loc, Out.str()); 1149 1150 const ProgramState *state = N->getState().getPtr(); 1151 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1152 if (report.isInteresting(R)) 1153 event->setPrunable(false); 1154 else { 1155 SVal V = state->getSVal(R); 1156 if (report.isInteresting(V)) 1157 event->setPrunable(false); 1158 } 1159 } 1160 return event; 1161} 1162 1163PathDiagnosticPiece * 1164UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, 1165 const ExplodedNode *PrevN, 1166 BugReporterContext &BRC, 1167 BugReport &BR) { 1168 1169 ProgramStateRef State = N->getState(); 1170 ProgramPoint ProgLoc = N->getLocation(); 1171 1172 // We are only interested in visiting CallEnter nodes. 1173 CallEnter *CEnter = dyn_cast<CallEnter>(&ProgLoc); 1174 if (!CEnter) 1175 return 0; 1176 1177 // Check if one of the arguments is the region the visitor is tracking. 1178 CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); 1179 CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); 1180 unsigned Idx = 0; 1181 for (CallEvent::param_iterator I = Call->param_begin(), 1182 E = Call->param_end(); I != E; ++I, ++Idx) { 1183 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); 1184 1185 // Are we tracking the argument or its subregion? 1186 if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) 1187 continue; 1188 1189 // Check the function parameter type. 1190 const ParmVarDecl *ParamDecl = *I; 1191 assert(ParamDecl && "Formal parameter has no decl?"); 1192 QualType T = ParamDecl->getType(); 1193 1194 if (!(T->isAnyPointerType() || T->isReferenceType())) { 1195 // Function can only change the value passed in by address. 1196 continue; 1197 } 1198 1199 // If it is a const pointer value, the function does not intend to 1200 // change the value. 1201 if (T->getPointeeType().isConstQualified()) 1202 continue; 1203 1204 // Mark the call site (LocationContext) as interesting if the value of the 1205 // argument is undefined or '0'/'NULL'. 1206 SVal BoundVal = State->getSVal(R); 1207 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { 1208 BR.markInteresting(CEnter->getCalleeContext()); 1209 return 0; 1210 } 1211 } 1212 return 0; 1213} 1214