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