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