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/Checker.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
17
18 using namespace clang;
19 using namespace ento;
20 using namespace retaincountchecker;
21
22 REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
23
24 namespace clang {
25 namespace ento {
26 namespace retaincountchecker {
27
getRefBinding(ProgramStateRef State,SymbolRef Sym)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
setRefBinding(ProgramStateRef State,SymbolRef Sym,RefVal Val)36 static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
37 RefVal Val) {
38 assert(Sym != nullptr);
39 return State->set<RefBindings>(Sym, Val);
40 }
41
removeRefBinding(ProgramStateRef State,SymbolRef Sym)42 static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
43 return State->remove<RefBindings>(Sym);
44 }
45
print(raw_ostream & Out) const46 void RefVal::print(raw_ostream &Out) const {
47 if (!T.isNull())
48 Out << "Tracked " << T << " | ";
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:
StopTrackingCallback(ProgramStateRef st)132 StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
getState() const133 ProgramStateRef getState() const { return state; }
134
VisitSymbol(SymbolRef sym)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
checkPostStmt(const BlockExpr * BE,CheckerContext & C) const146 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
checkPostStmt(const CastExpr * CE,CheckerContext & C) const182 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
processObjCLiterals(CheckerContext & C,const Expr * Ex) const229 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
checkPostStmt(const ObjCArrayLiteral * AL,CheckerContext & C) const259 void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
260 CheckerContext &C) const {
261 // Apply the 'MayEscape' to all values.
262 processObjCLiterals(C, AL);
263 }
264
checkPostStmt(const ObjCDictionaryLiteral * DL,CheckerContext & C) const265 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
checkPostStmt(const ObjCBoxedExpr * Ex,CheckerContext & C) const271 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
checkPostStmt(const ObjCIvarRefExpr * IRE,CheckerContext & C) const285 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 || !isa_and_nonnull<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
isReceiverUnconsumedSelf(const CallEvent & Call)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
getSummary(RetainSummaryManager & Summaries,const CallEvent & Call,QualType ReceiverType)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
checkPostCall(const CallEvent & Call,CheckerContext & C) const363 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.
GetReturnType(const Expr * RetE,ASTContext & Ctx)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
refValFromRetEffect(RetEffect RE,QualType ResultTy)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
isPointerToObject(QualType QT)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.
shouldEscapeOSArgumentOnCall(const CallEvent & CE,unsigned ArgIdx,const RefVal * TrackedValue)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.
processSummaryOfInlined(const RetainSummary & Summ,const CallEvent & CallOrMsg,CheckerContext & C) const448 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
isSmartPtrField(const MemRegion * MR)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.
shouldEscapeRegion(const MemRegion * R)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>
updateOutParameters(ProgramStateRef State,const RetainSummary & Summ,const CallEvent & CE)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 (!CE.getResultType()->isScalarType()) {
541 // Structures cannot be assumed. This probably deserves
542 // a compiler warning for invalid annotations.
543 return {State};
544 }
545 if (auto DL = L.getAs<DefinedOrUnknownSVal>()) {
546 AssumeNonZeroReturn = AssumeNonZeroReturn->assume(*DL, true);
547 AssumeZeroReturn = AssumeZeroReturn->assume(*DL, false);
548 }
549 }
550
551 for (unsigned idx = 0, e = CE.getNumArgs(); idx != e; ++idx) {
552 SVal ArgVal = CE.getArgSVal(idx);
553 ArgEffect AE = Summ.getArg(idx);
554
555 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
556 if (!ArgRegion)
557 continue;
558
559 QualType PointeeTy = ArgRegion->getValueType();
560 SVal PointeeVal = State->getSVal(ArgRegion);
561 SymbolRef Pointee = PointeeVal.getAsLocSymbol();
562 if (!Pointee)
563 continue;
564
565 if (shouldEscapeRegion(ArgRegion))
566 continue;
567
568 auto makeNotOwnedParameter = [&](ProgramStateRef St) {
569 return setRefBinding(St, Pointee,
570 RefVal::makeNotOwned(AE.getObjKind(), PointeeTy));
571 };
572 auto makeOwnedParameter = [&](ProgramStateRef St) {
573 return setRefBinding(St, Pointee,
574 RefVal::makeOwned(ObjKind::OS, PointeeTy));
575 };
576
577 switch (AE.getKind()) {
578 case UnretainedOutParameter:
579 AssumeNonZeroReturn = makeNotOwnedParameter(AssumeNonZeroReturn);
580 AssumeZeroReturn = makeNotOwnedParameter(AssumeZeroReturn);
581 break;
582 case RetainedOutParameter:
583 AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
584 AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
585 break;
586 case RetainedOutParameterOnNonZero:
587 AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);
588 break;
589 case RetainedOutParameterOnZero:
590 AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);
591 break;
592 default:
593 break;
594 }
595 }
596
597 if (SplitNecessary) {
598 return {AssumeNonZeroReturn, AssumeZeroReturn};
599 } else {
600 assert(AssumeZeroReturn == AssumeNonZeroReturn);
601 return {AssumeZeroReturn};
602 }
603 }
604
checkSummary(const RetainSummary & Summ,const CallEvent & CallOrMsg,CheckerContext & C) const605 void RetainCountChecker::checkSummary(const RetainSummary &Summ,
606 const CallEvent &CallOrMsg,
607 CheckerContext &C) const {
608 ProgramStateRef state = C.getState();
609
610 // Evaluate the effect of the arguments.
611 RefVal::Kind hasErr = (RefVal::Kind) 0;
612 SourceRange ErrorRange;
613 SymbolRef ErrorSym = nullptr;
614
615 // Helper tag for providing diagnostics: indicate whether dealloc was sent
616 // at this location.
617 bool DeallocSent = false;
618
619 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
620 SVal V = CallOrMsg.getArgSVal(idx);
621
622 ArgEffect Effect = Summ.getArg(idx);
623 if (SymbolRef Sym = V.getAsLocSymbol()) {
624 if (const RefVal *T = getRefBinding(state, Sym)) {
625
626 if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T))
627 Effect = ArgEffect(StopTrackingHard, ObjKind::OS);
628
629 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
630 if (hasErr) {
631 ErrorRange = CallOrMsg.getArgSourceRange(idx);
632 ErrorSym = Sym;
633 break;
634 } else if (Effect.getKind() == Dealloc) {
635 DeallocSent = true;
636 }
637 }
638 }
639 }
640
641 // Evaluate the effect on the message receiver / `this` argument.
642 bool ReceiverIsTracked = false;
643 if (!hasErr) {
644 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
645 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
646 if (const RefVal *T = getRefBinding(state, Sym)) {
647 ReceiverIsTracked = true;
648 state = updateSymbol(state, Sym, *T,
649 Summ.getReceiverEffect(), hasErr, C);
650 if (hasErr) {
651 ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
652 ErrorSym = Sym;
653 } else if (Summ.getReceiverEffect().getKind() == Dealloc) {
654 DeallocSent = true;
655 }
656 }
657 }
658 } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
659 if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
660 if (const RefVal *T = getRefBinding(state, Sym)) {
661 state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
662 hasErr, C);
663 if (hasErr) {
664 ErrorRange = MCall->getOriginExpr()->getSourceRange();
665 ErrorSym = Sym;
666 }
667 }
668 }
669 }
670 }
671
672 // Process any errors.
673 if (hasErr) {
674 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
675 return;
676 }
677
678 // Consult the summary for the return value.
679 RetEffect RE = Summ.getRetEffect();
680
681 if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
682 if (ReceiverIsTracked)
683 RE = getSummaryManager(C).getObjAllocRetEffect();
684 else
685 RE = RetEffect::MakeNoRet();
686 }
687
688 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
689 QualType ResultTy = CallOrMsg.getResultType();
690 if (RE.notOwned()) {
691 const Expr *Ex = CallOrMsg.getOriginExpr();
692 assert(Ex);
693 ResultTy = GetReturnType(Ex, C.getASTContext());
694 }
695 if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
696 state = setRefBinding(state, Sym, *updatedRefVal);
697 }
698
699 SmallVector<ProgramStateRef, 2> Out =
700 updateOutParameters(state, Summ, CallOrMsg);
701
702 for (ProgramStateRef St : Out) {
703 if (DeallocSent) {
704 C.addTransition(St, C.getPredecessor(), &getDeallocSentTag());
705 } else {
706 C.addTransition(St);
707 }
708 }
709 }
710
updateSymbol(ProgramStateRef state,SymbolRef sym,RefVal V,ArgEffect AE,RefVal::Kind & hasErr,CheckerContext & C) const711 ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state,
712 SymbolRef sym, RefVal V,
713 ArgEffect AE,
714 RefVal::Kind &hasErr,
715 CheckerContext &C) const {
716 bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
717 if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) {
718 switch (AE.getKind()) {
719 default:
720 break;
721 case IncRef:
722 AE = AE.withKind(DoNothing);
723 break;
724 case DecRef:
725 AE = AE.withKind(DoNothing);
726 break;
727 case DecRefAndStopTrackingHard:
728 AE = AE.withKind(StopTracking);
729 break;
730 }
731 }
732
733 // Handle all use-after-releases.
734 if (V.getKind() == RefVal::Released) {
735 V = V ^ RefVal::ErrorUseAfterRelease;
736 hasErr = V.getKind();
737 return setRefBinding(state, sym, V);
738 }
739
740 switch (AE.getKind()) {
741 case UnretainedOutParameter:
742 case RetainedOutParameter:
743 case RetainedOutParameterOnZero:
744 case RetainedOutParameterOnNonZero:
745 llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
746 "not have ref state.");
747
748 case Dealloc: // NB. we only need to add a note in a non-error case.
749 switch (V.getKind()) {
750 default:
751 llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
752 case RefVal::Owned:
753 // The object immediately transitions to the released state.
754 V = V ^ RefVal::Released;
755 V.clearCounts();
756 return setRefBinding(state, sym, V);
757 case RefVal::NotOwned:
758 V = V ^ RefVal::ErrorDeallocNotOwned;
759 hasErr = V.getKind();
760 break;
761 }
762 break;
763
764 case MayEscape:
765 if (V.getKind() == RefVal::Owned) {
766 V = V ^ RefVal::NotOwned;
767 break;
768 }
769
770 LLVM_FALLTHROUGH;
771
772 case DoNothing:
773 return state;
774
775 case Autorelease:
776 // Update the autorelease counts.
777 V = V.autorelease();
778 break;
779
780 case StopTracking:
781 case StopTrackingHard:
782 return removeRefBinding(state, sym);
783
784 case IncRef:
785 switch (V.getKind()) {
786 default:
787 llvm_unreachable("Invalid RefVal state for a retain.");
788 case RefVal::Owned:
789 case RefVal::NotOwned:
790 V = V + 1;
791 break;
792 }
793 break;
794
795 case DecRef:
796 case DecRefBridgedTransferred:
797 case DecRefAndStopTrackingHard:
798 switch (V.getKind()) {
799 default:
800 // case 'RefVal::Released' handled above.
801 llvm_unreachable("Invalid RefVal state for a release.");
802
803 case RefVal::Owned:
804 assert(V.getCount() > 0);
805 if (V.getCount() == 1) {
806 if (AE.getKind() == DecRefBridgedTransferred ||
807 V.getIvarAccessHistory() ==
808 RefVal::IvarAccessHistory::AccessedDirectly)
809 V = V ^ RefVal::NotOwned;
810 else
811 V = V ^ RefVal::Released;
812 } else if (AE.getKind() == DecRefAndStopTrackingHard) {
813 return removeRefBinding(state, sym);
814 }
815
816 V = V - 1;
817 break;
818
819 case RefVal::NotOwned:
820 if (V.getCount() > 0) {
821 if (AE.getKind() == DecRefAndStopTrackingHard)
822 return removeRefBinding(state, sym);
823 V = V - 1;
824 } else if (V.getIvarAccessHistory() ==
825 RefVal::IvarAccessHistory::AccessedDirectly) {
826 // Assume that the instance variable was holding on the object at
827 // +1, and we just didn't know.
828 if (AE.getKind() == DecRefAndStopTrackingHard)
829 return removeRefBinding(state, sym);
830 V = V.releaseViaIvar() ^ RefVal::Released;
831 } else {
832 V = V ^ RefVal::ErrorReleaseNotOwned;
833 hasErr = V.getKind();
834 }
835 break;
836 }
837 break;
838 }
839 return setRefBinding(state, sym, V);
840 }
841
842 const RefCountBug &
errorKindToBugKind(RefVal::Kind ErrorKind,SymbolRef Sym) const843 RetainCountChecker::errorKindToBugKind(RefVal::Kind ErrorKind,
844 SymbolRef Sym) const {
845 switch (ErrorKind) {
846 case RefVal::ErrorUseAfterRelease:
847 return *UseAfterRelease;
848 case RefVal::ErrorReleaseNotOwned:
849 return *ReleaseNotOwned;
850 case RefVal::ErrorDeallocNotOwned:
851 if (Sym->getType()->getPointeeCXXRecordDecl())
852 return *FreeNotOwned;
853 return *DeallocNotOwned;
854 default:
855 llvm_unreachable("Unhandled error.");
856 }
857 }
858
processNonLeakError(ProgramStateRef St,SourceRange ErrorRange,RefVal::Kind ErrorKind,SymbolRef Sym,CheckerContext & C) const859 void RetainCountChecker::processNonLeakError(ProgramStateRef St,
860 SourceRange ErrorRange,
861 RefVal::Kind ErrorKind,
862 SymbolRef Sym,
863 CheckerContext &C) const {
864 // HACK: Ignore retain-count issues on values accessed through ivars,
865 // because of cases like this:
866 // [_contentView retain];
867 // [_contentView removeFromSuperview];
868 // [self addSubview:_contentView]; // invalidates 'self'
869 // [_contentView release];
870 if (const RefVal *RV = getRefBinding(St, Sym))
871 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
872 return;
873
874 ExplodedNode *N = C.generateErrorNode(St);
875 if (!N)
876 return;
877
878 auto report = std::make_unique<RefCountReport>(
879 errorKindToBugKind(ErrorKind, Sym),
880 C.getASTContext().getLangOpts(), N, Sym);
881 report->addRange(ErrorRange);
882 C.emitReport(std::move(report));
883 }
884
885 //===----------------------------------------------------------------------===//
886 // Handle the return values of retain-count-related functions.
887 //===----------------------------------------------------------------------===//
888
evalCall(const CallEvent & Call,CheckerContext & C) const889 bool RetainCountChecker::evalCall(const CallEvent &Call,
890 CheckerContext &C) const {
891 ProgramStateRef state = C.getState();
892 const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
893 if (!FD)
894 return false;
895
896 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
897 if (!CE)
898 return false;
899
900 RetainSummaryManager &SmrMgr = getSummaryManager(C);
901 QualType ResultTy = Call.getResultType();
902
903 // See if the function has 'rc_ownership_trusted_implementation'
904 // annotate attribute. If it does, we will not inline it.
905 bool hasTrustedImplementationAnnotation = false;
906
907 const LocationContext *LCtx = C.getLocationContext();
908
909 using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
910 Optional<BehaviorSummary> BSmr =
911 SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
912
913 // See if it's one of the specific functions we know how to eval.
914 if (!BSmr)
915 return false;
916
917 // Bind the return value.
918 if (BSmr == BehaviorSummary::Identity ||
919 BSmr == BehaviorSummary::IdentityOrZero ||
920 BSmr == BehaviorSummary::IdentityThis) {
921
922 const Expr *BindReturnTo =
923 (BSmr == BehaviorSummary::IdentityThis)
924 ? cast<CXXMemberCallExpr>(CE)->getImplicitObjectArgument()
925 : CE->getArg(0);
926 SVal RetVal = state->getSVal(BindReturnTo, LCtx);
927
928 // If the receiver is unknown or the function has
929 // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
930 // return value.
931 // FIXME: this branch is very strange.
932 if (RetVal.isUnknown() ||
933 (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
934 SValBuilder &SVB = C.getSValBuilder();
935 RetVal =
936 SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
937 }
938
939 // Bind the value.
940 state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
941
942 if (BSmr == BehaviorSummary::IdentityOrZero) {
943 // Add a branch where the output is zero.
944 ProgramStateRef NullOutputState = C.getState();
945
946 // Assume that output is zero on the other branch.
947 NullOutputState = NullOutputState->BindExpr(
948 CE, LCtx, C.getSValBuilder().makeNullWithType(ResultTy),
949 /*Invalidate=*/false);
950 C.addTransition(NullOutputState, &getCastFailTag());
951
952 // And on the original branch assume that both input and
953 // output are non-zero.
954 if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
955 state = state->assume(*L, /*assumption=*/true);
956
957 }
958 }
959
960 C.addTransition(state);
961 return true;
962 }
963
processReturn(const ReturnStmt * S,CheckerContext & C) const964 ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
965 CheckerContext &C) const {
966 ExplodedNode *Pred = C.getPredecessor();
967
968 // Only adjust the reference count if this is the top-level call frame,
969 // and not the result of inlining. In the future, we should do
970 // better checking even for inlined calls, and see if they match
971 // with their expected semantics (e.g., the method should return a retained
972 // object, etc.).
973 if (!C.inTopFrame())
974 return Pred;
975
976 if (!S)
977 return Pred;
978
979 const Expr *RetE = S->getRetValue();
980 if (!RetE)
981 return Pred;
982
983 ProgramStateRef state = C.getState();
984 // We need to dig down to the symbolic base here because various
985 // custom allocators do sometimes return the symbol with an offset.
986 SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getLocationContext())
987 .getAsLocSymbol(/*IncludeBaseRegions=*/true);
988 if (!Sym)
989 return Pred;
990
991 // Get the reference count binding (if any).
992 const RefVal *T = getRefBinding(state, Sym);
993 if (!T)
994 return Pred;
995
996 // Change the reference count.
997 RefVal X = *T;
998
999 switch (X.getKind()) {
1000 case RefVal::Owned: {
1001 unsigned cnt = X.getCount();
1002 assert(cnt > 0);
1003 X.setCount(cnt - 1);
1004 X = X ^ RefVal::ReturnedOwned;
1005 break;
1006 }
1007
1008 case RefVal::NotOwned: {
1009 unsigned cnt = X.getCount();
1010 if (cnt) {
1011 X.setCount(cnt - 1);
1012 X = X ^ RefVal::ReturnedOwned;
1013 } else {
1014 X = X ^ RefVal::ReturnedNotOwned;
1015 }
1016 break;
1017 }
1018
1019 default:
1020 return Pred;
1021 }
1022
1023 // Update the binding.
1024 state = setRefBinding(state, Sym, X);
1025 Pred = C.addTransition(state);
1026
1027 // At this point we have updated the state properly.
1028 // Everything after this is merely checking to see if the return value has
1029 // been over- or under-retained.
1030
1031 // Did we cache out?
1032 if (!Pred)
1033 return nullptr;
1034
1035 // Update the autorelease counts.
1036 static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
1037 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
1038
1039 // Have we generated a sink node?
1040 if (!state)
1041 return nullptr;
1042
1043 // Get the updated binding.
1044 T = getRefBinding(state, Sym);
1045 assert(T);
1046 X = *T;
1047
1048 // Consult the summary of the enclosing method.
1049 RetainSummaryManager &Summaries = getSummaryManager(C);
1050 const Decl *CD = &Pred->getCodeDecl();
1051 RetEffect RE = RetEffect::MakeNoRet();
1052
1053 // FIXME: What is the convention for blocks? Is there one?
1054 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
1055 const RetainSummary *Summ = Summaries.getSummary(AnyCall(MD));
1056 RE = Summ->getRetEffect();
1057 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
1058 if (!isa<CXXMethodDecl>(FD)) {
1059 const RetainSummary *Summ = Summaries.getSummary(AnyCall(FD));
1060 RE = Summ->getRetEffect();
1061 }
1062 }
1063
1064 return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
1065 }
1066
checkReturnWithRetEffect(const ReturnStmt * S,CheckerContext & C,ExplodedNode * Pred,RetEffect RE,RefVal X,SymbolRef Sym,ProgramStateRef state) const1067 ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
1068 CheckerContext &C,
1069 ExplodedNode *Pred,
1070 RetEffect RE, RefVal X,
1071 SymbolRef Sym,
1072 ProgramStateRef state) const {
1073 // HACK: Ignore retain-count issues on values accessed through ivars,
1074 // because of cases like this:
1075 // [_contentView retain];
1076 // [_contentView removeFromSuperview];
1077 // [self addSubview:_contentView]; // invalidates 'self'
1078 // [_contentView release];
1079 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1080 return Pred;
1081
1082 // Any leaks or other errors?
1083 if (X.isReturnedOwned() && X.getCount() == 0) {
1084 if (RE.getKind() != RetEffect::NoRet) {
1085 if (!RE.isOwned()) {
1086
1087 // The returning type is a CF, we expect the enclosing method should
1088 // return ownership.
1089 X = X ^ RefVal::ErrorLeakReturned;
1090
1091 // Generate an error node.
1092 state = setRefBinding(state, Sym, X);
1093
1094 static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
1095 ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
1096 if (N) {
1097 const LangOptions &LOpts = C.getASTContext().getLangOpts();
1098 auto R =
1099 std::make_unique<RefLeakReport>(*LeakAtReturn, LOpts, N, Sym, C);
1100 C.emitReport(std::move(R));
1101 }
1102 return N;
1103 }
1104 }
1105 } else if (X.isReturnedNotOwned()) {
1106 if (RE.isOwned()) {
1107 if (X.getIvarAccessHistory() ==
1108 RefVal::IvarAccessHistory::AccessedDirectly) {
1109 // Assume the method was trying to transfer a +1 reference from a
1110 // strong ivar to the caller.
1111 state = setRefBinding(state, Sym,
1112 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
1113 } else {
1114 // Trying to return a not owned object to a caller expecting an
1115 // owned object.
1116 state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
1117
1118 static CheckerProgramPointTag
1119 ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
1120
1121 ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
1122 if (N) {
1123 auto R = std::make_unique<RefCountReport>(
1124 *ReturnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
1125 C.emitReport(std::move(R));
1126 }
1127 return N;
1128 }
1129 }
1130 }
1131 return Pred;
1132 }
1133
1134 //===----------------------------------------------------------------------===//
1135 // Check various ways a symbol can be invalidated.
1136 //===----------------------------------------------------------------------===//
1137
checkBind(SVal loc,SVal val,const Stmt * S,CheckerContext & C) const1138 void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
1139 CheckerContext &C) const {
1140 ProgramStateRef state = C.getState();
1141 const MemRegion *MR = loc.getAsRegion();
1142
1143 // Find all symbols referenced by 'val' that we are tracking
1144 // and stop tracking them.
1145 if (MR && shouldEscapeRegion(MR)) {
1146 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1147 C.addTransition(state);
1148 }
1149 }
1150
evalAssume(ProgramStateRef state,SVal Cond,bool Assumption) const1151 ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
1152 SVal Cond,
1153 bool Assumption) const {
1154 // FIXME: We may add to the interface of evalAssume the list of symbols
1155 // whose assumptions have changed. For now we just iterate through the
1156 // bindings and check if any of the tracked symbols are NULL. This isn't
1157 // too bad since the number of symbols we will track in practice are
1158 // probably small and evalAssume is only called at branches and a few
1159 // other places.
1160 RefBindingsTy B = state->get<RefBindings>();
1161
1162 if (B.isEmpty())
1163 return state;
1164
1165 bool changed = false;
1166 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1167 ConstraintManager &CMgr = state->getConstraintManager();
1168
1169 for (auto &I : B) {
1170 // Check if the symbol is null stop tracking the symbol.
1171 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.first);
1172 if (AllocFailed.isConstrainedTrue()) {
1173 changed = true;
1174 B = RefBFactory.remove(B, I.first);
1175 }
1176 }
1177
1178 if (changed)
1179 state = state->set<RefBindings>(B);
1180
1181 return state;
1182 }
1183
checkRegionChanges(ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > ExplicitRegions,ArrayRef<const MemRegion * > Regions,const LocationContext * LCtx,const CallEvent * Call) const1184 ProgramStateRef RetainCountChecker::checkRegionChanges(
1185 ProgramStateRef state, const InvalidatedSymbols *invalidated,
1186 ArrayRef<const MemRegion *> ExplicitRegions,
1187 ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
1188 const CallEvent *Call) const {
1189 if (!invalidated)
1190 return state;
1191
1192 llvm::SmallPtrSet<SymbolRef, 8> AllowedSymbols;
1193
1194 for (const MemRegion *I : ExplicitRegions)
1195 if (const SymbolicRegion *SR = I->StripCasts()->getAs<SymbolicRegion>())
1196 AllowedSymbols.insert(SR->getSymbol());
1197
1198 for (SymbolRef sym : *invalidated) {
1199 if (AllowedSymbols.count(sym))
1200 continue;
1201 // Remove any existing reference-count binding.
1202 state = removeRefBinding(state, sym);
1203 }
1204 return state;
1205 }
1206
1207 ProgramStateRef
handleAutoreleaseCounts(ProgramStateRef state,ExplodedNode * Pred,const ProgramPointTag * Tag,CheckerContext & Ctx,SymbolRef Sym,RefVal V,const ReturnStmt * S) const1208 RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1209 ExplodedNode *Pred,
1210 const ProgramPointTag *Tag,
1211 CheckerContext &Ctx,
1212 SymbolRef Sym,
1213 RefVal V,
1214 const ReturnStmt *S) const {
1215 unsigned ACnt = V.getAutoreleaseCount();
1216
1217 // No autorelease counts? Nothing to be done.
1218 if (!ACnt)
1219 return state;
1220
1221 unsigned Cnt = V.getCount();
1222
1223 // FIXME: Handle sending 'autorelease' to already released object.
1224
1225 if (V.getKind() == RefVal::ReturnedOwned)
1226 ++Cnt;
1227
1228 // If we would over-release here, but we know the value came from an ivar,
1229 // assume it was a strong ivar that's just been relinquished.
1230 if (ACnt > Cnt &&
1231 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1232 V = V.releaseViaIvar();
1233 --ACnt;
1234 }
1235
1236 if (ACnt <= Cnt) {
1237 if (ACnt == Cnt) {
1238 V.clearCounts();
1239 if (V.getKind() == RefVal::ReturnedOwned) {
1240 V = V ^ RefVal::ReturnedNotOwned;
1241 } else {
1242 V = V ^ RefVal::NotOwned;
1243 }
1244 } else {
1245 V.setCount(V.getCount() - ACnt);
1246 V.setAutoreleaseCount(0);
1247 }
1248 return setRefBinding(state, Sym, V);
1249 }
1250
1251 // HACK: Ignore retain-count issues on values accessed through ivars,
1252 // because of cases like this:
1253 // [_contentView retain];
1254 // [_contentView removeFromSuperview];
1255 // [self addSubview:_contentView]; // invalidates 'self'
1256 // [_contentView release];
1257 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1258 return state;
1259
1260 // Woah! More autorelease counts then retain counts left.
1261 // Emit hard error.
1262 V = V ^ RefVal::ErrorOverAutorelease;
1263 state = setRefBinding(state, Sym, V);
1264
1265 ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1266 if (N) {
1267 SmallString<128> sbuf;
1268 llvm::raw_svector_ostream os(sbuf);
1269 os << "Object was autoreleased ";
1270 if (V.getAutoreleaseCount() > 1)
1271 os << V.getAutoreleaseCount() << " times but the object ";
1272 else
1273 os << "but ";
1274 os << "has a +" << V.getCount() << " retain count";
1275
1276 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1277 auto R = std::make_unique<RefCountReport>(*OverAutorelease, LOpts, N, Sym,
1278 os.str());
1279 Ctx.emitReport(std::move(R));
1280 }
1281
1282 return nullptr;
1283 }
1284
1285 ProgramStateRef
handleSymbolDeath(ProgramStateRef state,SymbolRef sid,RefVal V,SmallVectorImpl<SymbolRef> & Leaked) const1286 RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1287 SymbolRef sid, RefVal V,
1288 SmallVectorImpl<SymbolRef> &Leaked) const {
1289 bool hasLeak;
1290
1291 // HACK: Ignore retain-count issues on values accessed through ivars,
1292 // because of cases like this:
1293 // [_contentView retain];
1294 // [_contentView removeFromSuperview];
1295 // [self addSubview:_contentView]; // invalidates 'self'
1296 // [_contentView release];
1297 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1298 hasLeak = false;
1299 else if (V.isOwned())
1300 hasLeak = true;
1301 else if (V.isNotOwned() || V.isReturnedOwned())
1302 hasLeak = (V.getCount() > 0);
1303 else
1304 hasLeak = false;
1305
1306 if (!hasLeak)
1307 return removeRefBinding(state, sid);
1308
1309 Leaked.push_back(sid);
1310 return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1311 }
1312
1313 ExplodedNode *
processLeaks(ProgramStateRef state,SmallVectorImpl<SymbolRef> & Leaked,CheckerContext & Ctx,ExplodedNode * Pred) const1314 RetainCountChecker::processLeaks(ProgramStateRef state,
1315 SmallVectorImpl<SymbolRef> &Leaked,
1316 CheckerContext &Ctx,
1317 ExplodedNode *Pred) const {
1318 // Generate an intermediate node representing the leak point.
1319 ExplodedNode *N = Ctx.addTransition(state, Pred);
1320 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1321
1322 if (N) {
1323 for (SymbolRef L : Leaked) {
1324 const RefCountBug &BT = Pred ? *LeakWithinFunction : *LeakAtReturn;
1325 Ctx.emitReport(std::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx));
1326 }
1327 }
1328
1329 return N;
1330 }
1331
checkBeginFunction(CheckerContext & Ctx) const1332 void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1333 if (!Ctx.inTopFrame())
1334 return;
1335
1336 RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
1337 const LocationContext *LCtx = Ctx.getLocationContext();
1338 const Decl *D = LCtx->getDecl();
1339 Optional<AnyCall> C = AnyCall::forDecl(D);
1340
1341 if (!C || SmrMgr.isTrustedReferenceCountImplementation(D))
1342 return;
1343
1344 ProgramStateRef state = Ctx.getState();
1345 const RetainSummary *FunctionSummary = SmrMgr.getSummary(*C);
1346 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1347
1348 for (unsigned idx = 0, e = C->param_size(); idx != e; ++idx) {
1349 const ParmVarDecl *Param = C->parameters()[idx];
1350 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1351
1352 QualType Ty = Param->getType();
1353 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
1354 if (AE) {
1355 ObjKind K = AE->getObjKind();
1356 if (K == ObjKind::Generalized || K == ObjKind::OS ||
1357 (TrackNSCFStartParam && (K == ObjKind::ObjC || K == ObjKind::CF))) {
1358 RefVal NewVal = AE->getKind() == DecRef ? RefVal::makeOwned(K, Ty)
1359 : RefVal::makeNotOwned(K, Ty);
1360 state = setRefBinding(state, Sym, NewVal);
1361 }
1362 }
1363 }
1364
1365 Ctx.addTransition(state);
1366 }
1367
checkEndFunction(const ReturnStmt * RS,CheckerContext & Ctx) const1368 void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1369 CheckerContext &Ctx) const {
1370 ExplodedNode *Pred = processReturn(RS, Ctx);
1371
1372 // Created state cached out.
1373 if (!Pred) {
1374 return;
1375 }
1376
1377 ProgramStateRef state = Pred->getState();
1378 RefBindingsTy B = state->get<RefBindings>();
1379
1380 // Don't process anything within synthesized bodies.
1381 const LocationContext *LCtx = Pred->getLocationContext();
1382 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1383 assert(!LCtx->inTopFrame());
1384 return;
1385 }
1386
1387 for (auto &I : B) {
1388 state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1389 I.first, I.second);
1390 if (!state)
1391 return;
1392 }
1393
1394 // If the current LocationContext has a parent, don't check for leaks.
1395 // We will do that later.
1396 // FIXME: we should instead check for imbalances of the retain/releases,
1397 // and suggest annotations.
1398 if (LCtx->getParent())
1399 return;
1400
1401 B = state->get<RefBindings>();
1402 SmallVector<SymbolRef, 10> Leaked;
1403
1404 for (auto &I : B)
1405 state = handleSymbolDeath(state, I.first, I.second, Leaked);
1406
1407 processLeaks(state, Leaked, Ctx, Pred);
1408 }
1409
checkDeadSymbols(SymbolReaper & SymReaper,CheckerContext & C) const1410 void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1411 CheckerContext &C) const {
1412 ExplodedNode *Pred = C.getPredecessor();
1413
1414 ProgramStateRef state = C.getState();
1415 SmallVector<SymbolRef, 10> Leaked;
1416
1417 // Update counts from autorelease pools
1418 for (const auto &I: state->get<RefBindings>()) {
1419 SymbolRef Sym = I.first;
1420 if (SymReaper.isDead(Sym)) {
1421 static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
1422 const RefVal &V = I.second;
1423 state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
1424 if (!state)
1425 return;
1426
1427 // Fetch the new reference count from the state, and use it to handle
1428 // this symbol.
1429 state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
1430 }
1431 }
1432
1433 if (Leaked.empty()) {
1434 C.addTransition(state);
1435 return;
1436 }
1437
1438 Pred = processLeaks(state, Leaked, C, Pred);
1439
1440 // Did we cache out?
1441 if (!Pred)
1442 return;
1443
1444 // Now generate a new node that nukes the old bindings.
1445 // The only bindings left at this point are the leaked symbols.
1446 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1447 RefBindingsTy B = state->get<RefBindings>();
1448
1449 for (SymbolRef L : Leaked)
1450 B = F.remove(B, L);
1451
1452 state = state->set<RefBindings>(B);
1453 C.addTransition(state, Pred);
1454 }
1455
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep) const1456 void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1457 const char *NL, const char *Sep) const {
1458
1459 RefBindingsTy B = State->get<RefBindings>();
1460
1461 if (B.isEmpty())
1462 return;
1463
1464 Out << Sep << NL;
1465
1466 for (auto &I : B) {
1467 Out << I.first << " : ";
1468 I.second.print(Out);
1469 Out << NL;
1470 }
1471 }
1472
1473 //===----------------------------------------------------------------------===//
1474 // Checker registration.
1475 //===----------------------------------------------------------------------===//
1476
1477 std::unique_ptr<CheckerProgramPointTag> RetainCountChecker::DeallocSentTag;
1478 std::unique_ptr<CheckerProgramPointTag> RetainCountChecker::CastFailTag;
1479
registerRetainCountBase(CheckerManager & Mgr)1480 void ento::registerRetainCountBase(CheckerManager &Mgr) {
1481 auto *Chk = Mgr.registerChecker<RetainCountChecker>();
1482 Chk->DeallocSentTag =
1483 std::make_unique<CheckerProgramPointTag>(Chk, "DeallocSent");
1484 Chk->CastFailTag =
1485 std::make_unique<CheckerProgramPointTag>(Chk, "DynamicCastFail");
1486 }
1487
shouldRegisterRetainCountBase(const CheckerManager & mgr)1488 bool ento::shouldRegisterRetainCountBase(const CheckerManager &mgr) {
1489 return true;
1490 }
registerRetainCountChecker(CheckerManager & Mgr)1491 void ento::registerRetainCountChecker(CheckerManager &Mgr) {
1492 auto *Chk = Mgr.getChecker<RetainCountChecker>();
1493 Chk->TrackObjCAndCFObjects = true;
1494 Chk->TrackNSCFStartParam = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
1495 Mgr.getCurrentCheckerName(), "TrackNSCFStartParam");
1496
1497 #define INIT_BUGTYPE(KIND) \
1498 Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName(), \
1499 RefCountBug::KIND);
1500 // TODO: Ideally, we should have a checker for each of these bug types.
1501 INIT_BUGTYPE(UseAfterRelease)
1502 INIT_BUGTYPE(ReleaseNotOwned)
1503 INIT_BUGTYPE(DeallocNotOwned)
1504 INIT_BUGTYPE(FreeNotOwned)
1505 INIT_BUGTYPE(OverAutorelease)
1506 INIT_BUGTYPE(ReturnNotOwnedForOwned)
1507 INIT_BUGTYPE(LeakWithinFunction)
1508 INIT_BUGTYPE(LeakAtReturn)
1509 #undef INIT_BUGTYPE
1510 }
1511
shouldRegisterRetainCountChecker(const CheckerManager & mgr)1512 bool ento::shouldRegisterRetainCountChecker(const CheckerManager &mgr) {
1513 return true;
1514 }
1515
registerOSObjectRetainCountChecker(CheckerManager & Mgr)1516 void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1517 auto *Chk = Mgr.getChecker<RetainCountChecker>();
1518 Chk->TrackOSObjects = true;
1519
1520 // FIXME: We want bug reports to always have the same checker name associated
1521 // with them, yet here, if RetainCountChecker is disabled but
1522 // OSObjectRetainCountChecker is enabled, the checker names will be different.
1523 // This hack will make it so that the checker name depends on which checker is
1524 // enabled rather than on the registration order.
1525 // For the most part, we want **non-hidden checkers** to be associated with
1526 // diagnostics, and **hidden checker options** with the fine-tuning of
1527 // modeling. Following this logic, OSObjectRetainCountChecker should be the
1528 // latter, but we can't just remove it for backward compatibility reasons.
1529 #define LAZY_INIT_BUGTYPE(KIND) \
1530 if (!Chk->KIND) \
1531 Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName(), \
1532 RefCountBug::KIND);
1533 LAZY_INIT_BUGTYPE(UseAfterRelease)
1534 LAZY_INIT_BUGTYPE(ReleaseNotOwned)
1535 LAZY_INIT_BUGTYPE(DeallocNotOwned)
1536 LAZY_INIT_BUGTYPE(FreeNotOwned)
1537 LAZY_INIT_BUGTYPE(OverAutorelease)
1538 LAZY_INIT_BUGTYPE(ReturnNotOwnedForOwned)
1539 LAZY_INIT_BUGTYPE(LeakWithinFunction)
1540 LAZY_INIT_BUGTYPE(LeakAtReturn)
1541 #undef LAZY_INIT_BUGTYPE
1542 }
1543
shouldRegisterOSObjectRetainCountChecker(const CheckerManager & mgr)1544 bool ento::shouldRegisterOSObjectRetainCountChecker(const CheckerManager &mgr) {
1545 return true;
1546 }
1547