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 // We need to dig down to the symbolic base here because various 974 // custom allocators do sometimes return the symbol with an offset. 975 SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getLocationContext()) 976 .getAsLocSymbol(/*IncludeBaseRegions=*/true); 977 if (!Sym) 978 return Pred; 979 980 // Get the reference count binding (if any). 981 const RefVal *T = getRefBinding(state, Sym); 982 if (!T) 983 return Pred; 984 985 // Change the reference count. 986 RefVal X = *T; 987 988 switch (X.getKind()) { 989 case RefVal::Owned: { 990 unsigned cnt = X.getCount(); 991 assert(cnt > 0); 992 X.setCount(cnt - 1); 993 X = X ^ RefVal::ReturnedOwned; 994 break; 995 } 996 997 case RefVal::NotOwned: { 998 unsigned cnt = X.getCount(); 999 if (cnt) { 1000 X.setCount(cnt - 1); 1001 X = X ^ RefVal::ReturnedOwned; 1002 } else { 1003 X = X ^ RefVal::ReturnedNotOwned; 1004 } 1005 break; 1006 } 1007 1008 default: 1009 return Pred; 1010 } 1011 1012 // Update the binding. 1013 state = setRefBinding(state, Sym, X); 1014 Pred = C.addTransition(state); 1015 1016 // At this point we have updated the state properly. 1017 // Everything after this is merely checking to see if the return value has 1018 // been over- or under-retained. 1019 1020 // Did we cache out? 1021 if (!Pred) 1022 return nullptr; 1023 1024 // Update the autorelease counts. 1025 static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease"); 1026 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S); 1027 1028 // Have we generated a sink node? 1029 if (!state) 1030 return nullptr; 1031 1032 // Get the updated binding. 1033 T = getRefBinding(state, Sym); 1034 assert(T); 1035 X = *T; 1036 1037 // Consult the summary of the enclosing method. 1038 RetainSummaryManager &Summaries = getSummaryManager(C); 1039 const Decl *CD = &Pred->getCodeDecl(); 1040 RetEffect RE = RetEffect::MakeNoRet(); 1041 1042 // FIXME: What is the convention for blocks? Is there one? 1043 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) { 1044 const RetainSummary *Summ = Summaries.getSummary(AnyCall(MD)); 1045 RE = Summ->getRetEffect(); 1046 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) { 1047 if (!isa<CXXMethodDecl>(FD)) { 1048 const RetainSummary *Summ = Summaries.getSummary(AnyCall(FD)); 1049 RE = Summ->getRetEffect(); 1050 } 1051 } 1052 1053 return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state); 1054 } 1055 1056 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S, 1057 CheckerContext &C, 1058 ExplodedNode *Pred, 1059 RetEffect RE, RefVal X, 1060 SymbolRef Sym, 1061 ProgramStateRef state) const { 1062 // HACK: Ignore retain-count issues on values accessed through ivars, 1063 // because of cases like this: 1064 // [_contentView retain]; 1065 // [_contentView removeFromSuperview]; 1066 // [self addSubview:_contentView]; // invalidates 'self' 1067 // [_contentView release]; 1068 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1069 return Pred; 1070 1071 // Any leaks or other errors? 1072 if (X.isReturnedOwned() && X.getCount() == 0) { 1073 if (RE.getKind() != RetEffect::NoRet) { 1074 if (!RE.isOwned()) { 1075 1076 // The returning type is a CF, we expect the enclosing method should 1077 // return ownership. 1078 X = X ^ RefVal::ErrorLeakReturned; 1079 1080 // Generate an error node. 1081 state = setRefBinding(state, Sym, X); 1082 1083 static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak"); 1084 ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag); 1085 if (N) { 1086 const LangOptions &LOpts = C.getASTContext().getLangOpts(); 1087 auto R = 1088 llvm::make_unique<RefLeakReport>(leakAtReturn, LOpts, N, Sym, C); 1089 C.emitReport(std::move(R)); 1090 } 1091 return N; 1092 } 1093 } 1094 } else if (X.isReturnedNotOwned()) { 1095 if (RE.isOwned()) { 1096 if (X.getIvarAccessHistory() == 1097 RefVal::IvarAccessHistory::AccessedDirectly) { 1098 // Assume the method was trying to transfer a +1 reference from a 1099 // strong ivar to the caller. 1100 state = setRefBinding(state, Sym, 1101 X.releaseViaIvar() ^ RefVal::ReturnedOwned); 1102 } else { 1103 // Trying to return a not owned object to a caller expecting an 1104 // owned object. 1105 state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned); 1106 1107 static CheckerProgramPointTag 1108 ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned"); 1109 1110 ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag); 1111 if (N) { 1112 auto R = llvm::make_unique<RefCountReport>( 1113 returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym); 1114 C.emitReport(std::move(R)); 1115 } 1116 return N; 1117 } 1118 } 1119 } 1120 return Pred; 1121 } 1122 1123 //===----------------------------------------------------------------------===// 1124 // Check various ways a symbol can be invalidated. 1125 //===----------------------------------------------------------------------===// 1126 1127 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S, 1128 CheckerContext &C) const { 1129 ProgramStateRef state = C.getState(); 1130 const MemRegion *MR = loc.getAsRegion(); 1131 1132 // Find all symbols referenced by 'val' that we are tracking 1133 // and stop tracking them. 1134 if (MR && shouldEscapeRegion(MR)) { 1135 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState(); 1136 C.addTransition(state); 1137 } 1138 } 1139 1140 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state, 1141 SVal Cond, 1142 bool Assumption) const { 1143 // FIXME: We may add to the interface of evalAssume the list of symbols 1144 // whose assumptions have changed. For now we just iterate through the 1145 // bindings and check if any of the tracked symbols are NULL. This isn't 1146 // too bad since the number of symbols we will track in practice are 1147 // probably small and evalAssume is only called at branches and a few 1148 // other places. 1149 RefBindingsTy B = state->get<RefBindings>(); 1150 1151 if (B.isEmpty()) 1152 return state; 1153 1154 bool changed = false; 1155 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>(); 1156 ConstraintManager &CMgr = state->getConstraintManager(); 1157 1158 for (auto &I : B) { 1159 // Check if the symbol is null stop tracking the symbol. 1160 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.first); 1161 if (AllocFailed.isConstrainedTrue()) { 1162 changed = true; 1163 B = RefBFactory.remove(B, I.first); 1164 } 1165 } 1166 1167 if (changed) 1168 state = state->set<RefBindings>(B); 1169 1170 return state; 1171 } 1172 1173 ProgramStateRef RetainCountChecker::checkRegionChanges( 1174 ProgramStateRef state, const InvalidatedSymbols *invalidated, 1175 ArrayRef<const MemRegion *> ExplicitRegions, 1176 ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx, 1177 const CallEvent *Call) const { 1178 if (!invalidated) 1179 return state; 1180 1181 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols; 1182 1183 for (const MemRegion *I : ExplicitRegions) 1184 if (const SymbolicRegion *SR = I->StripCasts()->getAs<SymbolicRegion>()) 1185 WhitelistedSymbols.insert(SR->getSymbol()); 1186 1187 for (SymbolRef sym : *invalidated) { 1188 if (WhitelistedSymbols.count(sym)) 1189 continue; 1190 // Remove any existing reference-count binding. 1191 state = removeRefBinding(state, sym); 1192 } 1193 return state; 1194 } 1195 1196 ProgramStateRef 1197 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, 1198 ExplodedNode *Pred, 1199 const ProgramPointTag *Tag, 1200 CheckerContext &Ctx, 1201 SymbolRef Sym, 1202 RefVal V, 1203 const ReturnStmt *S) const { 1204 unsigned ACnt = V.getAutoreleaseCount(); 1205 1206 // No autorelease counts? Nothing to be done. 1207 if (!ACnt) 1208 return state; 1209 1210 unsigned Cnt = V.getCount(); 1211 1212 // FIXME: Handle sending 'autorelease' to already released object. 1213 1214 if (V.getKind() == RefVal::ReturnedOwned) 1215 ++Cnt; 1216 1217 // If we would over-release here, but we know the value came from an ivar, 1218 // assume it was a strong ivar that's just been relinquished. 1219 if (ACnt > Cnt && 1220 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) { 1221 V = V.releaseViaIvar(); 1222 --ACnt; 1223 } 1224 1225 if (ACnt <= Cnt) { 1226 if (ACnt == Cnt) { 1227 V.clearCounts(); 1228 if (V.getKind() == RefVal::ReturnedOwned) { 1229 V = V ^ RefVal::ReturnedNotOwned; 1230 } else { 1231 V = V ^ RefVal::NotOwned; 1232 } 1233 } else { 1234 V.setCount(V.getCount() - ACnt); 1235 V.setAutoreleaseCount(0); 1236 } 1237 return setRefBinding(state, Sym, V); 1238 } 1239 1240 // HACK: Ignore retain-count issues on values accessed through ivars, 1241 // because of cases like this: 1242 // [_contentView retain]; 1243 // [_contentView removeFromSuperview]; 1244 // [self addSubview:_contentView]; // invalidates 'self' 1245 // [_contentView release]; 1246 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1247 return state; 1248 1249 // Woah! More autorelease counts then retain counts left. 1250 // Emit hard error. 1251 V = V ^ RefVal::ErrorOverAutorelease; 1252 state = setRefBinding(state, Sym, V); 1253 1254 ExplodedNode *N = Ctx.generateSink(state, Pred, Tag); 1255 if (N) { 1256 SmallString<128> sbuf; 1257 llvm::raw_svector_ostream os(sbuf); 1258 os << "Object was autoreleased "; 1259 if (V.getAutoreleaseCount() > 1) 1260 os << V.getAutoreleaseCount() << " times but the object "; 1261 else 1262 os << "but "; 1263 os << "has a +" << V.getCount() << " retain count"; 1264 1265 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts(); 1266 auto R = llvm::make_unique<RefCountReport>(overAutorelease, LOpts, N, Sym, 1267 os.str()); 1268 Ctx.emitReport(std::move(R)); 1269 } 1270 1271 return nullptr; 1272 } 1273 1274 ProgramStateRef 1275 RetainCountChecker::handleSymbolDeath(ProgramStateRef state, 1276 SymbolRef sid, RefVal V, 1277 SmallVectorImpl<SymbolRef> &Leaked) const { 1278 bool hasLeak; 1279 1280 // HACK: Ignore retain-count issues on values accessed through ivars, 1281 // because of cases like this: 1282 // [_contentView retain]; 1283 // [_contentView removeFromSuperview]; 1284 // [self addSubview:_contentView]; // invalidates 'self' 1285 // [_contentView release]; 1286 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None) 1287 hasLeak = false; 1288 else if (V.isOwned()) 1289 hasLeak = true; 1290 else if (V.isNotOwned() || V.isReturnedOwned()) 1291 hasLeak = (V.getCount() > 0); 1292 else 1293 hasLeak = false; 1294 1295 if (!hasLeak) 1296 return removeRefBinding(state, sid); 1297 1298 Leaked.push_back(sid); 1299 return setRefBinding(state, sid, V ^ RefVal::ErrorLeak); 1300 } 1301 1302 ExplodedNode * 1303 RetainCountChecker::processLeaks(ProgramStateRef state, 1304 SmallVectorImpl<SymbolRef> &Leaked, 1305 CheckerContext &Ctx, 1306 ExplodedNode *Pred) const { 1307 // Generate an intermediate node representing the leak point. 1308 ExplodedNode *N = Ctx.addTransition(state, Pred); 1309 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts(); 1310 1311 if (N) { 1312 for (SymbolRef L : Leaked) { 1313 const RefCountBug &BT = Pred ? leakWithinFunction : leakAtReturn; 1314 Ctx.emitReport(llvm::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx)); 1315 } 1316 } 1317 1318 return N; 1319 } 1320 1321 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const { 1322 if (!Ctx.inTopFrame()) 1323 return; 1324 1325 RetainSummaryManager &SmrMgr = getSummaryManager(Ctx); 1326 const LocationContext *LCtx = Ctx.getLocationContext(); 1327 const Decl *D = LCtx->getDecl(); 1328 Optional<AnyCall> C = AnyCall::forDecl(D); 1329 1330 if (!C || SmrMgr.isTrustedReferenceCountImplementation(D)) 1331 return; 1332 1333 ProgramStateRef state = Ctx.getState(); 1334 const RetainSummary *FunctionSummary = SmrMgr.getSummary(*C); 1335 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects(); 1336 1337 for (unsigned idx = 0, e = C->param_size(); idx != e; ++idx) { 1338 const ParmVarDecl *Param = C->parameters()[idx]; 1339 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol(); 1340 1341 QualType Ty = Param->getType(); 1342 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx); 1343 if (AE) { 1344 ObjKind K = AE->getObjKind(); 1345 if (K == ObjKind::Generalized || K == ObjKind::OS || 1346 (TrackNSCFStartParam && (K == ObjKind::ObjC || K == ObjKind::CF))) { 1347 RefVal NewVal = AE->getKind() == DecRef ? RefVal::makeOwned(K, Ty) 1348 : RefVal::makeNotOwned(K, Ty); 1349 state = setRefBinding(state, Sym, NewVal); 1350 } 1351 } 1352 } 1353 1354 Ctx.addTransition(state); 1355 } 1356 1357 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS, 1358 CheckerContext &Ctx) const { 1359 ExplodedNode *Pred = processReturn(RS, Ctx); 1360 1361 // Created state cached out. 1362 if (!Pred) { 1363 return; 1364 } 1365 1366 ProgramStateRef state = Pred->getState(); 1367 RefBindingsTy B = state->get<RefBindings>(); 1368 1369 // Don't process anything within synthesized bodies. 1370 const LocationContext *LCtx = Pred->getLocationContext(); 1371 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) { 1372 assert(!LCtx->inTopFrame()); 1373 return; 1374 } 1375 1376 for (auto &I : B) { 1377 state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx, 1378 I.first, I.second); 1379 if (!state) 1380 return; 1381 } 1382 1383 // If the current LocationContext has a parent, don't check for leaks. 1384 // We will do that later. 1385 // FIXME: we should instead check for imbalances of the retain/releases, 1386 // and suggest annotations. 1387 if (LCtx->getParent()) 1388 return; 1389 1390 B = state->get<RefBindings>(); 1391 SmallVector<SymbolRef, 10> Leaked; 1392 1393 for (auto &I : B) 1394 state = handleSymbolDeath(state, I.first, I.second, Leaked); 1395 1396 processLeaks(state, Leaked, Ctx, Pred); 1397 } 1398 1399 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, 1400 CheckerContext &C) const { 1401 ExplodedNode *Pred = C.getPredecessor(); 1402 1403 ProgramStateRef state = C.getState(); 1404 SmallVector<SymbolRef, 10> Leaked; 1405 1406 // Update counts from autorelease pools 1407 for (const auto &I: state->get<RefBindings>()) { 1408 SymbolRef Sym = I.first; 1409 if (SymReaper.isDead(Sym)) { 1410 static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease"); 1411 const RefVal &V = I.second; 1412 state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V); 1413 if (!state) 1414 return; 1415 1416 // Fetch the new reference count from the state, and use it to handle 1417 // this symbol. 1418 state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked); 1419 } 1420 } 1421 1422 if (Leaked.empty()) { 1423 C.addTransition(state); 1424 return; 1425 } 1426 1427 Pred = processLeaks(state, Leaked, C, Pred); 1428 1429 // Did we cache out? 1430 if (!Pred) 1431 return; 1432 1433 // Now generate a new node that nukes the old bindings. 1434 // The only bindings left at this point are the leaked symbols. 1435 RefBindingsTy::Factory &F = state->get_context<RefBindings>(); 1436 RefBindingsTy B = state->get<RefBindings>(); 1437 1438 for (SymbolRef L : Leaked) 1439 B = F.remove(B, L); 1440 1441 state = state->set<RefBindings>(B); 1442 C.addTransition(state, Pred); 1443 } 1444 1445 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State, 1446 const char *NL, const char *Sep) const { 1447 1448 RefBindingsTy B = State->get<RefBindings>(); 1449 1450 if (B.isEmpty()) 1451 return; 1452 1453 Out << Sep << NL; 1454 1455 for (auto &I : B) { 1456 Out << I.first << " : "; 1457 I.second.print(Out); 1458 Out << NL; 1459 } 1460 } 1461 1462 //===----------------------------------------------------------------------===// 1463 // Checker registration. 1464 //===----------------------------------------------------------------------===// 1465 1466 void ento::registerRetainCountBase(CheckerManager &Mgr) { 1467 Mgr.registerChecker<RetainCountChecker>(); 1468 } 1469 1470 bool ento::shouldRegisterRetainCountBase(const LangOptions &LO) { 1471 return true; 1472 } 1473 1474 // FIXME: remove this, hack for backwards compatibility: 1475 // it should be possible to enable the NS/CF retain count checker as 1476 // osx.cocoa.RetainCount, and it should be possible to disable 1477 // osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false. 1478 static bool getOption(AnalyzerOptions &Options, 1479 StringRef Postfix, 1480 StringRef Value) { 1481 auto I = Options.Config.find( 1482 (StringRef("osx.cocoa.RetainCount:") + Postfix).str()); 1483 if (I != Options.Config.end()) 1484 return I->getValue() == Value; 1485 return false; 1486 } 1487 1488 void ento::registerRetainCountChecker(CheckerManager &Mgr) { 1489 auto *Chk = Mgr.getChecker<RetainCountChecker>(); 1490 Chk->TrackObjCAndCFObjects = true; 1491 Chk->TrackNSCFStartParam = getOption(Mgr.getAnalyzerOptions(), 1492 "TrackNSCFStartParam", 1493 "true"); 1494 } 1495 1496 bool ento::shouldRegisterRetainCountChecker(const LangOptions &LO) { 1497 return true; 1498 } 1499 1500 void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) { 1501 auto *Chk = Mgr.getChecker<RetainCountChecker>(); 1502 if (!getOption(Mgr.getAnalyzerOptions(), 1503 "CheckOSObject", 1504 "false")) 1505 Chk->TrackOSObjects = true; 1506 } 1507 1508 bool ento::shouldRegisterOSObjectRetainCountChecker(const LangOptions &LO) { 1509 return true; 1510 } 1511