1 //==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- 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 the methods for RetainCountChecker, which implements 11 // a reference count checker for Core Foundation and Cocoa on (Mac OS X). 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "RetainCountChecker.h" 16 17 using namespace clang; 18 using namespace ento; 19 using namespace retaincountchecker; 20 using llvm::StrInStrNoCase; 21 22 REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal) 23 24 namespace clang { 25 namespace ento { 26 namespace retaincountchecker { 27 28 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) { 29 return State->get<RefBindings>(Sym); 30 } 31 32 ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, 33 RefVal Val) { 34 assert(Sym != nullptr); 35 return State->set<RefBindings>(Sym, Val); 36 } 37 38 ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) { 39 return State->remove<RefBindings>(Sym); 40 } 41 42 class UseAfterRelease : public RefCountBug { 43 public: 44 UseAfterRelease(const CheckerBase *checker) 45 : RefCountBug(checker, "Use-after-release") {} 46 47 const char *getDescription() const override { 48 return "Reference-counted object is used after it is released"; 49 } 50 }; 51 52 class BadRelease : public RefCountBug { 53 public: 54 BadRelease(const CheckerBase *checker) : RefCountBug(checker, "Bad release") {} 55 56 const char *getDescription() const override { 57 return "Incorrect decrement of the reference count of an object that is " 58 "not owned at this point by the caller"; 59 } 60 }; 61 62 class DeallocNotOwned : public RefCountBug { 63 public: 64 DeallocNotOwned(const CheckerBase *checker) 65 : RefCountBug(checker, "-dealloc sent to non-exclusively owned object") {} 66 67 const char *getDescription() const override { 68 return "-dealloc sent to object that may be referenced elsewhere"; 69 } 70 }; 71 72 class OverAutorelease : public RefCountBug { 73 public: 74 OverAutorelease(const CheckerBase *checker) 75 : RefCountBug(checker, "Object autoreleased too many times") {} 76 77 const char *getDescription() const override { 78 return "Object autoreleased too many times"; 79 } 80 }; 81 82 class ReturnedNotOwnedForOwned : public RefCountBug { 83 public: 84 ReturnedNotOwnedForOwned(const CheckerBase *checker) 85 : RefCountBug(checker, "Method should return an owned object") {} 86 87 const char *getDescription() const override { 88 return "Object with a +0 retain count returned to caller where a +1 " 89 "(owning) retain count is expected"; 90 } 91 }; 92 93 class Leak : public RefCountBug { 94 public: 95 Leak(const CheckerBase *checker, StringRef name) : RefCountBug(checker, name) { 96 // Leaks should not be reported if they are post-dominated by a sink. 97 setSuppressOnSink(true); 98 } 99 100 const char *getDescription() const override { return ""; } 101 102 bool isLeak() const override { return true; } 103 }; 104 105 } // end namespace retaincountchecker 106 } // end namespace ento 107 } // end namespace clang 108 109 void RefVal::print(raw_ostream &Out) const { 110 if (!T.isNull()) 111 Out << "Tracked " << T.getAsString() << " | "; 112 113 switch (getKind()) { 114 default: llvm_unreachable("Invalid RefVal kind"); 115 case Owned: { 116 Out << "Owned"; 117 unsigned cnt = getCount(); 118 if (cnt) Out << " (+ " << cnt << ")"; 119 break; 120 } 121 122 case NotOwned: { 123 Out << "NotOwned"; 124 unsigned cnt = getCount(); 125 if (cnt) Out << " (+ " << cnt << ")"; 126 break; 127 } 128 129 case ReturnedOwned: { 130 Out << "ReturnedOwned"; 131 unsigned cnt = getCount(); 132 if (cnt) Out << " (+ " << cnt << ")"; 133 break; 134 } 135 136 case ReturnedNotOwned: { 137 Out << "ReturnedNotOwned"; 138 unsigned cnt = getCount(); 139 if (cnt) Out << " (+ " << cnt << ")"; 140 break; 141 } 142 143 case Released: 144 Out << "Released"; 145 break; 146 147 case ErrorDeallocNotOwned: 148 Out << "-dealloc (not-owned)"; 149 break; 150 151 case ErrorLeak: 152 Out << "Leaked"; 153 break; 154 155 case ErrorLeakReturned: 156 Out << "Leaked (Bad naming)"; 157 break; 158 159 case ErrorUseAfterRelease: 160 Out << "Use-After-Release [ERROR]"; 161 break; 162 163 case ErrorReleaseNotOwned: 164 Out << "Release of Not-Owned [ERROR]"; 165 break; 166 167 case RefVal::ErrorOverAutorelease: 168 Out << "Over-autoreleased"; 169 break; 170 171 case RefVal::ErrorReturnedNotOwned: 172 Out << "Non-owned object returned instead of owned"; 173 break; 174 } 175 176 switch (getIvarAccessHistory()) { 177 case IvarAccessHistory::None: 178 break; 179 case IvarAccessHistory::AccessedDirectly: 180 Out << " [direct ivar access]"; 181 break; 182 case IvarAccessHistory::ReleasedAfterDirectAccess: 183 Out << " [released after direct ivar access]"; 184 } 185 186 if (ACnt) { 187 Out << " [autorelease -" << ACnt << ']'; 188 } 189 } 190 191 namespace { 192 class StopTrackingCallback final : public SymbolVisitor { 193 ProgramStateRef state; 194 public: 195 StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {} 196 ProgramStateRef getState() const { return state; } 197 198 bool VisitSymbol(SymbolRef sym) override { 199 state = state->remove<RefBindings>(sym); 200 return true; 201 } 202 }; 203 } // end anonymous namespace 204 205 //===----------------------------------------------------------------------===// 206 // Handle statements that may have an effect on refcounts. 207 //===----------------------------------------------------------------------===// 208 209 void RetainCountChecker::checkPostStmt(const BlockExpr *BE, 210 CheckerContext &C) const { 211 212 // Scan the BlockDecRefExprs for any object the retain count checker 213 // may be tracking. 214 if (!BE->getBlockDecl()->hasCaptures()) 215 return; 216 217 ProgramStateRef state = C.getState(); 218 auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion()); 219 220 BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), 221 E = R->referenced_vars_end(); 222 223 if (I == E) 224 return; 225 226 // FIXME: For now we invalidate the tracking of all symbols passed to blocks 227 // via captured variables, even though captured variables result in a copy 228 // and in implicit increment/decrement of a retain count. 229 SmallVector<const MemRegion*, 10> Regions; 230 const LocationContext *LC = C.getLocationContext(); 231 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager(); 232 233 for ( ; I != E; ++I) { 234 const VarRegion *VR = I.getCapturedRegion(); 235 if (VR->getSuperRegion() == R) { 236 VR = MemMgr.getVarRegion(VR->getDecl(), LC); 237 } 238 Regions.push_back(VR); 239 } 240 241 state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState(); 242 C.addTransition(state); 243 } 244 245 void RetainCountChecker::checkPostStmt(const CastExpr *CE, 246 CheckerContext &C) const { 247 const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE); 248 if (!BE) 249 return; 250 251 ArgEffect AE = ArgEffect(IncRef, ObjKind::ObjC); 252 253 switch (BE->getBridgeKind()) { 254 case OBC_Bridge: 255 // Do nothing. 256 return; 257 case OBC_BridgeRetained: 258 AE = AE.withKind(IncRef); 259 break; 260 case OBC_BridgeTransfer: 261 AE = AE.withKind(DecRefBridgedTransferred); 262 break; 263 } 264 265 ProgramStateRef state = C.getState(); 266 SymbolRef Sym = C.getSVal(CE).getAsLocSymbol(); 267 if (!Sym) 268 return; 269 const RefVal* T = getRefBinding(state, Sym); 270 if (!T) 271 return; 272 273 RefVal::Kind hasErr = (RefVal::Kind) 0; 274 state = updateSymbol(state, Sym, *T, AE, hasErr, C); 275 276 if (hasErr) { 277 // FIXME: If we get an error during a bridge cast, should we report it? 278 return; 279 } 280 281 C.addTransition(state); 282 } 283 284 void RetainCountChecker::processObjCLiterals(CheckerContext &C, 285 const Expr *Ex) const { 286 ProgramStateRef state = C.getState(); 287 const ExplodedNode *pred = C.getPredecessor(); 288 for (const Stmt *Child : Ex->children()) { 289 SVal V = pred->getSVal(Child); 290 if (SymbolRef sym = V.getAsSymbol()) 291 if (const RefVal* T = getRefBinding(state, sym)) { 292 RefVal::Kind hasErr = (RefVal::Kind) 0; 293 state = updateSymbol(state, sym, *T, 294 ArgEffect(MayEscape, ObjKind::ObjC), hasErr, C); 295 if (hasErr) { 296 processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C); 297 return; 298 } 299 } 300 } 301 302 // Return the object as autoreleased. 303 // RetEffect RE = RetEffect::MakeNotOwned(ObjKind::ObjC); 304 if (SymbolRef sym = 305 state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) { 306 QualType ResultTy = Ex->getType(); 307 state = setRefBinding(state, sym, 308 RefVal::makeNotOwned(ObjKind::ObjC, ResultTy)); 309 } 310 311 C.addTransition(state); 312 } 313 314 void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL, 315 CheckerContext &C) const { 316 // Apply the 'MayEscape' to all values. 317 processObjCLiterals(C, AL); 318 } 319 320 void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL, 321 CheckerContext &C) const { 322 // Apply the 'MayEscape' to all keys and values. 323 processObjCLiterals(C, DL); 324 } 325 326 void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex, 327 CheckerContext &C) const { 328 const ExplodedNode *Pred = C.getPredecessor(); 329 ProgramStateRef State = Pred->getState(); 330 331 if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) { 332 QualType ResultTy = Ex->getType(); 333 State = setRefBinding(State, Sym, 334 RefVal::makeNotOwned(ObjKind::ObjC, ResultTy)); 335 } 336 337 C.addTransition(State); 338 } 339 340 void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE, 341 CheckerContext &C) const { 342 Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>(); 343 if (!IVarLoc) 344 return; 345 346 ProgramStateRef State = C.getState(); 347 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol(); 348 if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion())) 349 return; 350 351 // Accessing an ivar directly is unusual. If we've done that, be more 352 // forgiving about what the surrounding code is allowed to do. 353 354 QualType Ty = Sym->getType(); 355 ObjKind Kind; 356 if (Ty->isObjCRetainableType()) 357 Kind = ObjKind::ObjC; 358 else if (coreFoundation::isCFObjectRef(Ty)) 359 Kind = ObjKind::CF; 360 else 361 return; 362 363 // If the value is already known to be nil, don't bother tracking it. 364 ConstraintManager &CMgr = State->getConstraintManager(); 365 if (CMgr.isNull(State, Sym).isConstrainedTrue()) 366 return; 367 368 if (const RefVal *RV = getRefBinding(State, Sym)) { 369 // If we've seen this symbol before, or we're only seeing it now because 370 // of something the analyzer has synthesized, don't do anything. 371 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None || 372 isSynthesizedAccessor(C.getStackFrame())) { 373 return; 374 } 375 376 // Note that this value has been loaded from an ivar. 377 C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess())); 378 return; 379 } 380 381 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty); 382 383 // In a synthesized accessor, the effective retain count is +0. 384 if (isSynthesizedAccessor(C.getStackFrame())) { 385 C.addTransition(setRefBinding(State, Sym, PlusZero)); 386 return; 387 } 388 389 State = setRefBinding(State, Sym, PlusZero.withIvarAccess()); 390 C.addTransition(State); 391 } 392 393 void RetainCountChecker::checkPostCall(const CallEvent &Call, 394 CheckerContext &C) const { 395 RetainSummaryManager &Summaries = getSummaryManager(C); 396 397 // Leave null if no receiver. 398 QualType ReceiverType; 399 if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) { 400 if (MC->isInstanceMessage()) { 401 SVal ReceiverV = MC->getReceiverSVal(); 402 if (SymbolRef Sym = ReceiverV.getAsLocSymbol()) 403 if (const RefVal *T = getRefBinding(C.getState(), Sym)) 404 ReceiverType = T->getType(); 405 } 406 } 407 408 const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType); 409 410 if (C.wasInlined) { 411 processSummaryOfInlined(*Summ, Call, C); 412 return; 413 } 414 checkSummary(*Summ, Call, C); 415 } 416 417 RefCountBug * 418 RetainCountChecker::getLeakWithinFunctionBug(const LangOptions &LOpts) const { 419 if (!leakWithinFunction) 420 leakWithinFunction.reset(new Leak(this, "Leak")); 421 return leakWithinFunction.get(); 422 } 423 424 RefCountBug * 425 RetainCountChecker::getLeakAtReturnBug(const LangOptions &LOpts) const { 426 if (!leakAtReturn) 427 leakAtReturn.reset(new Leak(this, "Leak of returned object")); 428 return leakAtReturn.get(); 429 } 430 431 /// GetReturnType - Used to get the return type of a message expression or 432 /// function call with the intention of affixing that type to a tracked symbol. 433 /// While the return type can be queried directly from RetEx, when 434 /// invoking class methods we augment to the return type to be that of 435 /// a pointer to the class (as opposed it just being id). 436 // FIXME: We may be able to do this with related result types instead. 437 // This function is probably overestimating. 438 static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) { 439 QualType RetTy = RetE->getType(); 440 // If RetE is not a message expression just return its type. 441 // If RetE is a message expression, return its types if it is something 442 /// more specific than id. 443 if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE)) 444 if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>()) 445 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() || 446 PT->isObjCClassType()) { 447 // At this point we know the return type of the message expression is 448 // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this 449 // is a call to a class method whose type we can resolve. In such 450 // cases, promote the return type to XXX* (where XXX is the class). 451 const ObjCInterfaceDecl *D = ME->getReceiverInterface(); 452 return !D ? RetTy : 453 Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D)); 454 } 455 456 return RetTy; 457 } 458 459 static Optional<RefVal> refValFromRetEffect(RetEffect RE, 460 QualType ResultTy) { 461 if (RE.isOwned()) { 462 return RefVal::makeOwned(RE.getObjKind(), ResultTy); 463 } else if (RE.notOwned()) { 464 return RefVal::makeNotOwned(RE.getObjKind(), ResultTy); 465 } 466 467 return None; 468 } 469 470 static bool isPointerToObject(QualType QT) { 471 QualType PT = QT->getPointeeType(); 472 if (!PT.isNull()) 473 if (PT->getAsCXXRecordDecl()) 474 return true; 475 return false; 476 } 477 478 /// Whether the tracked value should be escaped on a given call. 479 /// OSObjects are escaped when passed to void * / etc. 480 static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx, 481 const RefVal *TrackedValue) { 482 if (TrackedValue->getObjKind() != ObjKind::OS) 483 return false; 484 if (ArgIdx >= CE.parameters().size()) 485 return false; 486 return !isPointerToObject(CE.parameters()[ArgIdx]->getType()); 487 } 488 489 // We don't always get the exact modeling of the function with regards to the 490 // retain count checker even when the function is inlined. For example, we need 491 // to stop tracking the symbols which were marked with StopTrackingHard. 492 void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ, 493 const CallEvent &CallOrMsg, 494 CheckerContext &C) const { 495 ProgramStateRef state = C.getState(); 496 497 // Evaluate the effect of the arguments. 498 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) { 499 SVal V = CallOrMsg.getArgSVal(idx); 500 501 if (SymbolRef Sym = V.getAsLocSymbol()) { 502 bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard; 503 if (const RefVal *T = getRefBinding(state, Sym)) 504 if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T)) 505 ShouldRemoveBinding = true; 506 507 if (ShouldRemoveBinding) 508 state = removeRefBinding(state, Sym); 509 } 510 } 511 512 // Evaluate the effect on the message receiver. 513 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) { 514 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) { 515 if (Summ.getReceiverEffect().getKind() == StopTrackingHard) { 516 state = removeRefBinding(state, Sym); 517 } 518 } 519 } 520 521 // Consult the summary for the return value. 522 RetEffect RE = Summ.getRetEffect(); 523 524 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) { 525 if (RE.getKind() == RetEffect::NoRetHard) 526 state = removeRefBinding(state, Sym); 527 } 528 529 C.addTransition(state); 530 } 531 532 static ProgramStateRef updateOutParameter(ProgramStateRef State, 533 SVal ArgVal, 534 ArgEffectKind Effect) { 535 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion()); 536 if (!ArgRegion) 537 return State; 538 539 QualType PointeeTy = ArgRegion->getValueType(); 540 if (!coreFoundation::isCFObjectRef(PointeeTy)) 541 return State; 542 543 SVal PointeeVal = State->getSVal(ArgRegion); 544 SymbolRef Pointee = PointeeVal.getAsLocSymbol(); 545 if (!Pointee) 546 return State; 547 548 switch (Effect) { 549 case UnretainedOutParameter: 550 State = setRefBinding(State, Pointee, 551 RefVal::makeNotOwned(ObjKind::CF, PointeeTy)); 552 break; 553 case RetainedOutParameter: 554 // Do nothing. Retained out parameters will either point to a +1 reference 555 // or NULL, but the way you check for failure differs depending on the API. 556 // Consequently, we don't have a good way to track them yet. 557 break; 558 559 default: 560 llvm_unreachable("only for out parameters"); 561 } 562 563 return State; 564 } 565 566 void RetainCountChecker::checkSummary(const RetainSummary &Summ, 567 const CallEvent &CallOrMsg, 568 CheckerContext &C) const { 569 ProgramStateRef state = C.getState(); 570 571 // Evaluate the effect of the arguments. 572 RefVal::Kind hasErr = (RefVal::Kind) 0; 573 SourceRange ErrorRange; 574 SymbolRef ErrorSym = nullptr; 575 576 // Helper tag for providing diagnostics: indicate whether dealloc was sent 577 // at this location. 578 static CheckerProgramPointTag DeallocSentTag(this, DeallocTagDescription); 579 bool DeallocSent = false; 580 581 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) { 582 SVal V = CallOrMsg.getArgSVal(idx); 583 584 ArgEffect Effect = Summ.getArg(idx); 585 if (Effect.getKind() == RetainedOutParameter || 586 Effect.getKind() == UnretainedOutParameter) { 587 state = updateOutParameter(state, V, Effect.getKind()); 588 } else if (SymbolRef Sym = V.getAsLocSymbol()) { 589 if (const RefVal *T = getRefBinding(state, Sym)) { 590 591 if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T)) 592 Effect = ArgEffect(StopTrackingHard, ObjKind::OS); 593 594 state = updateSymbol(state, Sym, *T, Effect, hasErr, C); 595 if (hasErr) { 596 ErrorRange = CallOrMsg.getArgSourceRange(idx); 597 ErrorSym = Sym; 598 break; 599 } else if (Effect.getKind() == Dealloc) { 600 DeallocSent = true; 601 } 602 } 603 } 604 } 605 606 // Evaluate the effect on the message receiver / `this` argument. 607 bool ReceiverIsTracked = false; 608 if (!hasErr) { 609 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) { 610 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) { 611 if (const RefVal *T = getRefBinding(state, Sym)) { 612 ReceiverIsTracked = true; 613 state = updateSymbol(state, Sym, *T, 614 Summ.getReceiverEffect(), hasErr, C); 615 if (hasErr) { 616 ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange(); 617 ErrorSym = Sym; 618 } else if (Summ.getReceiverEffect().getKind() == Dealloc) { 619 DeallocSent = true; 620 } 621 } 622 } 623 } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) { 624 if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) { 625 if (const RefVal *T = getRefBinding(state, Sym)) { 626 state = updateSymbol(state, Sym, *T, Summ.getThisEffect(), 627 hasErr, C); 628 if (hasErr) { 629 ErrorRange = MCall->getOriginExpr()->getSourceRange(); 630 ErrorSym = Sym; 631 } 632 } 633 } 634 } 635 } 636 637 // Process any errors. 638 if (hasErr) { 639 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C); 640 return; 641 } 642 643 // Consult the summary for the return value. 644 RetEffect RE = Summ.getRetEffect(); 645 646 if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) { 647 if (ReceiverIsTracked) 648 RE = getSummaryManager(C).getObjAllocRetEffect(); 649 else 650 RE = RetEffect::MakeNoRet(); 651 } 652 653 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) { 654 QualType ResultTy = CallOrMsg.getResultType(); 655 if (RE.notOwned()) { 656 const Expr *Ex = CallOrMsg.getOriginExpr(); 657 assert(Ex); 658 ResultTy = GetReturnType(Ex, C.getASTContext()); 659 } 660 if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy)) 661 state = setRefBinding(state, Sym, *updatedRefVal); 662 } 663 664 if (DeallocSent) { 665 C.addTransition(state, C.getPredecessor(), &DeallocSentTag); 666 } else { 667 C.addTransition(state); 668 } 669 } 670 671 ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state, 672 SymbolRef sym, RefVal V, 673 ArgEffect AE, 674 RefVal::Kind &hasErr, 675 CheckerContext &C) const { 676 bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount; 677 if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) { 678 switch (AE.getKind()) { 679 default: 680 break; 681 case IncRef: 682 AE = AE.withKind(DoNothing); 683 break; 684 case DecRef: 685 AE = AE.withKind(DoNothing); 686 break; 687 case DecRefAndStopTrackingHard: 688 AE = AE.withKind(StopTracking); 689 break; 690 } 691 } 692 693 // Handle all use-after-releases. 694 if (V.getKind() == RefVal::Released) { 695 V = V ^ RefVal::ErrorUseAfterRelease; 696 hasErr = V.getKind(); 697 return setRefBinding(state, sym, V); 698 } 699 700 switch (AE.getKind()) { 701 case UnretainedOutParameter: 702 case RetainedOutParameter: 703 llvm_unreachable("Applies to pointer-to-pointer parameters, which should " 704 "not have ref state."); 705 706 case Dealloc: // NB. we only need to add a note in a non-error case. 707 switch (V.getKind()) { 708 default: 709 llvm_unreachable("Invalid RefVal state for an explicit dealloc."); 710 case RefVal::Owned: 711 // The object immediately transitions to the released state. 712 V = V ^ RefVal::Released; 713 V.clearCounts(); 714 return setRefBinding(state, sym, V); 715 case RefVal::NotOwned: 716 V = V ^ RefVal::ErrorDeallocNotOwned; 717 hasErr = V.getKind(); 718 break; 719 } 720 break; 721 722 case MayEscape: 723 if (V.getKind() == RefVal::Owned) { 724 V = V ^ RefVal::NotOwned; 725 break; 726 } 727 728 LLVM_FALLTHROUGH; 729 730 case DoNothing: 731 return state; 732 733 case Autorelease: 734 // Update the autorelease counts. 735 V = V.autorelease(); 736 break; 737 738 case StopTracking: 739 case StopTrackingHard: 740 return removeRefBinding(state, sym); 741 742 case IncRef: 743 switch (V.getKind()) { 744 default: 745 llvm_unreachable("Invalid RefVal state for a retain."); 746 case RefVal::Owned: 747 case RefVal::NotOwned: 748 V = V + 1; 749 break; 750 } 751 break; 752 753 case DecRef: 754 case DecRefBridgedTransferred: 755 case DecRefAndStopTrackingHard: 756 switch (V.getKind()) { 757 default: 758 // case 'RefVal::Released' handled above. 759 llvm_unreachable("Invalid RefVal state for a release."); 760 761 case RefVal::Owned: 762 assert(V.getCount() > 0); 763 if (V.getCount() == 1) { 764 if (AE.getKind() == DecRefBridgedTransferred || 765 V.getIvarAccessHistory() == 766 RefVal::IvarAccessHistory::AccessedDirectly) 767 V = V ^ RefVal::NotOwned; 768 else 769 V = V ^ RefVal::Released; 770 } else if (AE.getKind() == DecRefAndStopTrackingHard) { 771 return removeRefBinding(state, sym); 772 } 773 774 V = V - 1; 775 break; 776 777 case RefVal::NotOwned: 778 if (V.getCount() > 0) { 779 if (AE.getKind() == DecRefAndStopTrackingHard) 780 return removeRefBinding(state, sym); 781 V = V - 1; 782 } else if (V.getIvarAccessHistory() == 783 RefVal::IvarAccessHistory::AccessedDirectly) { 784 // Assume that the instance variable was holding on the object at 785 // +1, and we just didn't know. 786 if (AE.getKind() == DecRefAndStopTrackingHard) 787 return removeRefBinding(state, sym); 788 V = V.releaseViaIvar() ^ RefVal::Released; 789 } else { 790 V = V ^ RefVal::ErrorReleaseNotOwned; 791 hasErr = V.getKind(); 792 } 793 break; 794 } 795 break; 796 } 797 return setRefBinding(state, sym, V); 798 } 799 800 void RetainCountChecker::processNonLeakError(ProgramStateRef St, 801 SourceRange ErrorRange, 802 RefVal::Kind ErrorKind, 803 SymbolRef Sym, 804 CheckerContext &C) const { 805 // HACK: Ignore retain-count issues on values accessed through ivars, 806 // because of cases like this: 807 // [_contentView retain]; 808 // [_contentView removeFromSuperview]; 809 // [self addSubview:_contentView]; // invalidates 'self' 810 // [_contentView release]; 811 if (const RefVal *RV = getRefBinding(St, Sym)) 812 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 813 return; 814 815 ExplodedNode *N = C.generateErrorNode(St); 816 if (!N) 817 return; 818 819 RefCountBug *BT; 820 switch (ErrorKind) { 821 default: 822 llvm_unreachable("Unhandled error."); 823 case RefVal::ErrorUseAfterRelease: 824 if (!useAfterRelease) 825 useAfterRelease.reset(new UseAfterRelease(this)); 826 BT = useAfterRelease.get(); 827 break; 828 case RefVal::ErrorReleaseNotOwned: 829 if (!releaseNotOwned) 830 releaseNotOwned.reset(new BadRelease(this)); 831 BT = releaseNotOwned.get(); 832 break; 833 case RefVal::ErrorDeallocNotOwned: 834 if (!deallocNotOwned) 835 deallocNotOwned.reset(new DeallocNotOwned(this)); 836 BT = deallocNotOwned.get(); 837 break; 838 } 839 840 assert(BT); 841 auto report = llvm::make_unique<RefCountReport>( 842 *BT, C.getASTContext().getLangOpts(), N, Sym); 843 report->addRange(ErrorRange); 844 C.emitReport(std::move(report)); 845 } 846 847 //===----------------------------------------------------------------------===// 848 // Handle the return values of retain-count-related functions. 849 //===----------------------------------------------------------------------===// 850 851 bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 852 // Get the callee. We're only interested in simple C functions. 853 ProgramStateRef state = C.getState(); 854 const FunctionDecl *FD = C.getCalleeDecl(CE); 855 if (!FD) 856 return false; 857 858 RetainSummaryManager &SmrMgr = getSummaryManager(C); 859 QualType ResultTy = CE->getCallReturnType(C.getASTContext()); 860 861 // See if the function has 'rc_ownership_trusted_implementation' 862 // annotate attribute. If it does, we will not inline it. 863 bool hasTrustedImplementationAnnotation = false; 864 865 const LocationContext *LCtx = C.getLocationContext(); 866 867 using BehaviorSummary = RetainSummaryManager::BehaviorSummary; 868 Optional<BehaviorSummary> BSmr = 869 SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation); 870 871 // See if it's one of the specific functions we know how to eval. 872 if (!BSmr) 873 return false; 874 875 // Bind the return value. 876 if (BSmr == BehaviorSummary::Identity || 877 BSmr == BehaviorSummary::IdentityOrZero) { 878 SVal RetVal = state->getSVal(CE->getArg(0), LCtx); 879 880 // If the receiver is unknown or the function has 881 // 'rc_ownership_trusted_implementation' annotate attribute, conjure a 882 // return value. 883 if (RetVal.isUnknown() || 884 (hasTrustedImplementationAnnotation && !ResultTy.isNull())) { 885 SValBuilder &SVB = C.getSValBuilder(); 886 RetVal = 887 SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount()); 888 } 889 state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false); 890 891 if (BSmr == BehaviorSummary::IdentityOrZero) { 892 // Add a branch where the output is zero. 893 ProgramStateRef NullOutputState = C.getState(); 894 895 // Assume that output is zero on the other branch. 896 NullOutputState = NullOutputState->BindExpr( 897 CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false); 898 899 C.addTransition(NullOutputState); 900 901 // And on the original branch assume that both input and 902 // output are non-zero. 903 if (auto L = RetVal.getAs<DefinedOrUnknownSVal>()) 904 state = state->assume(*L, /*Assumption=*/true); 905 906 } 907 } 908 909 C.addTransition(state); 910 return true; 911 } 912 913 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S, 914 CheckerContext &C) const { 915 ExplodedNode *Pred = C.getPredecessor(); 916 917 // Only adjust the reference count if this is the top-level call frame, 918 // and not the result of inlining. In the future, we should do 919 // better checking even for inlined calls, and see if they match 920 // with their expected semantics (e.g., the method should return a retained 921 // object, etc.). 922 if (!C.inTopFrame()) 923 return Pred; 924 925 if (!S) 926 return Pred; 927 928 const Expr *RetE = S->getRetValue(); 929 if (!RetE) 930 return Pred; 931 932 ProgramStateRef state = C.getState(); 933 SymbolRef Sym = 934 state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol(); 935 if (!Sym) 936 return Pred; 937 938 // Get the reference count binding (if any). 939 const RefVal *T = getRefBinding(state, Sym); 940 if (!T) 941 return Pred; 942 943 // Change the reference count. 944 RefVal X = *T; 945 946 switch (X.getKind()) { 947 case RefVal::Owned: { 948 unsigned cnt = X.getCount(); 949 assert(cnt > 0); 950 X.setCount(cnt - 1); 951 X = X ^ RefVal::ReturnedOwned; 952 break; 953 } 954 955 case RefVal::NotOwned: { 956 unsigned cnt = X.getCount(); 957 if (cnt) { 958 X.setCount(cnt - 1); 959 X = X ^ RefVal::ReturnedOwned; 960 } else { 961 X = X ^ RefVal::ReturnedNotOwned; 962 } 963 break; 964 } 965 966 default: 967 return Pred; 968 } 969 970 // Update the binding. 971 state = setRefBinding(state, Sym, X); 972 Pred = C.addTransition(state); 973 974 // At this point we have updated the state properly. 975 // Everything after this is merely checking to see if the return value has 976 // been over- or under-retained. 977 978 // Did we cache out? 979 if (!Pred) 980 return nullptr; 981 982 // Update the autorelease counts. 983 static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease"); 984 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S); 985 986 // Have we generated a sink node? 987 if (!state) 988 return nullptr; 989 990 // Get the updated binding. 991 T = getRefBinding(state, Sym); 992 assert(T); 993 X = *T; 994 995 // Consult the summary of the enclosing method. 996 RetainSummaryManager &Summaries = getSummaryManager(C); 997 const Decl *CD = &Pred->getCodeDecl(); 998 RetEffect RE = RetEffect::MakeNoRet(); 999 1000 // FIXME: What is the convention for blocks? Is there one? 1001 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) { 1002 const RetainSummary *Summ = Summaries.getMethodSummary(MD); 1003 RE = Summ->getRetEffect(); 1004 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) { 1005 if (!isa<CXXMethodDecl>(FD)) { 1006 const RetainSummary *Summ = Summaries.getFunctionSummary(FD); 1007 RE = Summ->getRetEffect(); 1008 } 1009 } 1010 1011 return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state); 1012 } 1013 1014 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S, 1015 CheckerContext &C, 1016 ExplodedNode *Pred, 1017 RetEffect RE, RefVal X, 1018 SymbolRef Sym, 1019 ProgramStateRef state) const { 1020 // HACK: Ignore retain-count issues on values accessed through ivars, 1021 // because of cases like this: 1022 // [_contentView retain]; 1023 // [_contentView removeFromSuperview]; 1024 // [self addSubview:_contentView]; // invalidates 'self' 1025 // [_contentView release]; 1026 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1027 return Pred; 1028 1029 // Any leaks or other errors? 1030 if (X.isReturnedOwned() && X.getCount() == 0) { 1031 if (RE.getKind() != RetEffect::NoRet) { 1032 if (!RE.isOwned()) { 1033 1034 // The returning type is a CF, we expect the enclosing method should 1035 // return ownership. 1036 X = X ^ RefVal::ErrorLeakReturned; 1037 1038 // Generate an error node. 1039 state = setRefBinding(state, Sym, X); 1040 1041 static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak"); 1042 ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag); 1043 if (N) { 1044 const LangOptions &LOpts = C.getASTContext().getLangOpts(); 1045 auto R = llvm::make_unique<RefLeakReport>( 1046 *getLeakAtReturnBug(LOpts), LOpts, N, Sym, C); 1047 C.emitReport(std::move(R)); 1048 } 1049 return N; 1050 } 1051 } 1052 } else if (X.isReturnedNotOwned()) { 1053 if (RE.isOwned()) { 1054 if (X.getIvarAccessHistory() == 1055 RefVal::IvarAccessHistory::AccessedDirectly) { 1056 // Assume the method was trying to transfer a +1 reference from a 1057 // strong ivar to the caller. 1058 state = setRefBinding(state, Sym, 1059 X.releaseViaIvar() ^ RefVal::ReturnedOwned); 1060 } else { 1061 // Trying to return a not owned object to a caller expecting an 1062 // owned object. 1063 state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned); 1064 1065 static CheckerProgramPointTag 1066 ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned"); 1067 1068 ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag); 1069 if (N) { 1070 if (!returnNotOwnedForOwned) 1071 returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this)); 1072 1073 auto R = llvm::make_unique<RefCountReport>( 1074 *returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym); 1075 C.emitReport(std::move(R)); 1076 } 1077 return N; 1078 } 1079 } 1080 } 1081 return Pred; 1082 } 1083 1084 //===----------------------------------------------------------------------===// 1085 // Check various ways a symbol can be invalidated. 1086 //===----------------------------------------------------------------------===// 1087 1088 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S, 1089 CheckerContext &C) const { 1090 // Are we storing to something that causes the value to "escape"? 1091 bool escapes = true; 1092 1093 // A value escapes in three possible cases (this may change): 1094 // 1095 // (1) we are binding to something that is not a memory region. 1096 // (2) we are binding to a memregion that does not have stack storage 1097 // (3) we are binding to a memregion with stack storage that the store 1098 // does not understand. 1099 ProgramStateRef state = C.getState(); 1100 1101 if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) { 1102 escapes = !regionLoc->getRegion()->hasStackStorage(); 1103 1104 if (!escapes) { 1105 // To test (3), generate a new state with the binding added. If it is 1106 // the same state, then it escapes (since the store cannot represent 1107 // the binding). 1108 // Do this only if we know that the store is not supposed to generate the 1109 // same state. 1110 SVal StoredVal = state->getSVal(regionLoc->getRegion()); 1111 if (StoredVal != val) 1112 escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext()))); 1113 } 1114 if (!escapes) { 1115 // Case 4: We do not currently model what happens when a symbol is 1116 // assigned to a struct field, so be conservative here and let the symbol 1117 // go. TODO: This could definitely be improved upon. 1118 escapes = !isa<VarRegion>(regionLoc->getRegion()); 1119 } 1120 } 1121 1122 // If we are storing the value into an auto function scope variable annotated 1123 // with (__attribute__((cleanup))), stop tracking the value to avoid leak 1124 // false positives. 1125 if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) { 1126 const VarDecl *VD = LVR->getDecl(); 1127 if (VD->hasAttr<CleanupAttr>()) { 1128 escapes = true; 1129 } 1130 } 1131 1132 // If our store can represent the binding and we aren't storing to something 1133 // that doesn't have local storage then just return and have the simulation 1134 // state continue as is. 1135 if (!escapes) 1136 return; 1137 1138 // Otherwise, find all symbols referenced by 'val' that we are tracking 1139 // and stop tracking them. 1140 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState(); 1141 C.addTransition(state); 1142 } 1143 1144 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state, 1145 SVal Cond, 1146 bool Assumption) const { 1147 // FIXME: We may add to the interface of evalAssume the list of symbols 1148 // whose assumptions have changed. For now we just iterate through the 1149 // bindings and check if any of the tracked symbols are NULL. This isn't 1150 // too bad since the number of symbols we will track in practice are 1151 // probably small and evalAssume is only called at branches and a few 1152 // other places. 1153 RefBindingsTy B = state->get<RefBindings>(); 1154 1155 if (B.isEmpty()) 1156 return state; 1157 1158 bool changed = false; 1159 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>(); 1160 1161 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { 1162 // Check if the symbol is null stop tracking the symbol. 1163 ConstraintManager &CMgr = state->getConstraintManager(); 1164 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey()); 1165 if (AllocFailed.isConstrainedTrue()) { 1166 changed = true; 1167 B = RefBFactory.remove(B, I.getKey()); 1168 } 1169 } 1170 1171 if (changed) 1172 state = state->set<RefBindings>(B); 1173 1174 return state; 1175 } 1176 1177 ProgramStateRef 1178 RetainCountChecker::checkRegionChanges(ProgramStateRef state, 1179 const InvalidatedSymbols *invalidated, 1180 ArrayRef<const MemRegion *> ExplicitRegions, 1181 ArrayRef<const MemRegion *> Regions, 1182 const LocationContext *LCtx, 1183 const CallEvent *Call) const { 1184 if (!invalidated) 1185 return state; 1186 1187 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols; 1188 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(), 1189 E = ExplicitRegions.end(); I != E; ++I) { 1190 if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>()) 1191 WhitelistedSymbols.insert(SR->getSymbol()); 1192 } 1193 1194 for (SymbolRef sym : 1195 llvm::make_range(invalidated->begin(), invalidated->end())) { 1196 if (WhitelistedSymbols.count(sym)) 1197 continue; 1198 // Remove any existing reference-count binding. 1199 state = removeRefBinding(state, sym); 1200 } 1201 return state; 1202 } 1203 1204 ProgramStateRef 1205 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, 1206 ExplodedNode *Pred, 1207 const ProgramPointTag *Tag, 1208 CheckerContext &Ctx, 1209 SymbolRef Sym, 1210 RefVal V, 1211 const ReturnStmt *S) const { 1212 unsigned ACnt = V.getAutoreleaseCount(); 1213 1214 // No autorelease counts? Nothing to be done. 1215 if (!ACnt) 1216 return state; 1217 1218 unsigned Cnt = V.getCount(); 1219 1220 // FIXME: Handle sending 'autorelease' to already released object. 1221 1222 if (V.getKind() == RefVal::ReturnedOwned) 1223 ++Cnt; 1224 1225 // If we would over-release here, but we know the value came from an ivar, 1226 // assume it was a strong ivar that's just been relinquished. 1227 if (ACnt > Cnt && 1228 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) { 1229 V = V.releaseViaIvar(); 1230 --ACnt; 1231 } 1232 1233 if (ACnt <= Cnt) { 1234 if (ACnt == Cnt) { 1235 V.clearCounts(); 1236 if (V.getKind() == RefVal::ReturnedOwned) { 1237 V = V ^ RefVal::ReturnedNotOwned; 1238 } else { 1239 V = V ^ RefVal::NotOwned; 1240 } 1241 } else { 1242 V.setCount(V.getCount() - ACnt); 1243 V.setAutoreleaseCount(0); 1244 } 1245 return setRefBinding(state, Sym, V); 1246 } 1247 1248 // HACK: Ignore retain-count issues on values accessed through ivars, 1249 // because of cases like this: 1250 // [_contentView retain]; 1251 // [_contentView removeFromSuperview]; 1252 // [self addSubview:_contentView]; // invalidates 'self' 1253 // [_contentView release]; 1254 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1255 return state; 1256 1257 // Woah! More autorelease counts then retain counts left. 1258 // Emit hard error. 1259 V = V ^ RefVal::ErrorOverAutorelease; 1260 state = setRefBinding(state, Sym, V); 1261 1262 ExplodedNode *N = Ctx.generateSink(state, Pred, Tag); 1263 if (N) { 1264 SmallString<128> sbuf; 1265 llvm::raw_svector_ostream os(sbuf); 1266 os << "Object was autoreleased "; 1267 if (V.getAutoreleaseCount() > 1) 1268 os << V.getAutoreleaseCount() << " times but the object "; 1269 else 1270 os << "but "; 1271 os << "has a +" << V.getCount() << " retain count"; 1272 1273 if (!overAutorelease) 1274 overAutorelease.reset(new OverAutorelease(this)); 1275 1276 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts(); 1277 auto R = llvm::make_unique<RefCountReport>(*overAutorelease, LOpts, N, Sym, 1278 os.str()); 1279 Ctx.emitReport(std::move(R)); 1280 } 1281 1282 return nullptr; 1283 } 1284 1285 ProgramStateRef 1286 RetainCountChecker::handleSymbolDeath(ProgramStateRef state, 1287 SymbolRef sid, RefVal V, 1288 SmallVectorImpl<SymbolRef> &Leaked) const { 1289 bool hasLeak; 1290 1291 // HACK: Ignore retain-count issues on values accessed through ivars, 1292 // because of cases like this: 1293 // [_contentView retain]; 1294 // [_contentView removeFromSuperview]; 1295 // [self addSubview:_contentView]; // invalidates 'self' 1296 // [_contentView release]; 1297 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1298 hasLeak = false; 1299 else if (V.isOwned()) 1300 hasLeak = true; 1301 else if (V.isNotOwned() || V.isReturnedOwned()) 1302 hasLeak = (V.getCount() > 0); 1303 else 1304 hasLeak = false; 1305 1306 if (!hasLeak) 1307 return removeRefBinding(state, sid); 1308 1309 Leaked.push_back(sid); 1310 return setRefBinding(state, sid, V ^ RefVal::ErrorLeak); 1311 } 1312 1313 ExplodedNode * 1314 RetainCountChecker::processLeaks(ProgramStateRef state, 1315 SmallVectorImpl<SymbolRef> &Leaked, 1316 CheckerContext &Ctx, 1317 ExplodedNode *Pred) const { 1318 // Generate an intermediate node representing the leak point. 1319 ExplodedNode *N = Ctx.addTransition(state, Pred); 1320 1321 if (N) { 1322 for (SmallVectorImpl<SymbolRef>::iterator 1323 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) { 1324 1325 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts(); 1326 RefCountBug *BT = Pred ? getLeakWithinFunctionBug(LOpts) 1327 : getLeakAtReturnBug(LOpts); 1328 assert(BT && "BugType not initialized."); 1329 1330 Ctx.emitReport( 1331 llvm::make_unique<RefLeakReport>(*BT, LOpts, N, *I, Ctx)); 1332 } 1333 } 1334 1335 return N; 1336 } 1337 1338 static bool isISLObjectRef(QualType Ty) { 1339 return StringRef(Ty.getAsString()).startswith("isl_"); 1340 } 1341 1342 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const { 1343 if (!Ctx.inTopFrame()) 1344 return; 1345 1346 RetainSummaryManager &SmrMgr = getSummaryManager(Ctx); 1347 const LocationContext *LCtx = Ctx.getLocationContext(); 1348 const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl()); 1349 1350 if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD)) 1351 return; 1352 1353 ProgramStateRef state = Ctx.getState(); 1354 const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD); 1355 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects(); 1356 1357 for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) { 1358 const ParmVarDecl *Param = FD->getParamDecl(idx); 1359 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol(); 1360 1361 QualType Ty = Param->getType(); 1362 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx); 1363 if (AE && AE->getKind() == DecRef && isISLObjectRef(Ty)) { 1364 state = setRefBinding( 1365 state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty)); 1366 } else if (isISLObjectRef(Ty)) { 1367 state = setRefBinding( 1368 state, Sym, 1369 RefVal::makeNotOwned(ObjKind::Generalized, Ty)); 1370 } 1371 } 1372 1373 Ctx.addTransition(state); 1374 } 1375 1376 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS, 1377 CheckerContext &Ctx) const { 1378 ExplodedNode *Pred = processReturn(RS, Ctx); 1379 1380 // Created state cached out. 1381 if (!Pred) { 1382 return; 1383 } 1384 1385 ProgramStateRef state = Pred->getState(); 1386 RefBindingsTy B = state->get<RefBindings>(); 1387 1388 // Don't process anything within synthesized bodies. 1389 const LocationContext *LCtx = Pred->getLocationContext(); 1390 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) { 1391 assert(!LCtx->inTopFrame()); 1392 return; 1393 } 1394 1395 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { 1396 state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx, 1397 I->first, I->second); 1398 if (!state) 1399 return; 1400 } 1401 1402 // If the current LocationContext has a parent, don't check for leaks. 1403 // We will do that later. 1404 // FIXME: we should instead check for imbalances of the retain/releases, 1405 // and suggest annotations. 1406 if (LCtx->getParent()) 1407 return; 1408 1409 B = state->get<RefBindings>(); 1410 SmallVector<SymbolRef, 10> Leaked; 1411 1412 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) 1413 state = handleSymbolDeath(state, I->first, I->second, Leaked); 1414 1415 processLeaks(state, Leaked, Ctx, Pred); 1416 } 1417 1418 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, 1419 CheckerContext &C) const { 1420 ExplodedNode *Pred = C.getPredecessor(); 1421 1422 ProgramStateRef state = C.getState(); 1423 RefBindingsTy B = state->get<RefBindings>(); 1424 SmallVector<SymbolRef, 10> Leaked; 1425 1426 // Update counts from autorelease pools 1427 for (const auto &I: state->get<RefBindings>()) { 1428 SymbolRef Sym = I.first; 1429 if (SymReaper.isDead(Sym)) { 1430 static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease"); 1431 const RefVal &V = I.second; 1432 state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V); 1433 if (!state) 1434 return; 1435 1436 // Fetch the new reference count from the state, and use it to handle 1437 // this symbol. 1438 state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked); 1439 } 1440 } 1441 1442 if (Leaked.empty()) { 1443 C.addTransition(state); 1444 return; 1445 } 1446 1447 Pred = processLeaks(state, Leaked, C, Pred); 1448 1449 // Did we cache out? 1450 if (!Pred) 1451 return; 1452 1453 // Now generate a new node that nukes the old bindings. 1454 // The only bindings left at this point are the leaked symbols. 1455 RefBindingsTy::Factory &F = state->get_context<RefBindings>(); 1456 B = state->get<RefBindings>(); 1457 1458 for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(), 1459 E = Leaked.end(); 1460 I != E; ++I) 1461 B = F.remove(B, *I); 1462 1463 state = state->set<RefBindings>(B); 1464 C.addTransition(state, Pred); 1465 } 1466 1467 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State, 1468 const char *NL, const char *Sep) const { 1469 1470 RefBindingsTy B = State->get<RefBindings>(); 1471 1472 if (B.isEmpty()) 1473 return; 1474 1475 Out << Sep << NL; 1476 1477 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { 1478 Out << I->first << " : "; 1479 I->second.print(Out); 1480 Out << NL; 1481 } 1482 } 1483 1484 //===----------------------------------------------------------------------===// 1485 // Checker registration. 1486 //===----------------------------------------------------------------------===// 1487 1488 void ento::registerRetainCountChecker(CheckerManager &Mgr) { 1489 auto *Chk = Mgr.registerChecker<RetainCountChecker>(); 1490 Chk->TrackObjCAndCFObjects = true; 1491 } 1492 1493 // FIXME: remove this, hack for backwards compatibility: 1494 // it should be possible to enable the NS/CF retain count checker as 1495 // osx.cocoa.RetainCount, and it should be possible to disable 1496 // osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false. 1497 static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options) { 1498 auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject"); 1499 if (I != Options.Config.end()) 1500 return I->getValue() == "false"; 1501 return false; 1502 } 1503 1504 void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) { 1505 auto *Chk = Mgr.registerChecker<RetainCountChecker>(); 1506 if (!hasPrevCheckOSObjectOptionDisabled(Mgr.getAnalyzerOptions())) 1507 Chk->TrackOSObjects = true; 1508 } 1509