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