blob: a9b6d6839d910ac3b96066e3378d63017c86605f [file] [log] [blame]
George Karpenkov70c2ee32018-08-17 21:41:07 +00001//==-- RetainCountChecker.cpp - Checks for leaks and other issues -*- C++ -*--//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the methods for RetainCountChecker, which implements
11// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
15#include "RetainCountChecker.h"
16
17using namespace clang;
18using namespace ento;
George Karpenkov70c2ee32018-08-17 21:41:07 +000019using namespace retaincountchecker;
20using llvm::StrInStrNoCase;
21
22REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
23
24namespace clang {
25namespace ento {
26namespace retaincountchecker {
27
28const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) {
29 return State->get<RefBindings>(Sym);
30}
31
32ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
33 RefVal Val) {
George Karpenkovd5ef0d22018-08-29 20:28:33 +000034 assert(Sym != nullptr);
George Karpenkov70c2ee32018-08-17 21:41:07 +000035 return State->set<RefBindings>(Sym, Val);
36}
37
38ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym) {
39 return State->remove<RefBindings>(Sym);
40}
41
George Karpenkov62db8862018-11-30 02:18:23 +000042class UseAfterRelease : public CFRefBug {
43public:
44 UseAfterRelease(const CheckerBase *checker)
45 : CFRefBug(checker, "Use-after-release") {}
46
47 const char *getDescription() const override {
48 return "Reference-counted object is used after it is released";
49 }
50};
51
52class BadRelease : public CFRefBug {
53public:
54 BadRelease(const CheckerBase *checker) : CFRefBug(checker, "Bad release") {}
55
56 const char *getDescription() const override {
57 return "Incorrect decrement of the reference count of an object that is "
58 "not owned at this point by the caller";
59 }
60};
61
62class DeallocNotOwned : public CFRefBug {
63public:
64 DeallocNotOwned(const CheckerBase *checker)
65 : CFRefBug(checker, "-dealloc sent to non-exclusively owned object") {}
66
67 const char *getDescription() const override {
68 return "-dealloc sent to object that may be referenced elsewhere";
69 }
70};
71
72class OverAutorelease : public CFRefBug {
73public:
74 OverAutorelease(const CheckerBase *checker)
75 : CFRefBug(checker, "Object autoreleased too many times") {}
76
77 const char *getDescription() const override {
78 return "Object autoreleased too many times";
79 }
80};
81
82class ReturnedNotOwnedForOwned : public CFRefBug {
83public:
84 ReturnedNotOwnedForOwned(const CheckerBase *checker)
85 : CFRefBug(checker, "Method should return an owned object") {}
86
87 const char *getDescription() const override {
88 return "Object with a +0 retain count returned to caller where a +1 "
89 "(owning) retain count is expected";
90 }
91};
92
93class Leak : public CFRefBug {
94public:
95 Leak(const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
96 // Leaks should not be reported if they are post-dominated by a sink.
97 setSuppressOnSink(true);
98 }
99
100 const char *getDescription() const override { return ""; }
101
102 bool isLeak() const override { return true; }
103};
104
George Karpenkov70c2ee32018-08-17 21:41:07 +0000105} // end namespace retaincountchecker
106} // end namespace ento
107} // end namespace clang
108
109void RefVal::print(raw_ostream &Out) const {
110 if (!T.isNull())
George Karpenkov081c4772018-10-23 23:11:50 +0000111 Out << "Tracked " << T.getAsString() << " | ";
George Karpenkov70c2ee32018-08-17 21:41:07 +0000112
113 switch (getKind()) {
114 default: llvm_unreachable("Invalid RefVal kind");
115 case Owned: {
116 Out << "Owned";
117 unsigned cnt = getCount();
118 if (cnt) Out << " (+ " << cnt << ")";
119 break;
120 }
121
122 case NotOwned: {
123 Out << "NotOwned";
124 unsigned cnt = getCount();
125 if (cnt) Out << " (+ " << cnt << ")";
126 break;
127 }
128
129 case ReturnedOwned: {
130 Out << "ReturnedOwned";
131 unsigned cnt = getCount();
132 if (cnt) Out << " (+ " << cnt << ")";
133 break;
134 }
135
136 case ReturnedNotOwned: {
137 Out << "ReturnedNotOwned";
138 unsigned cnt = getCount();
139 if (cnt) Out << " (+ " << cnt << ")";
140 break;
141 }
142
143 case Released:
144 Out << "Released";
145 break;
146
147 case ErrorDeallocNotOwned:
148 Out << "-dealloc (not-owned)";
149 break;
150
151 case ErrorLeak:
152 Out << "Leaked";
153 break;
154
155 case ErrorLeakReturned:
156 Out << "Leaked (Bad naming)";
157 break;
158
159 case ErrorUseAfterRelease:
160 Out << "Use-After-Release [ERROR]";
161 break;
162
163 case ErrorReleaseNotOwned:
164 Out << "Release of Not-Owned [ERROR]";
165 break;
166
167 case RefVal::ErrorOverAutorelease:
168 Out << "Over-autoreleased";
169 break;
170
171 case RefVal::ErrorReturnedNotOwned:
172 Out << "Non-owned object returned instead of owned";
173 break;
174 }
175
176 switch (getIvarAccessHistory()) {
177 case IvarAccessHistory::None:
178 break;
179 case IvarAccessHistory::AccessedDirectly:
180 Out << " [direct ivar access]";
181 break;
182 case IvarAccessHistory::ReleasedAfterDirectAccess:
183 Out << " [released after direct ivar access]";
184 }
185
186 if (ACnt) {
187 Out << " [autorelease -" << ACnt << ']';
188 }
189}
190
191namespace {
192class StopTrackingCallback final : public SymbolVisitor {
193 ProgramStateRef state;
194public:
195 StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
196 ProgramStateRef getState() const { return state; }
197
198 bool VisitSymbol(SymbolRef sym) override {
199 state = state->remove<RefBindings>(sym);
200 return true;
201 }
202};
203} // end anonymous namespace
204
205//===----------------------------------------------------------------------===//
206// Handle statements that may have an effect on refcounts.
207//===----------------------------------------------------------------------===//
208
209void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
210 CheckerContext &C) const {
211
212 // Scan the BlockDecRefExprs for any object the retain count checker
213 // may be tracking.
214 if (!BE->getBlockDecl()->hasCaptures())
215 return;
216
217 ProgramStateRef state = C.getState();
218 auto *R = cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
219
220 BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
221 E = R->referenced_vars_end();
222
223 if (I == E)
224 return;
225
226 // FIXME: For now we invalidate the tracking of all symbols passed to blocks
227 // via captured variables, even though captured variables result in a copy
228 // and in implicit increment/decrement of a retain count.
229 SmallVector<const MemRegion*, 10> Regions;
230 const LocationContext *LC = C.getLocationContext();
231 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
232
233 for ( ; I != E; ++I) {
234 const VarRegion *VR = I.getCapturedRegion();
235 if (VR->getSuperRegion() == R) {
236 VR = MemMgr.getVarRegion(VR->getDecl(), LC);
237 }
238 Regions.push_back(VR);
239 }
240
George Karpenkovd3e76752018-10-23 23:12:12 +0000241 state = state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000242 C.addTransition(state);
243}
244
245void RetainCountChecker::checkPostStmt(const CastExpr *CE,
246 CheckerContext &C) const {
247 const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
248 if (!BE)
249 return;
250
251 ArgEffect AE = IncRef;
252
253 switch (BE->getBridgeKind()) {
254 case OBC_Bridge:
255 // Do nothing.
256 return;
257 case OBC_BridgeRetained:
258 AE = IncRef;
259 break;
260 case OBC_BridgeTransfer:
261 AE = DecRefBridgedTransferred;
262 break;
263 }
264
265 ProgramStateRef state = C.getState();
266 SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();
267 if (!Sym)
268 return;
269 const RefVal* T = getRefBinding(state, Sym);
270 if (!T)
271 return;
272
273 RefVal::Kind hasErr = (RefVal::Kind) 0;
274 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
275
276 if (hasErr) {
277 // FIXME: If we get an error during a bridge cast, should we report it?
278 return;
279 }
280
281 C.addTransition(state);
282}
283
284void RetainCountChecker::processObjCLiterals(CheckerContext &C,
285 const Expr *Ex) const {
286 ProgramStateRef state = C.getState();
287 const ExplodedNode *pred = C.getPredecessor();
288 for (const Stmt *Child : Ex->children()) {
289 SVal V = pred->getSVal(Child);
290 if (SymbolRef sym = V.getAsSymbol())
291 if (const RefVal* T = getRefBinding(state, sym)) {
292 RefVal::Kind hasErr = (RefVal::Kind) 0;
293 state = updateSymbol(state, sym, *T, MayEscape, hasErr, C);
294 if (hasErr) {
295 processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
296 return;
297 }
298 }
299 }
300
301 // Return the object as autoreleased.
George Karpenkov7e3016d2019-01-10 18:13:46 +0000302 // RetEffect RE = RetEffect::MakeNotOwned(ObjKind::ObjC);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000303 if (SymbolRef sym =
304 state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
305 QualType ResultTy = Ex->getType();
306 state = setRefBinding(state, sym,
George Karpenkov7e3016d2019-01-10 18:13:46 +0000307 RefVal::makeNotOwned(ObjKind::ObjC, ResultTy));
George Karpenkov70c2ee32018-08-17 21:41:07 +0000308 }
309
310 C.addTransition(state);
311}
312
313void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
314 CheckerContext &C) const {
315 // Apply the 'MayEscape' to all values.
316 processObjCLiterals(C, AL);
317}
318
319void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
320 CheckerContext &C) const {
321 // Apply the 'MayEscape' to all keys and values.
322 processObjCLiterals(C, DL);
323}
324
325void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
326 CheckerContext &C) const {
327 const ExplodedNode *Pred = C.getPredecessor();
328 ProgramStateRef State = Pred->getState();
329
330 if (SymbolRef Sym = Pred->getSVal(Ex).getAsSymbol()) {
331 QualType ResultTy = Ex->getType();
332 State = setRefBinding(State, Sym,
George Karpenkov7e3016d2019-01-10 18:13:46 +0000333 RefVal::makeNotOwned(ObjKind::ObjC, ResultTy));
George Karpenkov70c2ee32018-08-17 21:41:07 +0000334 }
335
336 C.addTransition(State);
337}
338
339void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
340 CheckerContext &C) const {
341 Optional<Loc> IVarLoc = C.getSVal(IRE).getAs<Loc>();
342 if (!IVarLoc)
343 return;
344
345 ProgramStateRef State = C.getState();
346 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
347 if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->getOriginRegion()))
348 return;
349
350 // Accessing an ivar directly is unusual. If we've done that, be more
351 // forgiving about what the surrounding code is allowed to do.
352
353 QualType Ty = Sym->getType();
George Karpenkov7e3016d2019-01-10 18:13:46 +0000354 ObjKind Kind;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000355 if (Ty->isObjCRetainableType())
George Karpenkov7e3016d2019-01-10 18:13:46 +0000356 Kind = ObjKind::ObjC;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000357 else if (coreFoundation::isCFObjectRef(Ty))
George Karpenkov7e3016d2019-01-10 18:13:46 +0000358 Kind = ObjKind::CF;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000359 else
360 return;
361
362 // If the value is already known to be nil, don't bother tracking it.
363 ConstraintManager &CMgr = State->getConstraintManager();
364 if (CMgr.isNull(State, Sym).isConstrainedTrue())
365 return;
366
367 if (const RefVal *RV = getRefBinding(State, Sym)) {
368 // If we've seen this symbol before, or we're only seeing it now because
369 // of something the analyzer has synthesized, don't do anything.
370 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
371 isSynthesizedAccessor(C.getStackFrame())) {
372 return;
373 }
374
375 // Note that this value has been loaded from an ivar.
376 C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));
377 return;
378 }
379
380 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
381
382 // In a synthesized accessor, the effective retain count is +0.
383 if (isSynthesizedAccessor(C.getStackFrame())) {
384 C.addTransition(setRefBinding(State, Sym, PlusZero));
385 return;
386 }
387
388 State = setRefBinding(State, Sym, PlusZero.withIvarAccess());
389 C.addTransition(State);
390}
391
392void RetainCountChecker::checkPostCall(const CallEvent &Call,
393 CheckerContext &C) const {
394 RetainSummaryManager &Summaries = getSummaryManager(C);
George Karpenkovefef49c2018-08-21 03:09:02 +0000395
396 // Leave null if no receiver.
397 QualType ReceiverType;
398 if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
399 if (MC->isInstanceMessage()) {
400 SVal ReceiverV = MC->getReceiverSVal();
401 if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
402 if (const RefVal *T = getRefBinding(C.getState(), Sym))
403 ReceiverType = T->getType();
404 }
405 }
406
407 const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000408
409 if (C.wasInlined) {
410 processSummaryOfInlined(*Summ, Call, C);
411 return;
412 }
413 checkSummary(*Summ, Call, C);
414}
415
George Karpenkov62db8862018-11-30 02:18:23 +0000416void RetainCountChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
417 ExprEngine &Eng) const {
418 // FIXME: This is a hack to make sure the summary log gets cleared between
419 // analyses of different code bodies.
420 //
421 // Why is this necessary? Because a checker's lifetime is tied to a
422 // translation unit, but an ExplodedGraph's lifetime is just a code body.
423 // Once in a blue moon, a new ExplodedNode will have the same address as an
424 // old one with an associated summary, and the bug report visitor gets very
425 // confused. (To make things worse, the summary lifetime is currently also
426 // tied to a code body, so we get a crash instead of incorrect results.)
427 //
428 // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
429 // changes, things will start going wrong again. Really the lifetime of this
430 // log needs to be tied to either the specific nodes in it or the entire
431 // ExplodedGraph, not to a specific part of the code being analyzed.
432 //
433 // (Also, having stateful local data means that the same checker can't be
434 // used from multiple threads, but a lot of checkers have incorrect
435 // assumptions about that anyway. So that wasn't a priority at the time of
436 // this fix.)
437 //
438 // This happens at the end of analysis, but bug reports are emitted /after/
439 // this point. So we can't just clear the summary log now. Instead, we mark
440 // that the next time we access the summary log, it should be cleared.
441
442 // If we never reset the summary log during /this/ code body analysis,
443 // there were no new summaries. There might still have been summaries from
444 // the /last/ analysis, so clear them out to make sure the bug report
445 // visitors don't get confused.
446 if (ShouldResetSummaryLog)
447 SummaryLog.clear();
448
449 ShouldResetSummaryLog = !SummaryLog.empty();
450}
451
452CFRefBug *
453RetainCountChecker::getLeakWithinFunctionBug(const LangOptions &LOpts) const {
454 if (!leakWithinFunction)
455 leakWithinFunction.reset(new Leak(this, "Leak"));
456 return leakWithinFunction.get();
457}
458
459CFRefBug *
460RetainCountChecker::getLeakAtReturnBug(const LangOptions &LOpts) const {
461 if (!leakAtReturn)
462 leakAtReturn.reset(new Leak(this, "Leak of returned object"));
463 return leakAtReturn.get();
464}
465
George Karpenkov70c2ee32018-08-17 21:41:07 +0000466/// GetReturnType - Used to get the return type of a message expression or
467/// function call with the intention of affixing that type to a tracked symbol.
468/// While the return type can be queried directly from RetEx, when
469/// invoking class methods we augment to the return type to be that of
470/// a pointer to the class (as opposed it just being id).
471// FIXME: We may be able to do this with related result types instead.
472// This function is probably overestimating.
473static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx) {
474 QualType RetTy = RetE->getType();
475 // If RetE is not a message expression just return its type.
476 // If RetE is a message expression, return its types if it is something
477 /// more specific than id.
478 if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
479 if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
480 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
481 PT->isObjCClassType()) {
482 // At this point we know the return type of the message expression is
483 // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
484 // is a call to a class method whose type we can resolve. In such
485 // cases, promote the return type to XXX* (where XXX is the class).
486 const ObjCInterfaceDecl *D = ME->getReceiverInterface();
487 return !D ? RetTy :
488 Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
489 }
490
491 return RetTy;
492}
493
George Karpenkov80c9e782018-08-22 01:16:49 +0000494static Optional<RefVal> refValFromRetEffect(RetEffect RE,
495 QualType ResultTy) {
496 if (RE.isOwned()) {
497 return RefVal::makeOwned(RE.getObjKind(), ResultTy);
498 } else if (RE.notOwned()) {
499 return RefVal::makeNotOwned(RE.getObjKind(), ResultTy);
500 }
501
502 return None;
503}
504
George Karpenkov255b0582018-12-21 19:13:40 +0000505static bool isPointerToObject(QualType QT) {
506 QualType PT = QT->getPointeeType();
507 if (!PT.isNull())
508 if (PT->getAsCXXRecordDecl())
509 return true;
510 return false;
511}
512
513/// Whether the tracked value should be escaped on a given call.
514/// OSObjects are escaped when passed to void * / etc.
515static bool shouldEscapeArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
516 const RefVal *TrackedValue) {
George Karpenkov7e3016d2019-01-10 18:13:46 +0000517 if (TrackedValue->getObjKind() != ObjKind::OS)
George Karpenkov255b0582018-12-21 19:13:40 +0000518 return false;
519 if (ArgIdx >= CE.parameters().size())
520 return false;
521 return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
522}
523
George Karpenkov70c2ee32018-08-17 21:41:07 +0000524// We don't always get the exact modeling of the function with regards to the
525// retain count checker even when the function is inlined. For example, we need
526// to stop tracking the symbols which were marked with StopTrackingHard.
527void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
528 const CallEvent &CallOrMsg,
529 CheckerContext &C) const {
530 ProgramStateRef state = C.getState();
531
532 // Evaluate the effect of the arguments.
533 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
George Karpenkov255b0582018-12-21 19:13:40 +0000534 SVal V = CallOrMsg.getArgSVal(idx);
535
536 if (SymbolRef Sym = V.getAsLocSymbol()) {
537 bool ShouldRemoveBinding = Summ.getArg(idx) == StopTrackingHard;
538 if (const RefVal *T = getRefBinding(state, Sym))
539 if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
540 ShouldRemoveBinding = true;
541
542 if (ShouldRemoveBinding)
George Karpenkov70c2ee32018-08-17 21:41:07 +0000543 state = removeRefBinding(state, Sym);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000544 }
545 }
546
547 // Evaluate the effect on the message receiver.
George Karpenkov6e9fd132018-08-22 01:17:09 +0000548 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000549 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
550 if (Summ.getReceiverEffect() == StopTrackingHard) {
551 state = removeRefBinding(state, Sym);
552 }
553 }
554 }
555
556 // Consult the summary for the return value.
557 RetEffect RE = Summ.getRetEffect();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000558
George Karpenkovd5ef0d22018-08-29 20:28:33 +0000559 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
George Karpenkovd5ef0d22018-08-29 20:28:33 +0000560 if (RE.getKind() == RetEffect::NoRetHard)
561 state = removeRefBinding(state, Sym);
562 }
George Karpenkovab0011e2018-08-23 00:26:59 +0000563
George Karpenkov70c2ee32018-08-17 21:41:07 +0000564 C.addTransition(state);
565}
566
567static ProgramStateRef updateOutParameter(ProgramStateRef State,
568 SVal ArgVal,
569 ArgEffect Effect) {
570 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
571 if (!ArgRegion)
572 return State;
573
574 QualType PointeeTy = ArgRegion->getValueType();
575 if (!coreFoundation::isCFObjectRef(PointeeTy))
576 return State;
577
578 SVal PointeeVal = State->getSVal(ArgRegion);
579 SymbolRef Pointee = PointeeVal.getAsLocSymbol();
580 if (!Pointee)
581 return State;
582
583 switch (Effect) {
584 case UnretainedOutParameter:
585 State = setRefBinding(State, Pointee,
George Karpenkov7e3016d2019-01-10 18:13:46 +0000586 RefVal::makeNotOwned(ObjKind::CF, PointeeTy));
George Karpenkov70c2ee32018-08-17 21:41:07 +0000587 break;
588 case RetainedOutParameter:
589 // Do nothing. Retained out parameters will either point to a +1 reference
590 // or NULL, but the way you check for failure differs depending on the API.
591 // Consequently, we don't have a good way to track them yet.
592 break;
593
594 default:
595 llvm_unreachable("only for out parameters");
596 }
597
598 return State;
599}
600
601void RetainCountChecker::checkSummary(const RetainSummary &Summ,
602 const CallEvent &CallOrMsg,
603 CheckerContext &C) const {
604 ProgramStateRef state = C.getState();
605
606 // Evaluate the effect of the arguments.
607 RefVal::Kind hasErr = (RefVal::Kind) 0;
608 SourceRange ErrorRange;
609 SymbolRef ErrorSym = nullptr;
610
611 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
612 SVal V = CallOrMsg.getArgSVal(idx);
613
614 ArgEffect Effect = Summ.getArg(idx);
615 if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
616 state = updateOutParameter(state, V, Effect);
617 } else if (SymbolRef Sym = V.getAsLocSymbol()) {
618 if (const RefVal *T = getRefBinding(state, Sym)) {
George Karpenkov041c9fa2018-12-08 01:18:40 +0000619
620 if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
621 Effect = StopTrackingHard;
622
George Karpenkov70c2ee32018-08-17 21:41:07 +0000623 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
624 if (hasErr) {
625 ErrorRange = CallOrMsg.getArgSourceRange(idx);
626 ErrorSym = Sym;
627 break;
628 }
629 }
630 }
631 }
632
George Karpenkovab0011e2018-08-23 00:26:59 +0000633 // Evaluate the effect on the message receiver / `this` argument.
George Karpenkov70c2ee32018-08-17 21:41:07 +0000634 bool ReceiverIsTracked = false;
635 if (!hasErr) {
George Karpenkovab0011e2018-08-23 00:26:59 +0000636 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000637 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
638 if (const RefVal *T = getRefBinding(state, Sym)) {
639 ReceiverIsTracked = true;
640 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
641 hasErr, C);
642 if (hasErr) {
643 ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
644 ErrorSym = Sym;
645 }
646 }
647 }
George Karpenkovab0011e2018-08-23 00:26:59 +0000648 } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
649 if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
650 if (const RefVal *T = getRefBinding(state, Sym)) {
651 state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
652 hasErr, C);
653 if (hasErr) {
654 ErrorRange = MCall->getOriginExpr()->getSourceRange();
655 ErrorSym = Sym;
656 }
657 }
658 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000659 }
660 }
661
662 // Process any errors.
663 if (hasErr) {
664 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
665 return;
666 }
667
668 // Consult the summary for the return value.
669 RetEffect RE = Summ.getRetEffect();
670
671 if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
672 if (ReceiverIsTracked)
673 RE = getSummaryManager(C).getObjAllocRetEffect();
674 else
675 RE = RetEffect::MakeNoRet();
676 }
677
George Karpenkov80c9e782018-08-22 01:16:49 +0000678 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
679 QualType ResultTy = CallOrMsg.getResultType();
680 if (RE.notOwned()) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000681 const Expr *Ex = CallOrMsg.getOriginExpr();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000682 assert(Ex);
George Karpenkov80c9e782018-08-22 01:16:49 +0000683 ResultTy = GetReturnType(Ex, C.getASTContext());
George Karpenkov70c2ee32018-08-17 21:41:07 +0000684 }
George Karpenkov80c9e782018-08-22 01:16:49 +0000685 if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
686 state = setRefBinding(state, Sym, *updatedRefVal);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000687 }
688
689 // This check is actually necessary; otherwise the statement builder thinks
690 // we've hit a previously-found path.
691 // Normally addTransition takes care of this, but we want the node pointer.
692 ExplodedNode *NewNode;
693 if (state == C.getState()) {
694 NewNode = C.getPredecessor();
695 } else {
696 NewNode = C.addTransition(state);
697 }
698
699 // Annotate the node with summary we used.
700 if (NewNode) {
701 // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
702 if (ShouldResetSummaryLog) {
703 SummaryLog.clear();
704 ShouldResetSummaryLog = false;
705 }
706 SummaryLog[NewNode] = &Summ;
707 }
708}
709
710ProgramStateRef
711RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
712 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
713 CheckerContext &C) const {
714 bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
715 switch (E) {
716 default:
717 break;
718 case IncRefMsg:
719 E = IgnoreRetainMsg ? DoNothing : IncRef;
720 break;
721 case DecRefMsg:
722 E = IgnoreRetainMsg ? DoNothing: DecRef;
723 break;
724 case DecRefMsgAndStopTrackingHard:
725 E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
726 break;
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000727 case MakeCollectable:
728 E = DoNothing;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000729 }
730
731 // Handle all use-after-releases.
732 if (V.getKind() == RefVal::Released) {
733 V = V ^ RefVal::ErrorUseAfterRelease;
734 hasErr = V.getKind();
735 return setRefBinding(state, sym, V);
736 }
737
738 switch (E) {
739 case DecRefMsg:
740 case IncRefMsg:
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000741 case MakeCollectable:
George Karpenkov70c2ee32018-08-17 21:41:07 +0000742 case DecRefMsgAndStopTrackingHard:
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000743 llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
George Karpenkov70c2ee32018-08-17 21:41:07 +0000744
745 case UnretainedOutParameter:
746 case RetainedOutParameter:
747 llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
748 "not have ref state.");
749
750 case Dealloc:
751 switch (V.getKind()) {
752 default:
753 llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
754 case RefVal::Owned:
755 // The object immediately transitions to the released state.
756 V = V ^ RefVal::Released;
757 V.clearCounts();
758 return setRefBinding(state, sym, V);
759 case RefVal::NotOwned:
760 V = V ^ RefVal::ErrorDeallocNotOwned;
761 hasErr = V.getKind();
762 break;
763 }
764 break;
765
766 case MayEscape:
767 if (V.getKind() == RefVal::Owned) {
768 V = V ^ RefVal::NotOwned;
769 break;
770 }
771
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000772 LLVM_FALLTHROUGH;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000773
774 case DoNothing:
775 return state;
776
777 case Autorelease:
778 // Update the autorelease counts.
779 V = V.autorelease();
780 break;
781
782 case StopTracking:
783 case StopTrackingHard:
784 return removeRefBinding(state, sym);
785
786 case IncRef:
787 switch (V.getKind()) {
788 default:
789 llvm_unreachable("Invalid RefVal state for a retain.");
790 case RefVal::Owned:
791 case RefVal::NotOwned:
792 V = V + 1;
793 break;
794 }
795 break;
796
797 case DecRef:
798 case DecRefBridgedTransferred:
799 case DecRefAndStopTrackingHard:
800 switch (V.getKind()) {
801 default:
802 // case 'RefVal::Released' handled above.
803 llvm_unreachable("Invalid RefVal state for a release.");
804
805 case RefVal::Owned:
806 assert(V.getCount() > 0);
807 if (V.getCount() == 1) {
808 if (E == DecRefBridgedTransferred ||
809 V.getIvarAccessHistory() ==
810 RefVal::IvarAccessHistory::AccessedDirectly)
811 V = V ^ RefVal::NotOwned;
812 else
813 V = V ^ RefVal::Released;
814 } else if (E == DecRefAndStopTrackingHard) {
815 return removeRefBinding(state, sym);
816 }
817
818 V = V - 1;
819 break;
820
821 case RefVal::NotOwned:
822 if (V.getCount() > 0) {
823 if (E == DecRefAndStopTrackingHard)
824 return removeRefBinding(state, sym);
825 V = V - 1;
826 } else if (V.getIvarAccessHistory() ==
827 RefVal::IvarAccessHistory::AccessedDirectly) {
828 // Assume that the instance variable was holding on the object at
829 // +1, and we just didn't know.
830 if (E == DecRefAndStopTrackingHard)
831 return removeRefBinding(state, sym);
832 V = V.releaseViaIvar() ^ RefVal::Released;
833 } else {
834 V = V ^ RefVal::ErrorReleaseNotOwned;
835 hasErr = V.getKind();
836 }
837 break;
838 }
839 break;
840 }
841 return setRefBinding(state, sym, V);
842}
843
844void RetainCountChecker::processNonLeakError(ProgramStateRef St,
845 SourceRange ErrorRange,
846 RefVal::Kind ErrorKind,
847 SymbolRef Sym,
848 CheckerContext &C) const {
849 // HACK: Ignore retain-count issues on values accessed through ivars,
850 // because of cases like this:
851 // [_contentView retain];
852 // [_contentView removeFromSuperview];
853 // [self addSubview:_contentView]; // invalidates 'self'
854 // [_contentView release];
855 if (const RefVal *RV = getRefBinding(St, Sym))
856 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
857 return;
858
859 ExplodedNode *N = C.generateErrorNode(St);
860 if (!N)
861 return;
862
863 CFRefBug *BT;
864 switch (ErrorKind) {
865 default:
866 llvm_unreachable("Unhandled error.");
867 case RefVal::ErrorUseAfterRelease:
868 if (!useAfterRelease)
869 useAfterRelease.reset(new UseAfterRelease(this));
870 BT = useAfterRelease.get();
871 break;
872 case RefVal::ErrorReleaseNotOwned:
873 if (!releaseNotOwned)
874 releaseNotOwned.reset(new BadRelease(this));
875 BT = releaseNotOwned.get();
876 break;
877 case RefVal::ErrorDeallocNotOwned:
878 if (!deallocNotOwned)
879 deallocNotOwned.reset(new DeallocNotOwned(this));
880 BT = deallocNotOwned.get();
881 break;
882 }
883
884 assert(BT);
George Karpenkov6babf2a2018-09-21 20:36:21 +0000885 auto report = llvm::make_unique<CFRefReport>(
886 *BT, C.getASTContext().getLangOpts(), SummaryLog, N, Sym);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000887 report->addRange(ErrorRange);
888 C.emitReport(std::move(report));
889}
890
891//===----------------------------------------------------------------------===//
892// Handle the return values of retain-count-related functions.
893//===----------------------------------------------------------------------===//
894
895bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
896 // Get the callee. We're only interested in simple C functions.
897 ProgramStateRef state = C.getState();
898 const FunctionDecl *FD = C.getCalleeDecl(CE);
899 if (!FD)
900 return false;
901
George Karpenkovc4d6b932018-08-17 21:42:05 +0000902 RetainSummaryManager &SmrMgr = getSummaryManager(C);
903 QualType ResultTy = CE->getCallReturnType(C.getASTContext());
George Karpenkov70c2ee32018-08-17 21:41:07 +0000904
George Karpenkov70c2ee32018-08-17 21:41:07 +0000905 // See if the function has 'rc_ownership_trusted_implementation'
906 // annotate attribute. If it does, we will not inline it.
907 bool hasTrustedImplementationAnnotation = false;
908
George Karpenkov41dc8de2018-10-11 22:59:16 +0000909 const LocationContext *LCtx = C.getLocationContext();
910
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000911 using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
912 Optional<BehaviorSummary> BSmr =
913 SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
914
George Karpenkovc4d6b932018-08-17 21:42:05 +0000915 // See if it's one of the specific functions we know how to eval.
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000916 if (!BSmr)
George Karpenkov70c2ee32018-08-17 21:41:07 +0000917 return false;
918
919 // Bind the return value.
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000920 if (BSmr == BehaviorSummary::Identity ||
921 BSmr == BehaviorSummary::IdentityOrZero) {
George Karpenkov48de5822018-10-23 23:11:30 +0000922 SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
923
George Karpenkov70c2ee32018-08-17 21:41:07 +0000924 // If the receiver is unknown or the function has
925 // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
926 // return value.
George Karpenkov48de5822018-10-23 23:11:30 +0000927 if (RetVal.isUnknown() ||
928 (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
929 SValBuilder &SVB = C.getSValBuilder();
930 RetVal =
931 SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
932 }
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000933 state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
934
935 if (BSmr == BehaviorSummary::IdentityOrZero) {
936 // Add a branch where the output is zero.
937 ProgramStateRef NullOutputState = C.getState();
938
939 // Assume that output is zero on the other branch.
940 NullOutputState = NullOutputState->BindExpr(
941 CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
942
943 C.addTransition(NullOutputState);
944
945 // And on the original branch assume that both input and
946 // output are non-zero.
947 if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
948 state = state->assume(*L, /*Assumption=*/true);
949
950 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000951 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000952
George Karpenkov70c2ee32018-08-17 21:41:07 +0000953 C.addTransition(state);
954 return true;
955}
956
George Karpenkov04553e52018-09-21 20:37:20 +0000957ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
958 CheckerContext &C) const {
959 ExplodedNode *Pred = C.getPredecessor();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000960
961 // Only adjust the reference count if this is the top-level call frame,
962 // and not the result of inlining. In the future, we should do
963 // better checking even for inlined calls, and see if they match
964 // with their expected semantics (e.g., the method should return a retained
965 // object, etc.).
966 if (!C.inTopFrame())
George Karpenkov04553e52018-09-21 20:37:20 +0000967 return Pred;
968
969 if (!S)
970 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000971
972 const Expr *RetE = S->getRetValue();
973 if (!RetE)
George Karpenkov04553e52018-09-21 20:37:20 +0000974 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000975
976 ProgramStateRef state = C.getState();
977 SymbolRef Sym =
978 state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
979 if (!Sym)
George Karpenkov04553e52018-09-21 20:37:20 +0000980 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000981
982 // Get the reference count binding (if any).
983 const RefVal *T = getRefBinding(state, Sym);
984 if (!T)
George Karpenkov04553e52018-09-21 20:37:20 +0000985 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000986
987 // Change the reference count.
988 RefVal X = *T;
989
990 switch (X.getKind()) {
991 case RefVal::Owned: {
992 unsigned cnt = X.getCount();
993 assert(cnt > 0);
994 X.setCount(cnt - 1);
995 X = X ^ RefVal::ReturnedOwned;
996 break;
997 }
998
999 case RefVal::NotOwned: {
1000 unsigned cnt = X.getCount();
1001 if (cnt) {
1002 X.setCount(cnt - 1);
1003 X = X ^ RefVal::ReturnedOwned;
George Karpenkov04553e52018-09-21 20:37:20 +00001004 } else {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001005 X = X ^ RefVal::ReturnedNotOwned;
1006 }
1007 break;
1008 }
1009
1010 default:
George Karpenkov04553e52018-09-21 20:37:20 +00001011 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001012 }
1013
1014 // Update the binding.
1015 state = setRefBinding(state, Sym, X);
George Karpenkov04553e52018-09-21 20:37:20 +00001016 Pred = C.addTransition(state);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001017
1018 // At this point we have updated the state properly.
1019 // Everything after this is merely checking to see if the return value has
1020 // been over- or under-retained.
1021
1022 // Did we cache out?
1023 if (!Pred)
George Karpenkov04553e52018-09-21 20:37:20 +00001024 return nullptr;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001025
1026 // Update the autorelease counts.
1027 static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
George Karpenkov04553e52018-09-21 20:37:20 +00001028 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001029
George Karpenkov04553e52018-09-21 20:37:20 +00001030 // Have we generated a sink node?
George Karpenkov70c2ee32018-08-17 21:41:07 +00001031 if (!state)
George Karpenkov04553e52018-09-21 20:37:20 +00001032 return nullptr;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001033
1034 // Get the updated binding.
1035 T = getRefBinding(state, Sym);
1036 assert(T);
1037 X = *T;
1038
1039 // Consult the summary of the enclosing method.
1040 RetainSummaryManager &Summaries = getSummaryManager(C);
1041 const Decl *CD = &Pred->getCodeDecl();
1042 RetEffect RE = RetEffect::MakeNoRet();
1043
1044 // FIXME: What is the convention for blocks? Is there one?
1045 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
1046 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
1047 RE = Summ->getRetEffect();
1048 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
1049 if (!isa<CXXMethodDecl>(FD)) {
1050 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
1051 RE = Summ->getRetEffect();
1052 }
1053 }
1054
George Karpenkov04553e52018-09-21 20:37:20 +00001055 return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001056}
1057
George Karpenkov04553e52018-09-21 20:37:20 +00001058ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
George Karpenkov70c2ee32018-08-17 21:41:07 +00001059 CheckerContext &C,
1060 ExplodedNode *Pred,
1061 RetEffect RE, RefVal X,
1062 SymbolRef Sym,
1063 ProgramStateRef state) const {
1064 // HACK: Ignore retain-count issues on values accessed through ivars,
1065 // because of cases like this:
1066 // [_contentView retain];
1067 // [_contentView removeFromSuperview];
1068 // [self addSubview:_contentView]; // invalidates 'self'
1069 // [_contentView release];
1070 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
George Karpenkov04553e52018-09-21 20:37:20 +00001071 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001072
1073 // Any leaks or other errors?
1074 if (X.isReturnedOwned() && X.getCount() == 0) {
1075 if (RE.getKind() != RetEffect::NoRet) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001076 if (!RE.isOwned()) {
George Karpenkov04553e52018-09-21 20:37:20 +00001077
George Karpenkov70c2ee32018-08-17 21:41:07 +00001078 // The returning type is a CF, we expect the enclosing method should
1079 // return ownership.
George Karpenkov70c2ee32018-08-17 21:41:07 +00001080 X = X ^ RefVal::ErrorLeakReturned;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001081
George Karpenkov70c2ee32018-08-17 21:41:07 +00001082 // Generate an error node.
1083 state = setRefBinding(state, Sym, X);
1084
1085 static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
1086 ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
1087 if (N) {
1088 const LangOptions &LOpts = C.getASTContext().getLangOpts();
George Karpenkov04553e52018-09-21 20:37:20 +00001089 auto R = llvm::make_unique<CFRefLeakReport>(
George Karpenkov936a9c92018-12-07 20:21:37 +00001090 *getLeakAtReturnBug(LOpts), LOpts, SummaryLog, N, Sym, C);
George Karpenkov04553e52018-09-21 20:37:20 +00001091 C.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001092 }
George Karpenkov04553e52018-09-21 20:37:20 +00001093 return N;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001094 }
1095 }
1096 } else if (X.isReturnedNotOwned()) {
1097 if (RE.isOwned()) {
1098 if (X.getIvarAccessHistory() ==
1099 RefVal::IvarAccessHistory::AccessedDirectly) {
1100 // Assume the method was trying to transfer a +1 reference from a
1101 // strong ivar to the caller.
1102 state = setRefBinding(state, Sym,
1103 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
1104 } else {
1105 // Trying to return a not owned object to a caller expecting an
1106 // owned object.
1107 state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
1108
1109 static CheckerProgramPointTag
1110 ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
1111
1112 ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
1113 if (N) {
1114 if (!returnNotOwnedForOwned)
1115 returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
1116
George Karpenkov04553e52018-09-21 20:37:20 +00001117 auto R = llvm::make_unique<CFRefReport>(
George Karpenkov70c2ee32018-08-17 21:41:07 +00001118 *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
George Karpenkov04553e52018-09-21 20:37:20 +00001119 SummaryLog, N, Sym);
1120 C.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001121 }
George Karpenkov04553e52018-09-21 20:37:20 +00001122 return N;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001123 }
1124 }
1125 }
George Karpenkov04553e52018-09-21 20:37:20 +00001126 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001127}
1128
1129//===----------------------------------------------------------------------===//
1130// Check various ways a symbol can be invalidated.
1131//===----------------------------------------------------------------------===//
1132
1133void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
1134 CheckerContext &C) const {
1135 // Are we storing to something that causes the value to "escape"?
1136 bool escapes = true;
1137
1138 // A value escapes in three possible cases (this may change):
1139 //
1140 // (1) we are binding to something that is not a memory region.
1141 // (2) we are binding to a memregion that does not have stack storage
1142 // (3) we are binding to a memregion with stack storage that the store
1143 // does not understand.
1144 ProgramStateRef state = C.getState();
1145
George Karpenkov6e9fd132018-08-22 01:17:09 +00001146 if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001147 escapes = !regionLoc->getRegion()->hasStackStorage();
1148
1149 if (!escapes) {
1150 // To test (3), generate a new state with the binding added. If it is
1151 // the same state, then it escapes (since the store cannot represent
1152 // the binding).
1153 // Do this only if we know that the store is not supposed to generate the
1154 // same state.
1155 SVal StoredVal = state->getSVal(regionLoc->getRegion());
1156 if (StoredVal != val)
1157 escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
1158 }
1159 if (!escapes) {
1160 // Case 4: We do not currently model what happens when a symbol is
1161 // assigned to a struct field, so be conservative here and let the symbol
1162 // go. TODO: This could definitely be improved upon.
1163 escapes = !isa<VarRegion>(regionLoc->getRegion());
1164 }
1165 }
1166
1167 // If we are storing the value into an auto function scope variable annotated
1168 // with (__attribute__((cleanup))), stop tracking the value to avoid leak
1169 // false positives.
George Karpenkov6e9fd132018-08-22 01:17:09 +00001170 if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001171 const VarDecl *VD = LVR->getDecl();
1172 if (VD->hasAttr<CleanupAttr>()) {
1173 escapes = true;
1174 }
1175 }
1176
1177 // If our store can represent the binding and we aren't storing to something
1178 // that doesn't have local storage then just return and have the simulation
1179 // state continue as is.
1180 if (!escapes)
1181 return;
1182
1183 // Otherwise, find all symbols referenced by 'val' that we are tracking
1184 // and stop tracking them.
1185 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1186 C.addTransition(state);
1187}
1188
1189ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
George Karpenkov6e9fd132018-08-22 01:17:09 +00001190 SVal Cond,
1191 bool Assumption) const {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001192 // FIXME: We may add to the interface of evalAssume the list of symbols
1193 // whose assumptions have changed. For now we just iterate through the
1194 // bindings and check if any of the tracked symbols are NULL. This isn't
1195 // too bad since the number of symbols we will track in practice are
1196 // probably small and evalAssume is only called at branches and a few
1197 // other places.
1198 RefBindingsTy B = state->get<RefBindings>();
1199
1200 if (B.isEmpty())
1201 return state;
1202
1203 bool changed = false;
1204 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1205
1206 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1207 // Check if the symbol is null stop tracking the symbol.
1208 ConstraintManager &CMgr = state->getConstraintManager();
1209 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1210 if (AllocFailed.isConstrainedTrue()) {
1211 changed = true;
1212 B = RefBFactory.remove(B, I.getKey());
1213 }
1214 }
1215
1216 if (changed)
1217 state = state->set<RefBindings>(B);
1218
1219 return state;
1220}
1221
1222ProgramStateRef
1223RetainCountChecker::checkRegionChanges(ProgramStateRef state,
1224 const InvalidatedSymbols *invalidated,
1225 ArrayRef<const MemRegion *> ExplicitRegions,
1226 ArrayRef<const MemRegion *> Regions,
1227 const LocationContext *LCtx,
1228 const CallEvent *Call) const {
1229 if (!invalidated)
1230 return state;
1231
1232 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1233 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
1234 E = ExplicitRegions.end(); I != E; ++I) {
1235 if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
1236 WhitelistedSymbols.insert(SR->getSymbol());
1237 }
1238
George Karpenkov6fd5c86d2018-10-31 17:38:29 +00001239 for (SymbolRef sym :
1240 llvm::make_range(invalidated->begin(), invalidated->end())) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001241 if (WhitelistedSymbols.count(sym))
1242 continue;
1243 // Remove any existing reference-count binding.
1244 state = removeRefBinding(state, sym);
1245 }
1246 return state;
1247}
1248
George Karpenkov70c2ee32018-08-17 21:41:07 +00001249ProgramStateRef
1250RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1251 ExplodedNode *Pred,
1252 const ProgramPointTag *Tag,
1253 CheckerContext &Ctx,
George Karpenkov04553e52018-09-21 20:37:20 +00001254 SymbolRef Sym,
1255 RefVal V,
1256 const ReturnStmt *S) const {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001257 unsigned ACnt = V.getAutoreleaseCount();
1258
1259 // No autorelease counts? Nothing to be done.
1260 if (!ACnt)
1261 return state;
1262
1263 unsigned Cnt = V.getCount();
1264
1265 // FIXME: Handle sending 'autorelease' to already released object.
1266
1267 if (V.getKind() == RefVal::ReturnedOwned)
1268 ++Cnt;
1269
1270 // If we would over-release here, but we know the value came from an ivar,
1271 // assume it was a strong ivar that's just been relinquished.
1272 if (ACnt > Cnt &&
1273 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1274 V = V.releaseViaIvar();
1275 --ACnt;
1276 }
1277
1278 if (ACnt <= Cnt) {
1279 if (ACnt == Cnt) {
1280 V.clearCounts();
George Karpenkov04553e52018-09-21 20:37:20 +00001281 if (V.getKind() == RefVal::ReturnedOwned) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001282 V = V ^ RefVal::ReturnedNotOwned;
George Karpenkov04553e52018-09-21 20:37:20 +00001283 } else {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001284 V = V ^ RefVal::NotOwned;
George Karpenkov04553e52018-09-21 20:37:20 +00001285 }
George Karpenkov70c2ee32018-08-17 21:41:07 +00001286 } else {
1287 V.setCount(V.getCount() - ACnt);
1288 V.setAutoreleaseCount(0);
1289 }
1290 return setRefBinding(state, Sym, V);
1291 }
1292
1293 // HACK: Ignore retain-count issues on values accessed through ivars,
1294 // because of cases like this:
1295 // [_contentView retain];
1296 // [_contentView removeFromSuperview];
1297 // [self addSubview:_contentView]; // invalidates 'self'
1298 // [_contentView release];
1299 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1300 return state;
1301
1302 // Woah! More autorelease counts then retain counts left.
1303 // Emit hard error.
1304 V = V ^ RefVal::ErrorOverAutorelease;
1305 state = setRefBinding(state, Sym, V);
1306
1307 ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1308 if (N) {
1309 SmallString<128> sbuf;
1310 llvm::raw_svector_ostream os(sbuf);
1311 os << "Object was autoreleased ";
1312 if (V.getAutoreleaseCount() > 1)
1313 os << V.getAutoreleaseCount() << " times but the object ";
1314 else
1315 os << "but ";
1316 os << "has a +" << V.getCount() << " retain count";
1317
1318 if (!overAutorelease)
1319 overAutorelease.reset(new OverAutorelease(this));
1320
1321 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
George Karpenkov04553e52018-09-21 20:37:20 +00001322 auto R = llvm::make_unique<CFRefReport>(*overAutorelease, LOpts, SummaryLog,
1323 N, Sym, os.str());
1324 Ctx.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001325 }
1326
1327 return nullptr;
1328}
1329
1330ProgramStateRef
1331RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1332 SymbolRef sid, RefVal V,
1333 SmallVectorImpl<SymbolRef> &Leaked) const {
1334 bool hasLeak;
1335
1336 // HACK: Ignore retain-count issues on values accessed through ivars,
1337 // because of cases like this:
1338 // [_contentView retain];
1339 // [_contentView removeFromSuperview];
1340 // [self addSubview:_contentView]; // invalidates 'self'
1341 // [_contentView release];
1342 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1343 hasLeak = false;
1344 else if (V.isOwned())
1345 hasLeak = true;
1346 else if (V.isNotOwned() || V.isReturnedOwned())
1347 hasLeak = (V.getCount() > 0);
1348 else
1349 hasLeak = false;
1350
1351 if (!hasLeak)
1352 return removeRefBinding(state, sid);
1353
1354 Leaked.push_back(sid);
1355 return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1356}
1357
1358ExplodedNode *
1359RetainCountChecker::processLeaks(ProgramStateRef state,
1360 SmallVectorImpl<SymbolRef> &Leaked,
1361 CheckerContext &Ctx,
1362 ExplodedNode *Pred) const {
1363 // Generate an intermediate node representing the leak point.
1364 ExplodedNode *N = Ctx.addTransition(state, Pred);
1365
1366 if (N) {
1367 for (SmallVectorImpl<SymbolRef>::iterator
1368 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
1369
1370 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1371 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts)
1372 : getLeakAtReturnBug(LOpts);
1373 assert(BT && "BugType not initialized.");
1374
George Karpenkov6babf2a2018-09-21 20:36:21 +00001375 Ctx.emitReport(llvm::make_unique<CFRefLeakReport>(
George Karpenkov936a9c92018-12-07 20:21:37 +00001376 *BT, LOpts, SummaryLog, N, *I, Ctx));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001377 }
1378 }
1379
1380 return N;
1381}
1382
George Karpenkovb1b791b2018-08-17 21:43:27 +00001383static bool isISLObjectRef(QualType Ty) {
1384 return StringRef(Ty.getAsString()).startswith("isl_");
George Karpenkov70c2ee32018-08-17 21:41:07 +00001385}
1386
1387void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1388 if (!Ctx.inTopFrame())
1389 return;
1390
George Karpenkovc4d6b932018-08-17 21:42:05 +00001391 RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001392 const LocationContext *LCtx = Ctx.getLocationContext();
1393 const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1394
George Karpenkovc4d6b932018-08-17 21:42:05 +00001395 if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
George Karpenkov70c2ee32018-08-17 21:41:07 +00001396 return;
1397
1398 ProgramStateRef state = Ctx.getState();
George Karpenkovc4d6b932018-08-17 21:42:05 +00001399 const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001400 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1401
1402 for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1403 const ParmVarDecl *Param = FD->getParamDecl(idx);
1404 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1405
1406 QualType Ty = Param->getType();
1407 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
George Karpenkovb1b791b2018-08-17 21:43:27 +00001408 if (AE && *AE == DecRef && isISLObjectRef(Ty)) {
George Karpenkov6e9fd132018-08-22 01:17:09 +00001409 state = setRefBinding(
George Karpenkov7e3016d2019-01-10 18:13:46 +00001410 state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty));
George Karpenkovb1b791b2018-08-17 21:43:27 +00001411 } else if (isISLObjectRef(Ty)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001412 state = setRefBinding(
1413 state, Sym,
George Karpenkov7e3016d2019-01-10 18:13:46 +00001414 RefVal::makeNotOwned(ObjKind::Generalized, Ty));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001415 }
1416 }
1417
1418 Ctx.addTransition(state);
1419}
1420
1421void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1422 CheckerContext &Ctx) const {
George Karpenkov04553e52018-09-21 20:37:20 +00001423 ExplodedNode *Pred = processReturn(RS, Ctx);
1424
1425 // Created state cached out.
1426 if (!Pred) {
1427 return;
1428 }
1429
1430 ProgramStateRef state = Pred->getState();
George Karpenkov70c2ee32018-08-17 21:41:07 +00001431 RefBindingsTy B = state->get<RefBindings>();
George Karpenkov70c2ee32018-08-17 21:41:07 +00001432
1433 // Don't process anything within synthesized bodies.
1434 const LocationContext *LCtx = Pred->getLocationContext();
1435 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1436 assert(!LCtx->inTopFrame());
1437 return;
1438 }
1439
1440 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1441 state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1442 I->first, I->second);
1443 if (!state)
1444 return;
1445 }
1446
1447 // If the current LocationContext has a parent, don't check for leaks.
1448 // We will do that later.
1449 // FIXME: we should instead check for imbalances of the retain/releases,
1450 // and suggest annotations.
1451 if (LCtx->getParent())
1452 return;
1453
1454 B = state->get<RefBindings>();
1455 SmallVector<SymbolRef, 10> Leaked;
1456
1457 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
1458 state = handleSymbolDeath(state, I->first, I->second, Leaked);
1459
1460 processLeaks(state, Leaked, Ctx, Pred);
1461}
1462
George Karpenkov70c2ee32018-08-17 21:41:07 +00001463void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1464 CheckerContext &C) const {
1465 ExplodedNode *Pred = C.getPredecessor();
1466
1467 ProgramStateRef state = C.getState();
1468 RefBindingsTy B = state->get<RefBindings>();
1469 SmallVector<SymbolRef, 10> Leaked;
1470
1471 // Update counts from autorelease pools
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001472 for (const auto &I: state->get<RefBindings>()) {
1473 SymbolRef Sym = I.first;
1474 if (SymReaper.isDead(Sym)) {
Artem Dergachev65b4d7d2018-10-15 17:47:56 +00001475 static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001476 const RefVal &V = I.second;
1477 state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001478 if (!state)
1479 return;
1480
1481 // Fetch the new reference count from the state, and use it to handle
1482 // this symbol.
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001483 state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001484 }
1485 }
1486
1487 if (Leaked.empty()) {
1488 C.addTransition(state);
1489 return;
1490 }
1491
1492 Pred = processLeaks(state, Leaked, C, Pred);
1493
1494 // Did we cache out?
1495 if (!Pred)
1496 return;
1497
1498 // Now generate a new node that nukes the old bindings.
1499 // The only bindings left at this point are the leaked symbols.
1500 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1501 B = state->get<RefBindings>();
1502
1503 for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
1504 E = Leaked.end();
1505 I != E; ++I)
1506 B = F.remove(B, *I);
1507
1508 state = state->set<RefBindings>(B);
1509 C.addTransition(state, Pred);
1510}
1511
1512void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1513 const char *NL, const char *Sep) const {
1514
1515 RefBindingsTy B = State->get<RefBindings>();
1516
1517 if (B.isEmpty())
1518 return;
1519
1520 Out << Sep << NL;
1521
1522 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1523 Out << I->first << " : ";
1524 I->second.print(Out);
1525 Out << NL;
1526 }
1527}
1528
1529//===----------------------------------------------------------------------===//
George Karpenkov70c2ee32018-08-17 21:41:07 +00001530// Checker registration.
1531//===----------------------------------------------------------------------===//
1532
1533void ento::registerRetainCountChecker(CheckerManager &Mgr) {
Kristof Umannc83b0dd2018-11-02 15:48:10 +00001534 auto *Chk = Mgr.registerChecker<RetainCountChecker>();
George Karpenkov27db3302018-12-07 20:21:51 +00001535 Chk->TrackObjCAndCFObjects = true;
1536}
Kristof Umannc83b0dd2018-11-02 15:48:10 +00001537
George Karpenkovd1081ec2018-12-11 01:13:58 +00001538// FIXME: remove this, hack for backwards compatibility:
1539// it should be possible to enable the NS/CF retain count checker as
1540// osx.cocoa.RetainCount, and it should be possible to disable
1541// osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false.
1542static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options) {
1543 auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject");
1544 if (I != Options.Config.end())
1545 return I->getValue() == "false";
1546 return false;
1547}
1548
George Karpenkov27db3302018-12-07 20:21:51 +00001549void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1550 auto *Chk = Mgr.registerChecker<RetainCountChecker>();
George Karpenkovd1081ec2018-12-11 01:13:58 +00001551 if (!hasPrevCheckOSObjectOptionDisabled(Mgr.getAnalyzerOptions()))
1552 Chk->TrackOSObjects = true;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001553}