BugReporterVisitors.cpp revision 09f7bf14d25bdc55cb715bc8d40600906848a409
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 bool IsParam = false; 287 288 // First see if we reached the declaration of the region. 289 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 290 if (const PostStmt *P = Pred->getLocationAs<PostStmt>()) { 291 if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) { 292 if (DS->getSingleDecl() == VR->getDecl()) { 293 StoreSite = Pred; 294 InitE = VR->getDecl()->getInit(); 295 } 296 } 297 } 298 } 299 300 // Otherwise, check that Succ has this binding and Pred does not, i.e. this is 301 // where the binding first occurred. 302 if (!StoreSite) { 303 if (Succ->getState()->getSVal(R) != V) 304 return NULL; 305 if (Pred->getState()->getSVal(R) == V) 306 return NULL; 307 308 StoreSite = Succ; 309 310 // If this is an assignment expression, we can track the value 311 // being assigned. 312 if (const PostStmt *P = Succ->getLocationAs<PostStmt>()) 313 if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) 314 if (BO->isAssignmentOp()) 315 InitE = BO->getRHS(); 316 317 // If this is a call entry, the variable should be a parameter. 318 // FIXME: Handle CXXThisRegion as well. (This is not a priority because 319 // 'this' should never be NULL, but this visitor isn't just for NULL and 320 // UndefinedVal.) 321 if (const CallEnter *CE = Succ->getLocationAs<CallEnter>()) { 322 const VarRegion *VR = cast<VarRegion>(R); 323 const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 324 325 ProgramStateManager &StateMgr = BRC.getStateManager(); 326 CallEventManager &CallMgr = StateMgr.getCallEventManager(); 327 328 CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), 329 Succ->getState()); 330 InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); 331 IsParam = true; 332 } 333 } 334 335 if (!StoreSite) 336 return NULL; 337 satisfied = true; 338 339 // If we have an expression that provided the value, try to track where it 340 // came from. 341 if (InitE) { 342 if (V.isUndef() || isa<loc::ConcreteInt>(V)) { 343 if (!IsParam) 344 InitE = InitE->IgnoreParenCasts(); 345 bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam); 346 } else { 347 ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), 348 BR); 349 } 350 } 351 352 if (!R->canPrintPretty()) 353 return 0; 354 355 // Okay, we've found the binding. Emit an appropriate message. 356 SmallString<256> sbuf; 357 llvm::raw_svector_ostream os(sbuf); 358 359 if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) { 360 if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { 361 362 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 363 os << "Variable '" << *VR->getDecl() << "' "; 364 } 365 else 366 return NULL; 367 368 if (isa<loc::ConcreteInt>(V)) { 369 bool b = false; 370 if (R->isBoundable()) { 371 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 372 if (TR->getValueType()->isObjCObjectPointerType()) { 373 os << "initialized to nil"; 374 b = true; 375 } 376 } 377 } 378 379 if (!b) 380 os << "initialized to a null pointer value"; 381 } 382 else if (isa<nonloc::ConcreteInt>(V)) { 383 os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); 384 } 385 else if (V.isUndef()) { 386 if (isa<VarRegion>(R)) { 387 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 388 if (VD->getInit()) 389 os << "initialized to a garbage value"; 390 else 391 os << "declared without an initial value"; 392 } 393 } 394 else { 395 os << "initialized here"; 396 } 397 } 398 } else if (isa<CallEnter>(StoreSite->getLocation())) { 399 const ParmVarDecl *Param = cast<ParmVarDecl>(cast<VarRegion>(R)->getDecl()); 400 401 os << "Passing "; 402 403 if (isa<loc::ConcreteInt>(V)) { 404 if (Param->getType()->isObjCObjectPointerType()) 405 os << "nil object reference"; 406 else 407 os << "null pointer value"; 408 } else if (V.isUndef()) { 409 os << "uninitialized value"; 410 } else if (isa<nonloc::ConcreteInt>(V)) { 411 os << "the value " << cast<nonloc::ConcreteInt>(V).getValue(); 412 } else { 413 os << "value"; 414 } 415 416 // Printed parameter indexes are 1-based, not 0-based. 417 unsigned Idx = Param->getFunctionScopeIndex() + 1; 418 os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter '"; 419 420 R->printPretty(os); 421 os << '\''; 422 } 423 424 if (os.str().empty()) { 425 if (isa<loc::ConcreteInt>(V)) { 426 bool b = false; 427 if (R->isBoundable()) { 428 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 429 if (TR->getValueType()->isObjCObjectPointerType()) { 430 os << "nil object reference stored to "; 431 b = true; 432 } 433 } 434 } 435 436 if (!b) 437 os << "Null pointer value stored to "; 438 } 439 else if (V.isUndef()) { 440 os << "Uninitialized value stored to "; 441 } 442 else if (isa<nonloc::ConcreteInt>(V)) { 443 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() 444 << " is assigned to "; 445 } 446 else 447 os << "Value assigned to "; 448 449 os << '\''; 450 R->printPretty(os); 451 os << '\''; 452 } 453 454 // Construct a new PathDiagnosticPiece. 455 ProgramPoint P = StoreSite->getLocation(); 456 PathDiagnosticLocation L; 457 if (isa<CallEnter>(P)) 458 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(), 459 P.getLocationContext()); 460 else 461 L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); 462 if (!L.isValid()) 463 return NULL; 464 return new PathDiagnosticEventPiece(L, os.str()); 465} 466 467void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 468 static int tag = 0; 469 ID.AddPointer(&tag); 470 ID.AddBoolean(Assumption); 471 ID.Add(Constraint); 472} 473 474/// Return the tag associated with this visitor. This tag will be used 475/// to make all PathDiagnosticPieces created by this visitor. 476const char *TrackConstraintBRVisitor::getTag() { 477 return "TrackConstraintBRVisitor"; 478} 479 480PathDiagnosticPiece * 481TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 482 const ExplodedNode *PrevN, 483 BugReporterContext &BRC, 484 BugReport &BR) { 485 if (isSatisfied) 486 return NULL; 487 488 // Check if in the previous state it was feasible for this constraint 489 // to *not* be true. 490 if (PrevN->getState()->assume(Constraint, !Assumption)) { 491 492 isSatisfied = true; 493 494 // As a sanity check, make sure that the negation of the constraint 495 // was infeasible in the current state. If it is feasible, we somehow 496 // missed the transition point. 497 if (N->getState()->assume(Constraint, !Assumption)) 498 return NULL; 499 500 // We found the transition point for the constraint. We now need to 501 // pretty-print the constraint. (work-in-progress) 502 std::string sbuf; 503 llvm::raw_string_ostream os(sbuf); 504 505 if (isa<Loc>(Constraint)) { 506 os << "Assuming pointer value is "; 507 os << (Assumption ? "non-null" : "null"); 508 } 509 510 if (os.str().empty()) 511 return NULL; 512 513 // Construct a new PathDiagnosticPiece. 514 ProgramPoint P = N->getLocation(); 515 PathDiagnosticLocation L = 516 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 517 if (!L.isValid()) 518 return NULL; 519 520 PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str()); 521 X->setTag(getTag()); 522 return X; 523 } 524 525 return NULL; 526} 527 528void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, 529 BugReport &report, bool IsArg) { 530 if (!S || !N) 531 return; 532 533 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) 534 S = OVE->getSourceExpr(); 535 536 if (IsArg) { 537 assert(isa<CallEnter>(N->getLocation()) && "Tracking arg but not at call"); 538 } else { 539 // Walk through nodes until we get one that matches the statement exactly. 540 do { 541 const ProgramPoint &pp = N->getLocation(); 542 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { 543 if (ps->getStmt() == S) 544 break; 545 } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&pp)) { 546 if (CEE->getCalleeContext()->getCallSite() == S) 547 break; 548 } 549 N = N->getFirstPred(); 550 } while (N); 551 552 if (!N) 553 return; 554 } 555 556 ProgramStateRef state = N->getState(); 557 558 // See if the expression we're interested refers to a variable. 559 // If so, we can track both its contents and constraints on its value. 560 if (const Expr *Ex = dyn_cast<Expr>(S)) { 561 // Strip off parens and casts. Note that this will never have issues with 562 // C++ user-defined implicit conversions, because those have a constructor 563 // or function call inside. 564 Ex = Ex->IgnoreParenCasts(); 565 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 566 // FIXME: Right now we only track VarDecls because it's non-trivial to 567 // get a MemRegion for any other DeclRefExprs. <rdar://problem/12114812> 568 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 569 ProgramStateManager &StateMgr = state->getStateManager(); 570 MemRegionManager &MRMgr = StateMgr.getRegionManager(); 571 const VarRegion *R = MRMgr.getVarRegion(VD, N->getLocationContext()); 572 573 // Mark both the variable region and its contents as interesting. 574 SVal V = state->getRawSVal(loc::MemRegionVal(R)); 575 576 // If the value matches the default for the variable region, that 577 // might mean that it's been cleared out of the state. Fall back to 578 // the full argument expression (with casts and such intact). 579 if (IsArg) { 580 bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant(); 581 if (!UseArgValue) { 582 const SymbolRegionValue *SRV = 583 dyn_cast_or_null<SymbolRegionValue>(V.getAsLocSymbol()); 584 if (SRV) 585 UseArgValue = (SRV->getRegion() == R); 586 } 587 if (UseArgValue) 588 V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 589 } 590 591 report.markInteresting(R); 592 report.markInteresting(V); 593 report.addVisitor(new UndefOrNullArgVisitor(R)); 594 595 // If the contents are symbolic, find out when they became null. 596 if (V.getAsLocSymbol()) { 597 BugReporterVisitor *ConstraintTracker 598 = new TrackConstraintBRVisitor(cast<DefinedSVal>(V), false); 599 report.addVisitor(ConstraintTracker); 600 } 601 602 report.addVisitor(new FindLastStoreBRVisitor(V, R)); 603 return; 604 } 605 } 606 } 607 608 // If the expression does NOT refer to a variable, we can still track 609 // constraints on its contents. 610 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 611 612 // Uncomment this to find cases where we aren't properly getting the 613 // base value that was dereferenced. 614 // assert(!V.isUnknownOrUndef()); 615 616 // Is it a symbolic value? 617 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) { 618 // At this point we are dealing with the region's LValue. 619 // However, if the rvalue is a symbolic region, we should track it as well. 620 SVal RVal = state->getSVal(L->getRegion()); 621 const MemRegion *RegionRVal = RVal.getAsRegion(); 622 report.addVisitor(new UndefOrNullArgVisitor(L->getRegion())); 623 624 625 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { 626 report.markInteresting(RegionRVal); 627 report.addVisitor(new TrackConstraintBRVisitor( 628 loc::MemRegionVal(RegionRVal), false)); 629 } 630 } else { 631 // Otherwise, if the value came from an inlined function call, 632 // we should at least make sure that function isn't pruned in our output. 633 if (const Expr *E = dyn_cast<Expr>(S)) 634 S = E->IgnoreParenCasts(); 635 ReturnVisitor::addVisitorIfNecessary(N, S, report); 636 } 637} 638 639BugReporterVisitor * 640FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N, 641 const MemRegion *R) { 642 assert(R && "The memory region is null."); 643 644 ProgramStateRef state = N->getState(); 645 SVal V = state->getSVal(R); 646 if (V.isUnknown()) 647 return 0; 648 649 return new FindLastStoreBRVisitor(V, R); 650} 651 652 653PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 654 const ExplodedNode *PrevN, 655 BugReporterContext &BRC, 656 BugReport &BR) { 657 const PostStmt *P = N->getLocationAs<PostStmt>(); 658 if (!P) 659 return 0; 660 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 661 if (!ME) 662 return 0; 663 const Expr *Receiver = ME->getInstanceReceiver(); 664 if (!Receiver) 665 return 0; 666 ProgramStateRef state = N->getState(); 667 const SVal &V = state->getSVal(Receiver, N->getLocationContext()); 668 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); 669 if (!DV) 670 return 0; 671 state = state->assume(*DV, true); 672 if (state) 673 return 0; 674 675 // The receiver was nil, and hence the method was skipped. 676 // Register a BugReporterVisitor to issue a message telling us how 677 // the receiver was null. 678 bugreporter::trackNullOrUndefValue(N, Receiver, BR); 679 // Issue a message saying that the method was skipped. 680 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 681 N->getLocationContext()); 682 return new PathDiagnosticEventPiece(L, "No method is called " 683 "because the receiver is nil"); 684} 685 686// Registers every VarDecl inside a Stmt with a last store visitor. 687void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 688 const Stmt *S) { 689 const ExplodedNode *N = BR.getErrorNode(); 690 std::deque<const Stmt *> WorkList; 691 WorkList.push_back(S); 692 693 while (!WorkList.empty()) { 694 const Stmt *Head = WorkList.front(); 695 WorkList.pop_front(); 696 697 ProgramStateRef state = N->getState(); 698 ProgramStateManager &StateMgr = state->getStateManager(); 699 700 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 701 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 702 const VarRegion *R = 703 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 704 705 // What did we load? 706 SVal V = state->getSVal(S, N->getLocationContext()); 707 708 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { 709 // Register a new visitor with the BugReport. 710 BR.addVisitor(new FindLastStoreBRVisitor(V, R)); 711 } 712 } 713 } 714 715 for (Stmt::const_child_iterator I = Head->child_begin(); 716 I != Head->child_end(); ++I) 717 WorkList.push_back(*I); 718 } 719} 720 721//===----------------------------------------------------------------------===// 722// Visitor that tries to report interesting diagnostics from conditions. 723//===----------------------------------------------------------------------===// 724 725/// Return the tag associated with this visitor. This tag will be used 726/// to make all PathDiagnosticPieces created by this visitor. 727const char *ConditionBRVisitor::getTag() { 728 return "ConditionBRVisitor"; 729} 730 731PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 732 const ExplodedNode *Prev, 733 BugReporterContext &BRC, 734 BugReport &BR) { 735 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR); 736 if (piece) { 737 piece->setTag(getTag()); 738 if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece)) 739 ev->setPrunable(true, /* override */ false); 740 } 741 return piece; 742} 743 744PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 745 const ExplodedNode *Prev, 746 BugReporterContext &BRC, 747 BugReport &BR) { 748 749 ProgramPoint progPoint = N->getLocation(); 750 ProgramStateRef CurrentState = N->getState(); 751 ProgramStateRef PrevState = Prev->getState(); 752 753 // Compare the GDMs of the state, because that is where constraints 754 // are managed. Note that ensure that we only look at nodes that 755 // were generated by the analyzer engine proper, not checkers. 756 if (CurrentState->getGDM().getRoot() == 757 PrevState->getGDM().getRoot()) 758 return 0; 759 760 // If an assumption was made on a branch, it should be caught 761 // here by looking at the state transition. 762 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) { 763 const CFGBlock *srcBlk = BE->getSrc(); 764 if (const Stmt *term = srcBlk->getTerminator()) 765 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); 766 return 0; 767 } 768 769 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) { 770 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 771 // violation. 772 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 773 cast<GRBugReporter>(BRC.getBugReporter()). 774 getEngine().geteagerlyAssumeBinOpBifurcationTags(); 775 776 const ProgramPointTag *tag = PS->getTag(); 777 if (tag == tags.first) 778 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 779 BRC, BR, N); 780 if (tag == tags.second) 781 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 782 BRC, BR, N); 783 784 return 0; 785 } 786 787 return 0; 788} 789 790PathDiagnosticPiece * 791ConditionBRVisitor::VisitTerminator(const Stmt *Term, 792 const ExplodedNode *N, 793 const CFGBlock *srcBlk, 794 const CFGBlock *dstBlk, 795 BugReport &R, 796 BugReporterContext &BRC) { 797 const Expr *Cond = 0; 798 799 switch (Term->getStmtClass()) { 800 default: 801 return 0; 802 case Stmt::IfStmtClass: 803 Cond = cast<IfStmt>(Term)->getCond(); 804 break; 805 case Stmt::ConditionalOperatorClass: 806 Cond = cast<ConditionalOperator>(Term)->getCond(); 807 break; 808 } 809 810 assert(Cond); 811 assert(srcBlk->succ_size() == 2); 812 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 813 return VisitTrueTest(Cond, tookTrue, BRC, R, N); 814} 815 816PathDiagnosticPiece * 817ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 818 bool tookTrue, 819 BugReporterContext &BRC, 820 BugReport &R, 821 const ExplodedNode *N) { 822 823 const Expr *Ex = Cond; 824 825 while (true) { 826 Ex = Ex->IgnoreParenCasts(); 827 switch (Ex->getStmtClass()) { 828 default: 829 return 0; 830 case Stmt::BinaryOperatorClass: 831 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, 832 R, N); 833 case Stmt::DeclRefExprClass: 834 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, 835 R, N); 836 case Stmt::UnaryOperatorClass: { 837 const UnaryOperator *UO = cast<UnaryOperator>(Ex); 838 if (UO->getOpcode() == UO_LNot) { 839 tookTrue = !tookTrue; 840 Ex = UO->getSubExpr(); 841 continue; 842 } 843 return 0; 844 } 845 } 846 } 847} 848 849bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out, 850 BugReporterContext &BRC, 851 BugReport &report, 852 const ExplodedNode *N, 853 llvm::Optional<bool> &prunable) { 854 const Expr *OriginalExpr = Ex; 855 Ex = Ex->IgnoreParenCasts(); 856 857 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 858 const bool quotes = isa<VarDecl>(DR->getDecl()); 859 if (quotes) { 860 Out << '\''; 861 const LocationContext *LCtx = N->getLocationContext(); 862 const ProgramState *state = N->getState().getPtr(); 863 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 864 LCtx).getAsRegion()) { 865 if (report.isInteresting(R)) 866 prunable = false; 867 else { 868 const ProgramState *state = N->getState().getPtr(); 869 SVal V = state->getSVal(R); 870 if (report.isInteresting(V)) 871 prunable = false; 872 } 873 } 874 } 875 Out << DR->getDecl()->getDeclName().getAsString(); 876 if (quotes) 877 Out << '\''; 878 return quotes; 879 } 880 881 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 882 QualType OriginalTy = OriginalExpr->getType(); 883 if (OriginalTy->isPointerType()) { 884 if (IL->getValue() == 0) { 885 Out << "null"; 886 return false; 887 } 888 } 889 else if (OriginalTy->isObjCObjectPointerType()) { 890 if (IL->getValue() == 0) { 891 Out << "nil"; 892 return false; 893 } 894 } 895 896 Out << IL->getValue(); 897 return false; 898 } 899 900 return false; 901} 902 903PathDiagnosticPiece * 904ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 905 const BinaryOperator *BExpr, 906 const bool tookTrue, 907 BugReporterContext &BRC, 908 BugReport &R, 909 const ExplodedNode *N) { 910 911 bool shouldInvert = false; 912 llvm::Optional<bool> shouldPrune; 913 914 SmallString<128> LhsString, RhsString; 915 { 916 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 917 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, 918 shouldPrune); 919 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, 920 shouldPrune); 921 922 shouldInvert = !isVarLHS && isVarRHS; 923 } 924 925 BinaryOperator::Opcode Op = BExpr->getOpcode(); 926 927 if (BinaryOperator::isAssignmentOp(Op)) { 928 // For assignment operators, all that we care about is that the LHS 929 // evaluates to "true" or "false". 930 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 931 BRC, R, N); 932 } 933 934 // For non-assignment operations, we require that we can understand 935 // both the LHS and RHS. 936 if (LhsString.empty() || RhsString.empty()) 937 return 0; 938 939 // Should we invert the strings if the LHS is not a variable name? 940 SmallString<256> buf; 941 llvm::raw_svector_ostream Out(buf); 942 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 943 944 // Do we need to invert the opcode? 945 if (shouldInvert) 946 switch (Op) { 947 default: break; 948 case BO_LT: Op = BO_GT; break; 949 case BO_GT: Op = BO_LT; break; 950 case BO_LE: Op = BO_GE; break; 951 case BO_GE: Op = BO_LE; break; 952 } 953 954 if (!tookTrue) 955 switch (Op) { 956 case BO_EQ: Op = BO_NE; break; 957 case BO_NE: Op = BO_EQ; break; 958 case BO_LT: Op = BO_GE; break; 959 case BO_GT: Op = BO_LE; break; 960 case BO_LE: Op = BO_GT; break; 961 case BO_GE: Op = BO_LT; break; 962 default: 963 return 0; 964 } 965 966 switch (Op) { 967 case BO_EQ: 968 Out << "equal to "; 969 break; 970 case BO_NE: 971 Out << "not equal to "; 972 break; 973 default: 974 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 975 break; 976 } 977 978 Out << (shouldInvert ? LhsString : RhsString); 979 const LocationContext *LCtx = N->getLocationContext(); 980 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 981 PathDiagnosticEventPiece *event = 982 new PathDiagnosticEventPiece(Loc, Out.str()); 983 if (shouldPrune.hasValue()) 984 event->setPrunable(shouldPrune.getValue()); 985 return event; 986} 987 988PathDiagnosticPiece * 989ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 990 const Expr *CondVarExpr, 991 const bool tookTrue, 992 BugReporterContext &BRC, 993 BugReport &report, 994 const ExplodedNode *N) { 995 // FIXME: If there's already a constraint tracker for this variable, 996 // we shouldn't emit anything here (c.f. the double note in 997 // test/Analysis/inlining/path-notes.c) 998 SmallString<256> buf; 999 llvm::raw_svector_ostream Out(buf); 1000 Out << "Assuming " << LhsString << " is "; 1001 1002 QualType Ty = CondVarExpr->getType(); 1003 1004 if (Ty->isPointerType()) 1005 Out << (tookTrue ? "not null" : "null"); 1006 else if (Ty->isObjCObjectPointerType()) 1007 Out << (tookTrue ? "not nil" : "nil"); 1008 else if (Ty->isBooleanType()) 1009 Out << (tookTrue ? "true" : "false"); 1010 else if (Ty->isIntegerType()) 1011 Out << (tookTrue ? "non-zero" : "zero"); 1012 else 1013 return 0; 1014 1015 const LocationContext *LCtx = N->getLocationContext(); 1016 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 1017 PathDiagnosticEventPiece *event = 1018 new PathDiagnosticEventPiece(Loc, Out.str()); 1019 1020 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { 1021 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 1022 const ProgramState *state = N->getState().getPtr(); 1023 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1024 if (report.isInteresting(R)) 1025 event->setPrunable(false); 1026 } 1027 } 1028 } 1029 1030 return event; 1031} 1032 1033PathDiagnosticPiece * 1034ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 1035 const DeclRefExpr *DR, 1036 const bool tookTrue, 1037 BugReporterContext &BRC, 1038 BugReport &report, 1039 const ExplodedNode *N) { 1040 1041 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 1042 if (!VD) 1043 return 0; 1044 1045 SmallString<256> Buf; 1046 llvm::raw_svector_ostream Out(Buf); 1047 1048 Out << "Assuming '"; 1049 VD->getDeclName().printName(Out); 1050 Out << "' is "; 1051 1052 QualType VDTy = VD->getType(); 1053 1054 if (VDTy->isPointerType()) 1055 Out << (tookTrue ? "non-null" : "null"); 1056 else if (VDTy->isObjCObjectPointerType()) 1057 Out << (tookTrue ? "non-nil" : "nil"); 1058 else if (VDTy->isScalarType()) 1059 Out << (tookTrue ? "not equal to 0" : "0"); 1060 else 1061 return 0; 1062 1063 const LocationContext *LCtx = N->getLocationContext(); 1064 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 1065 PathDiagnosticEventPiece *event = 1066 new PathDiagnosticEventPiece(Loc, Out.str()); 1067 1068 const ProgramState *state = N->getState().getPtr(); 1069 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1070 if (report.isInteresting(R)) 1071 event->setPrunable(false); 1072 else { 1073 SVal V = state->getSVal(R); 1074 if (report.isInteresting(V)) 1075 event->setPrunable(false); 1076 } 1077 } 1078 return event; 1079} 1080 1081PathDiagnosticPiece * 1082UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, 1083 const ExplodedNode *PrevN, 1084 BugReporterContext &BRC, 1085 BugReport &BR) { 1086 1087 ProgramStateRef State = N->getState(); 1088 ProgramPoint ProgLoc = N->getLocation(); 1089 1090 // We are only interested in visiting CallEnter nodes. 1091 CallEnter *CEnter = dyn_cast<CallEnter>(&ProgLoc); 1092 if (!CEnter) 1093 return 0; 1094 1095 // Check if one of the arguments is the region the visitor is tracking. 1096 CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); 1097 CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); 1098 unsigned Idx = 0; 1099 for (CallEvent::param_iterator I = Call->param_begin(), 1100 E = Call->param_end(); I != E; ++I, ++Idx) { 1101 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); 1102 1103 // Are we tracking the argument or its subregion? 1104 if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) 1105 continue; 1106 1107 // Check the function parameter type. 1108 const ParmVarDecl *ParamDecl = *I; 1109 assert(ParamDecl && "Formal parameter has no decl?"); 1110 QualType T = ParamDecl->getType(); 1111 1112 if (!(T->isAnyPointerType() || T->isReferenceType())) { 1113 // Function can only change the value passed in by address. 1114 continue; 1115 } 1116 1117 // If it is a const pointer value, the function does not intend to 1118 // change the value. 1119 if (T->getPointeeType().isConstQualified()) 1120 continue; 1121 1122 // Mark the call site (LocationContext) as interesting if the value of the 1123 // argument is undefined or '0'/'NULL'. 1124 SVal BoundVal = State->getSVal(R); 1125 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { 1126 BR.markInteresting(CEnter->getCalleeContext()); 1127 return 0; 1128 } 1129 } 1130 return 0; 1131} 1132