blob: 488cf6d3eb883f73d1f5d88eb83295f5d609535d [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.
302 // RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
303 if (SymbolRef sym =
304 state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
305 QualType ResultTy = Ex->getType();
306 state = setRefBinding(state, sym,
307 RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
308 }
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,
333 RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
334 }
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();
354 RetEffect::ObjKind Kind;
355 if (Ty->isObjCRetainableType())
356 Kind = RetEffect::ObjC;
357 else if (coreFoundation::isCFObjectRef(Ty))
358 Kind = RetEffect::CF;
359 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 Karpenkov70c2ee32018-08-17 21:41:07 +0000505// We don't always get the exact modeling of the function with regards to the
506// retain count checker even when the function is inlined. For example, we need
507// to stop tracking the symbols which were marked with StopTrackingHard.
508void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
509 const CallEvent &CallOrMsg,
510 CheckerContext &C) const {
511 ProgramStateRef state = C.getState();
512
513 // Evaluate the effect of the arguments.
514 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
Simon Pilgrim82fbb662018-12-21 10:11:23 +0000515 if (Summ.getArg(idx) == StopTrackingHard) {
516 SVal V = CallOrMsg.getArgSVal(idx);
517 if (SymbolRef Sym = V.getAsLocSymbol()) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000518 state = removeRefBinding(state, Sym);
Simon Pilgrim82fbb662018-12-21 10:11:23 +0000519 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000520 }
521 }
522
523 // Evaluate the effect on the message receiver.
George Karpenkov6e9fd132018-08-22 01:17:09 +0000524 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000525 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
526 if (Summ.getReceiverEffect() == StopTrackingHard) {
527 state = removeRefBinding(state, Sym);
528 }
529 }
530 }
531
532 // Consult the summary for the return value.
533 RetEffect RE = Summ.getRetEffect();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000534
George Karpenkovd5ef0d22018-08-29 20:28:33 +0000535 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
George Karpenkovd5ef0d22018-08-29 20:28:33 +0000536 if (RE.getKind() == RetEffect::NoRetHard)
537 state = removeRefBinding(state, Sym);
538 }
George Karpenkovab0011e2018-08-23 00:26:59 +0000539
George Karpenkov70c2ee32018-08-17 21:41:07 +0000540 C.addTransition(state);
541}
542
543static ProgramStateRef updateOutParameter(ProgramStateRef State,
544 SVal ArgVal,
545 ArgEffect Effect) {
546 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
547 if (!ArgRegion)
548 return State;
549
550 QualType PointeeTy = ArgRegion->getValueType();
551 if (!coreFoundation::isCFObjectRef(PointeeTy))
552 return State;
553
554 SVal PointeeVal = State->getSVal(ArgRegion);
555 SymbolRef Pointee = PointeeVal.getAsLocSymbol();
556 if (!Pointee)
557 return State;
558
559 switch (Effect) {
560 case UnretainedOutParameter:
561 State = setRefBinding(State, Pointee,
562 RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
563 break;
564 case RetainedOutParameter:
565 // Do nothing. Retained out parameters will either point to a +1 reference
566 // or NULL, but the way you check for failure differs depending on the API.
567 // Consequently, we don't have a good way to track them yet.
568 break;
569
570 default:
571 llvm_unreachable("only for out parameters");
572 }
573
574 return State;
575}
576
Simon Pilgrim82fbb662018-12-21 10:11:23 +0000577static bool isPointerToObject(QualType QT) {
578 QualType PT = QT->getPointeeType();
579 if (!PT.isNull())
580 if (PT->getAsCXXRecordDecl())
581 return true;
582 return false;
583}
584
585/// Whether the tracked value should be escaped on a given call.
586/// OSObjects are escaped when passed to void * / etc.
587static bool shouldEscapeArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
588 const RefVal *TrackedValue) {
589 if (TrackedValue->getObjKind() != RetEffect::OS)
590 return false;
591 if (ArgIdx >= CE.parameters().size())
592 return false;
593 return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
594}
595
George Karpenkov70c2ee32018-08-17 21:41:07 +0000596void RetainCountChecker::checkSummary(const RetainSummary &Summ,
597 const CallEvent &CallOrMsg,
598 CheckerContext &C) const {
599 ProgramStateRef state = C.getState();
600
601 // Evaluate the effect of the arguments.
602 RefVal::Kind hasErr = (RefVal::Kind) 0;
603 SourceRange ErrorRange;
604 SymbolRef ErrorSym = nullptr;
605
606 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
607 SVal V = CallOrMsg.getArgSVal(idx);
608
609 ArgEffect Effect = Summ.getArg(idx);
610 if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
611 state = updateOutParameter(state, V, Effect);
612 } else if (SymbolRef Sym = V.getAsLocSymbol()) {
613 if (const RefVal *T = getRefBinding(state, Sym)) {
George Karpenkov041c9fa2018-12-08 01:18:40 +0000614
615 if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
616 Effect = StopTrackingHard;
617
George Karpenkov70c2ee32018-08-17 21:41:07 +0000618 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
619 if (hasErr) {
620 ErrorRange = CallOrMsg.getArgSourceRange(idx);
621 ErrorSym = Sym;
622 break;
623 }
624 }
625 }
626 }
627
George Karpenkovab0011e2018-08-23 00:26:59 +0000628 // Evaluate the effect on the message receiver / `this` argument.
George Karpenkov70c2ee32018-08-17 21:41:07 +0000629 bool ReceiverIsTracked = false;
630 if (!hasErr) {
George Karpenkovab0011e2018-08-23 00:26:59 +0000631 if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000632 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
633 if (const RefVal *T = getRefBinding(state, Sym)) {
634 ReceiverIsTracked = true;
635 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
636 hasErr, C);
637 if (hasErr) {
638 ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
639 ErrorSym = Sym;
640 }
641 }
642 }
George Karpenkovab0011e2018-08-23 00:26:59 +0000643 } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
644 if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
645 if (const RefVal *T = getRefBinding(state, Sym)) {
646 state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
647 hasErr, C);
648 if (hasErr) {
649 ErrorRange = MCall->getOriginExpr()->getSourceRange();
650 ErrorSym = Sym;
651 }
652 }
653 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000654 }
655 }
656
657 // Process any errors.
658 if (hasErr) {
659 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
660 return;
661 }
662
663 // Consult the summary for the return value.
664 RetEffect RE = Summ.getRetEffect();
665
666 if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
667 if (ReceiverIsTracked)
668 RE = getSummaryManager(C).getObjAllocRetEffect();
669 else
670 RE = RetEffect::MakeNoRet();
671 }
672
George Karpenkov80c9e782018-08-22 01:16:49 +0000673 if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) {
674 QualType ResultTy = CallOrMsg.getResultType();
675 if (RE.notOwned()) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000676 const Expr *Ex = CallOrMsg.getOriginExpr();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000677 assert(Ex);
George Karpenkov80c9e782018-08-22 01:16:49 +0000678 ResultTy = GetReturnType(Ex, C.getASTContext());
George Karpenkov70c2ee32018-08-17 21:41:07 +0000679 }
George Karpenkov80c9e782018-08-22 01:16:49 +0000680 if (Optional<RefVal> updatedRefVal = refValFromRetEffect(RE, ResultTy))
681 state = setRefBinding(state, Sym, *updatedRefVal);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000682 }
683
684 // This check is actually necessary; otherwise the statement builder thinks
685 // we've hit a previously-found path.
686 // Normally addTransition takes care of this, but we want the node pointer.
687 ExplodedNode *NewNode;
688 if (state == C.getState()) {
689 NewNode = C.getPredecessor();
690 } else {
691 NewNode = C.addTransition(state);
692 }
693
694 // Annotate the node with summary we used.
695 if (NewNode) {
696 // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
697 if (ShouldResetSummaryLog) {
698 SummaryLog.clear();
699 ShouldResetSummaryLog = false;
700 }
701 SummaryLog[NewNode] = &Summ;
702 }
703}
704
705ProgramStateRef
706RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
707 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
708 CheckerContext &C) const {
709 bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
710 switch (E) {
711 default:
712 break;
713 case IncRefMsg:
714 E = IgnoreRetainMsg ? DoNothing : IncRef;
715 break;
716 case DecRefMsg:
717 E = IgnoreRetainMsg ? DoNothing: DecRef;
718 break;
719 case DecRefMsgAndStopTrackingHard:
720 E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
721 break;
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000722 case MakeCollectable:
723 E = DoNothing;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000724 }
725
726 // Handle all use-after-releases.
727 if (V.getKind() == RefVal::Released) {
728 V = V ^ RefVal::ErrorUseAfterRelease;
729 hasErr = V.getKind();
730 return setRefBinding(state, sym, V);
731 }
732
733 switch (E) {
734 case DecRefMsg:
735 case IncRefMsg:
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000736 case MakeCollectable:
George Karpenkov70c2ee32018-08-17 21:41:07 +0000737 case DecRefMsgAndStopTrackingHard:
George Karpenkovbc0cddf2018-08-17 21:42:59 +0000738 llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
George Karpenkov70c2ee32018-08-17 21:41:07 +0000739
740 case UnretainedOutParameter:
741 case RetainedOutParameter:
742 llvm_unreachable("Applies to pointer-to-pointer parameters, which should "
743 "not have ref state.");
744
745 case Dealloc:
746 switch (V.getKind()) {
747 default:
748 llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
749 case RefVal::Owned:
750 // The object immediately transitions to the released state.
751 V = V ^ RefVal::Released;
752 V.clearCounts();
753 return setRefBinding(state, sym, V);
754 case RefVal::NotOwned:
755 V = V ^ RefVal::ErrorDeallocNotOwned;
756 hasErr = V.getKind();
757 break;
758 }
759 break;
760
761 case MayEscape:
762 if (V.getKind() == RefVal::Owned) {
763 V = V ^ RefVal::NotOwned;
764 break;
765 }
766
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000767 LLVM_FALLTHROUGH;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000768
769 case DoNothing:
770 return state;
771
772 case Autorelease:
773 // Update the autorelease counts.
774 V = V.autorelease();
775 break;
776
777 case StopTracking:
778 case StopTrackingHard:
779 return removeRefBinding(state, sym);
780
781 case IncRef:
782 switch (V.getKind()) {
783 default:
784 llvm_unreachable("Invalid RefVal state for a retain.");
785 case RefVal::Owned:
786 case RefVal::NotOwned:
787 V = V + 1;
788 break;
789 }
790 break;
791
792 case DecRef:
793 case DecRefBridgedTransferred:
794 case DecRefAndStopTrackingHard:
795 switch (V.getKind()) {
796 default:
797 // case 'RefVal::Released' handled above.
798 llvm_unreachable("Invalid RefVal state for a release.");
799
800 case RefVal::Owned:
801 assert(V.getCount() > 0);
802 if (V.getCount() == 1) {
803 if (E == DecRefBridgedTransferred ||
804 V.getIvarAccessHistory() ==
805 RefVal::IvarAccessHistory::AccessedDirectly)
806 V = V ^ RefVal::NotOwned;
807 else
808 V = V ^ RefVal::Released;
809 } else if (E == DecRefAndStopTrackingHard) {
810 return removeRefBinding(state, sym);
811 }
812
813 V = V - 1;
814 break;
815
816 case RefVal::NotOwned:
817 if (V.getCount() > 0) {
818 if (E == DecRefAndStopTrackingHard)
819 return removeRefBinding(state, sym);
820 V = V - 1;
821 } else if (V.getIvarAccessHistory() ==
822 RefVal::IvarAccessHistory::AccessedDirectly) {
823 // Assume that the instance variable was holding on the object at
824 // +1, and we just didn't know.
825 if (E == DecRefAndStopTrackingHard)
826 return removeRefBinding(state, sym);
827 V = V.releaseViaIvar() ^ RefVal::Released;
828 } else {
829 V = V ^ RefVal::ErrorReleaseNotOwned;
830 hasErr = V.getKind();
831 }
832 break;
833 }
834 break;
835 }
836 return setRefBinding(state, sym, V);
837}
838
839void RetainCountChecker::processNonLeakError(ProgramStateRef St,
840 SourceRange ErrorRange,
841 RefVal::Kind ErrorKind,
842 SymbolRef Sym,
843 CheckerContext &C) const {
844 // HACK: Ignore retain-count issues on values accessed through ivars,
845 // because of cases like this:
846 // [_contentView retain];
847 // [_contentView removeFromSuperview];
848 // [self addSubview:_contentView]; // invalidates 'self'
849 // [_contentView release];
850 if (const RefVal *RV = getRefBinding(St, Sym))
851 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
852 return;
853
854 ExplodedNode *N = C.generateErrorNode(St);
855 if (!N)
856 return;
857
858 CFRefBug *BT;
859 switch (ErrorKind) {
860 default:
861 llvm_unreachable("Unhandled error.");
862 case RefVal::ErrorUseAfterRelease:
863 if (!useAfterRelease)
864 useAfterRelease.reset(new UseAfterRelease(this));
865 BT = useAfterRelease.get();
866 break;
867 case RefVal::ErrorReleaseNotOwned:
868 if (!releaseNotOwned)
869 releaseNotOwned.reset(new BadRelease(this));
870 BT = releaseNotOwned.get();
871 break;
872 case RefVal::ErrorDeallocNotOwned:
873 if (!deallocNotOwned)
874 deallocNotOwned.reset(new DeallocNotOwned(this));
875 BT = deallocNotOwned.get();
876 break;
877 }
878
879 assert(BT);
George Karpenkov6babf2a2018-09-21 20:36:21 +0000880 auto report = llvm::make_unique<CFRefReport>(
881 *BT, C.getASTContext().getLangOpts(), SummaryLog, N, Sym);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000882 report->addRange(ErrorRange);
883 C.emitReport(std::move(report));
884}
885
886//===----------------------------------------------------------------------===//
887// Handle the return values of retain-count-related functions.
888//===----------------------------------------------------------------------===//
889
890bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
891 // Get the callee. We're only interested in simple C functions.
892 ProgramStateRef state = C.getState();
893 const FunctionDecl *FD = C.getCalleeDecl(CE);
894 if (!FD)
895 return false;
896
George Karpenkovc4d6b932018-08-17 21:42:05 +0000897 RetainSummaryManager &SmrMgr = getSummaryManager(C);
898 QualType ResultTy = CE->getCallReturnType(C.getASTContext());
George Karpenkov70c2ee32018-08-17 21:41:07 +0000899
George Karpenkov70c2ee32018-08-17 21:41:07 +0000900 // See if the function has 'rc_ownership_trusted_implementation'
901 // annotate attribute. If it does, we will not inline it.
902 bool hasTrustedImplementationAnnotation = false;
903
George Karpenkov41dc8de2018-10-11 22:59:16 +0000904 const LocationContext *LCtx = C.getLocationContext();
905
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000906 using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
907 Optional<BehaviorSummary> BSmr =
908 SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);
909
George Karpenkovc4d6b932018-08-17 21:42:05 +0000910 // See if it's one of the specific functions we know how to eval.
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000911 if (!BSmr)
George Karpenkov70c2ee32018-08-17 21:41:07 +0000912 return false;
913
914 // Bind the return value.
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000915 if (BSmr == BehaviorSummary::Identity ||
916 BSmr == BehaviorSummary::IdentityOrZero) {
George Karpenkov48de5822018-10-23 23:11:30 +0000917 SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
918
George Karpenkov70c2ee32018-08-17 21:41:07 +0000919 // If the receiver is unknown or the function has
920 // 'rc_ownership_trusted_implementation' annotate attribute, conjure a
921 // return value.
George Karpenkov48de5822018-10-23 23:11:30 +0000922 if (RetVal.isUnknown() ||
923 (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {
924 SValBuilder &SVB = C.getSValBuilder();
925 RetVal =
926 SVB.conjureSymbolVal(nullptr, CE, LCtx, ResultTy, C.blockCount());
927 }
George Karpenkov3c2ed8f2018-10-25 23:38:07 +0000928 state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
929
930 if (BSmr == BehaviorSummary::IdentityOrZero) {
931 // Add a branch where the output is zero.
932 ProgramStateRef NullOutputState = C.getState();
933
934 // Assume that output is zero on the other branch.
935 NullOutputState = NullOutputState->BindExpr(
936 CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
937
938 C.addTransition(NullOutputState);
939
940 // And on the original branch assume that both input and
941 // output are non-zero.
942 if (auto L = RetVal.getAs<DefinedOrUnknownSVal>())
943 state = state->assume(*L, /*Assumption=*/true);
944
945 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000946 }
George Karpenkov70c2ee32018-08-17 21:41:07 +0000947
George Karpenkov70c2ee32018-08-17 21:41:07 +0000948 C.addTransition(state);
949 return true;
950}
951
George Karpenkov04553e52018-09-21 20:37:20 +0000952ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
953 CheckerContext &C) const {
954 ExplodedNode *Pred = C.getPredecessor();
George Karpenkov70c2ee32018-08-17 21:41:07 +0000955
956 // Only adjust the reference count if this is the top-level call frame,
957 // and not the result of inlining. In the future, we should do
958 // better checking even for inlined calls, and see if they match
959 // with their expected semantics (e.g., the method should return a retained
960 // object, etc.).
961 if (!C.inTopFrame())
George Karpenkov04553e52018-09-21 20:37:20 +0000962 return Pred;
963
964 if (!S)
965 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000966
967 const Expr *RetE = S->getRetValue();
968 if (!RetE)
George Karpenkov04553e52018-09-21 20:37:20 +0000969 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000970
971 ProgramStateRef state = C.getState();
972 SymbolRef Sym =
973 state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
974 if (!Sym)
George Karpenkov04553e52018-09-21 20:37:20 +0000975 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000976
977 // Get the reference count binding (if any).
978 const RefVal *T = getRefBinding(state, Sym);
979 if (!T)
George Karpenkov04553e52018-09-21 20:37:20 +0000980 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000981
982 // Change the reference count.
983 RefVal X = *T;
984
985 switch (X.getKind()) {
986 case RefVal::Owned: {
987 unsigned cnt = X.getCount();
988 assert(cnt > 0);
989 X.setCount(cnt - 1);
990 X = X ^ RefVal::ReturnedOwned;
991 break;
992 }
993
994 case RefVal::NotOwned: {
995 unsigned cnt = X.getCount();
996 if (cnt) {
997 X.setCount(cnt - 1);
998 X = X ^ RefVal::ReturnedOwned;
George Karpenkov04553e52018-09-21 20:37:20 +0000999 } else {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001000 X = X ^ RefVal::ReturnedNotOwned;
1001 }
1002 break;
1003 }
1004
1005 default:
George Karpenkov04553e52018-09-21 20:37:20 +00001006 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001007 }
1008
1009 // Update the binding.
1010 state = setRefBinding(state, Sym, X);
George Karpenkov04553e52018-09-21 20:37:20 +00001011 Pred = C.addTransition(state);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001012
1013 // At this point we have updated the state properly.
1014 // Everything after this is merely checking to see if the return value has
1015 // been over- or under-retained.
1016
1017 // Did we cache out?
1018 if (!Pred)
George Karpenkov04553e52018-09-21 20:37:20 +00001019 return nullptr;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001020
1021 // Update the autorelease counts.
1022 static CheckerProgramPointTag AutoreleaseTag(this, "Autorelease");
George Karpenkov04553e52018-09-21 20:37:20 +00001023 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X, S);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001024
George Karpenkov04553e52018-09-21 20:37:20 +00001025 // Have we generated a sink node?
George Karpenkov70c2ee32018-08-17 21:41:07 +00001026 if (!state)
George Karpenkov04553e52018-09-21 20:37:20 +00001027 return nullptr;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001028
1029 // Get the updated binding.
1030 T = getRefBinding(state, Sym);
1031 assert(T);
1032 X = *T;
1033
1034 // Consult the summary of the enclosing method.
1035 RetainSummaryManager &Summaries = getSummaryManager(C);
1036 const Decl *CD = &Pred->getCodeDecl();
1037 RetEffect RE = RetEffect::MakeNoRet();
1038
1039 // FIXME: What is the convention for blocks? Is there one?
1040 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
1041 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
1042 RE = Summ->getRetEffect();
1043 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
1044 if (!isa<CXXMethodDecl>(FD)) {
1045 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
1046 RE = Summ->getRetEffect();
1047 }
1048 }
1049
George Karpenkov04553e52018-09-21 20:37:20 +00001050 return checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001051}
1052
George Karpenkov04553e52018-09-21 20:37:20 +00001053ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
George Karpenkov70c2ee32018-08-17 21:41:07 +00001054 CheckerContext &C,
1055 ExplodedNode *Pred,
1056 RetEffect RE, RefVal X,
1057 SymbolRef Sym,
1058 ProgramStateRef state) const {
1059 // HACK: Ignore retain-count issues on values accessed through ivars,
1060 // because of cases like this:
1061 // [_contentView retain];
1062 // [_contentView removeFromSuperview];
1063 // [self addSubview:_contentView]; // invalidates 'self'
1064 // [_contentView release];
1065 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
George Karpenkov04553e52018-09-21 20:37:20 +00001066 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001067
1068 // Any leaks or other errors?
1069 if (X.isReturnedOwned() && X.getCount() == 0) {
1070 if (RE.getKind() != RetEffect::NoRet) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001071 if (!RE.isOwned()) {
George Karpenkov04553e52018-09-21 20:37:20 +00001072
George Karpenkov70c2ee32018-08-17 21:41:07 +00001073 // The returning type is a CF, we expect the enclosing method should
1074 // return ownership.
George Karpenkov70c2ee32018-08-17 21:41:07 +00001075 X = X ^ RefVal::ErrorLeakReturned;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001076
George Karpenkov70c2ee32018-08-17 21:41:07 +00001077 // Generate an error node.
1078 state = setRefBinding(state, Sym, X);
1079
1080 static CheckerProgramPointTag ReturnOwnLeakTag(this, "ReturnsOwnLeak");
1081 ExplodedNode *N = C.addTransition(state, Pred, &ReturnOwnLeakTag);
1082 if (N) {
1083 const LangOptions &LOpts = C.getASTContext().getLangOpts();
George Karpenkov04553e52018-09-21 20:37:20 +00001084 auto R = llvm::make_unique<CFRefLeakReport>(
George Karpenkov936a9c92018-12-07 20:21:37 +00001085 *getLeakAtReturnBug(LOpts), LOpts, SummaryLog, N, Sym, C);
George Karpenkov04553e52018-09-21 20:37:20 +00001086 C.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001087 }
George Karpenkov04553e52018-09-21 20:37:20 +00001088 return N;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001089 }
1090 }
1091 } else if (X.isReturnedNotOwned()) {
1092 if (RE.isOwned()) {
1093 if (X.getIvarAccessHistory() ==
1094 RefVal::IvarAccessHistory::AccessedDirectly) {
1095 // Assume the method was trying to transfer a +1 reference from a
1096 // strong ivar to the caller.
1097 state = setRefBinding(state, Sym,
1098 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
1099 } else {
1100 // Trying to return a not owned object to a caller expecting an
1101 // owned object.
1102 state = setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
1103
1104 static CheckerProgramPointTag
1105 ReturnNotOwnedTag(this, "ReturnNotOwnedForOwned");
1106
1107 ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
1108 if (N) {
1109 if (!returnNotOwnedForOwned)
1110 returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
1111
George Karpenkov04553e52018-09-21 20:37:20 +00001112 auto R = llvm::make_unique<CFRefReport>(
George Karpenkov70c2ee32018-08-17 21:41:07 +00001113 *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
George Karpenkov04553e52018-09-21 20:37:20 +00001114 SummaryLog, N, Sym);
1115 C.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001116 }
George Karpenkov04553e52018-09-21 20:37:20 +00001117 return N;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001118 }
1119 }
1120 }
George Karpenkov04553e52018-09-21 20:37:20 +00001121 return Pred;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001122}
1123
1124//===----------------------------------------------------------------------===//
1125// Check various ways a symbol can be invalidated.
1126//===----------------------------------------------------------------------===//
1127
1128void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
1129 CheckerContext &C) const {
1130 // Are we storing to something that causes the value to "escape"?
1131 bool escapes = true;
1132
1133 // A value escapes in three possible cases (this may change):
1134 //
1135 // (1) we are binding to something that is not a memory region.
1136 // (2) we are binding to a memregion that does not have stack storage
1137 // (3) we are binding to a memregion with stack storage that the store
1138 // does not understand.
1139 ProgramStateRef state = C.getState();
1140
George Karpenkov6e9fd132018-08-22 01:17:09 +00001141 if (auto regionLoc = loc.getAs<loc::MemRegionVal>()) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001142 escapes = !regionLoc->getRegion()->hasStackStorage();
1143
1144 if (!escapes) {
1145 // To test (3), generate a new state with the binding added. If it is
1146 // the same state, then it escapes (since the store cannot represent
1147 // the binding).
1148 // Do this only if we know that the store is not supposed to generate the
1149 // same state.
1150 SVal StoredVal = state->getSVal(regionLoc->getRegion());
1151 if (StoredVal != val)
1152 escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
1153 }
1154 if (!escapes) {
1155 // Case 4: We do not currently model what happens when a symbol is
1156 // assigned to a struct field, so be conservative here and let the symbol
1157 // go. TODO: This could definitely be improved upon.
1158 escapes = !isa<VarRegion>(regionLoc->getRegion());
1159 }
1160 }
1161
1162 // If we are storing the value into an auto function scope variable annotated
1163 // with (__attribute__((cleanup))), stop tracking the value to avoid leak
1164 // false positives.
George Karpenkov6e9fd132018-08-22 01:17:09 +00001165 if (const auto *LVR = dyn_cast_or_null<VarRegion>(loc.getAsRegion())) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001166 const VarDecl *VD = LVR->getDecl();
1167 if (VD->hasAttr<CleanupAttr>()) {
1168 escapes = true;
1169 }
1170 }
1171
1172 // If our store can represent the binding and we aren't storing to something
1173 // that doesn't have local storage then just return and have the simulation
1174 // state continue as is.
1175 if (!escapes)
1176 return;
1177
1178 // Otherwise, find all symbols referenced by 'val' that we are tracking
1179 // and stop tracking them.
1180 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
1181 C.addTransition(state);
1182}
1183
1184ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
George Karpenkov6e9fd132018-08-22 01:17:09 +00001185 SVal Cond,
1186 bool Assumption) const {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001187 // FIXME: We may add to the interface of evalAssume the list of symbols
1188 // whose assumptions have changed. For now we just iterate through the
1189 // bindings and check if any of the tracked symbols are NULL. This isn't
1190 // too bad since the number of symbols we will track in practice are
1191 // probably small and evalAssume is only called at branches and a few
1192 // other places.
1193 RefBindingsTy B = state->get<RefBindings>();
1194
1195 if (B.isEmpty())
1196 return state;
1197
1198 bool changed = false;
1199 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
1200
1201 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1202 // Check if the symbol is null stop tracking the symbol.
1203 ConstraintManager &CMgr = state->getConstraintManager();
1204 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1205 if (AllocFailed.isConstrainedTrue()) {
1206 changed = true;
1207 B = RefBFactory.remove(B, I.getKey());
1208 }
1209 }
1210
1211 if (changed)
1212 state = state->set<RefBindings>(B);
1213
1214 return state;
1215}
1216
1217ProgramStateRef
1218RetainCountChecker::checkRegionChanges(ProgramStateRef state,
1219 const InvalidatedSymbols *invalidated,
1220 ArrayRef<const MemRegion *> ExplicitRegions,
1221 ArrayRef<const MemRegion *> Regions,
1222 const LocationContext *LCtx,
1223 const CallEvent *Call) const {
1224 if (!invalidated)
1225 return state;
1226
1227 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
1228 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
1229 E = ExplicitRegions.end(); I != E; ++I) {
1230 if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
1231 WhitelistedSymbols.insert(SR->getSymbol());
1232 }
1233
George Karpenkov6fd5c86d2018-10-31 17:38:29 +00001234 for (SymbolRef sym :
1235 llvm::make_range(invalidated->begin(), invalidated->end())) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001236 if (WhitelistedSymbols.count(sym))
1237 continue;
1238 // Remove any existing reference-count binding.
1239 state = removeRefBinding(state, sym);
1240 }
1241 return state;
1242}
1243
George Karpenkov70c2ee32018-08-17 21:41:07 +00001244ProgramStateRef
1245RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
1246 ExplodedNode *Pred,
1247 const ProgramPointTag *Tag,
1248 CheckerContext &Ctx,
George Karpenkov04553e52018-09-21 20:37:20 +00001249 SymbolRef Sym,
1250 RefVal V,
1251 const ReturnStmt *S) const {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001252 unsigned ACnt = V.getAutoreleaseCount();
1253
1254 // No autorelease counts? Nothing to be done.
1255 if (!ACnt)
1256 return state;
1257
1258 unsigned Cnt = V.getCount();
1259
1260 // FIXME: Handle sending 'autorelease' to already released object.
1261
1262 if (V.getKind() == RefVal::ReturnedOwned)
1263 ++Cnt;
1264
1265 // If we would over-release here, but we know the value came from an ivar,
1266 // assume it was a strong ivar that's just been relinquished.
1267 if (ACnt > Cnt &&
1268 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
1269 V = V.releaseViaIvar();
1270 --ACnt;
1271 }
1272
1273 if (ACnt <= Cnt) {
1274 if (ACnt == Cnt) {
1275 V.clearCounts();
George Karpenkov04553e52018-09-21 20:37:20 +00001276 if (V.getKind() == RefVal::ReturnedOwned) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001277 V = V ^ RefVal::ReturnedNotOwned;
George Karpenkov04553e52018-09-21 20:37:20 +00001278 } else {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001279 V = V ^ RefVal::NotOwned;
George Karpenkov04553e52018-09-21 20:37:20 +00001280 }
George Karpenkov70c2ee32018-08-17 21:41:07 +00001281 } else {
1282 V.setCount(V.getCount() - ACnt);
1283 V.setAutoreleaseCount(0);
1284 }
1285 return setRefBinding(state, Sym, V);
1286 }
1287
1288 // HACK: Ignore retain-count issues on values accessed through ivars,
1289 // because of cases like this:
1290 // [_contentView retain];
1291 // [_contentView removeFromSuperview];
1292 // [self addSubview:_contentView]; // invalidates 'self'
1293 // [_contentView release];
1294 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1295 return state;
1296
1297 // Woah! More autorelease counts then retain counts left.
1298 // Emit hard error.
1299 V = V ^ RefVal::ErrorOverAutorelease;
1300 state = setRefBinding(state, Sym, V);
1301
1302 ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
1303 if (N) {
1304 SmallString<128> sbuf;
1305 llvm::raw_svector_ostream os(sbuf);
1306 os << "Object was autoreleased ";
1307 if (V.getAutoreleaseCount() > 1)
1308 os << V.getAutoreleaseCount() << " times but the object ";
1309 else
1310 os << "but ";
1311 os << "has a +" << V.getCount() << " retain count";
1312
1313 if (!overAutorelease)
1314 overAutorelease.reset(new OverAutorelease(this));
1315
1316 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
George Karpenkov04553e52018-09-21 20:37:20 +00001317 auto R = llvm::make_unique<CFRefReport>(*overAutorelease, LOpts, SummaryLog,
1318 N, Sym, os.str());
1319 Ctx.emitReport(std::move(R));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001320 }
1321
1322 return nullptr;
1323}
1324
1325ProgramStateRef
1326RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
1327 SymbolRef sid, RefVal V,
1328 SmallVectorImpl<SymbolRef> &Leaked) const {
1329 bool hasLeak;
1330
1331 // HACK: Ignore retain-count issues on values accessed through ivars,
1332 // because of cases like this:
1333 // [_contentView retain];
1334 // [_contentView removeFromSuperview];
1335 // [self addSubview:_contentView]; // invalidates 'self'
1336 // [_contentView release];
1337 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
1338 hasLeak = false;
1339 else if (V.isOwned())
1340 hasLeak = true;
1341 else if (V.isNotOwned() || V.isReturnedOwned())
1342 hasLeak = (V.getCount() > 0);
1343 else
1344 hasLeak = false;
1345
1346 if (!hasLeak)
1347 return removeRefBinding(state, sid);
1348
1349 Leaked.push_back(sid);
1350 return setRefBinding(state, sid, V ^ RefVal::ErrorLeak);
1351}
1352
1353ExplodedNode *
1354RetainCountChecker::processLeaks(ProgramStateRef state,
1355 SmallVectorImpl<SymbolRef> &Leaked,
1356 CheckerContext &Ctx,
1357 ExplodedNode *Pred) const {
1358 // Generate an intermediate node representing the leak point.
1359 ExplodedNode *N = Ctx.addTransition(state, Pred);
1360
1361 if (N) {
1362 for (SmallVectorImpl<SymbolRef>::iterator
1363 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
1364
1365 const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
1366 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts)
1367 : getLeakAtReturnBug(LOpts);
1368 assert(BT && "BugType not initialized.");
1369
George Karpenkov6babf2a2018-09-21 20:36:21 +00001370 Ctx.emitReport(llvm::make_unique<CFRefLeakReport>(
George Karpenkov936a9c92018-12-07 20:21:37 +00001371 *BT, LOpts, SummaryLog, N, *I, Ctx));
George Karpenkov70c2ee32018-08-17 21:41:07 +00001372 }
1373 }
1374
1375 return N;
1376}
1377
George Karpenkovb1b791b2018-08-17 21:43:27 +00001378static bool isISLObjectRef(QualType Ty) {
1379 return StringRef(Ty.getAsString()).startswith("isl_");
George Karpenkov70c2ee32018-08-17 21:41:07 +00001380}
1381
1382void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
1383 if (!Ctx.inTopFrame())
1384 return;
1385
George Karpenkovc4d6b932018-08-17 21:42:05 +00001386 RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001387 const LocationContext *LCtx = Ctx.getLocationContext();
1388 const FunctionDecl *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
1389
George Karpenkovc4d6b932018-08-17 21:42:05 +00001390 if (!FD || SmrMgr.isTrustedReferenceCountImplementation(FD))
George Karpenkov70c2ee32018-08-17 21:41:07 +00001391 return;
1392
1393 ProgramStateRef state = Ctx.getState();
George Karpenkovc4d6b932018-08-17 21:42:05 +00001394 const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001395 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
1396
1397 for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
1398 const ParmVarDecl *Param = FD->getParamDecl(idx);
1399 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
1400
1401 QualType Ty = Param->getType();
1402 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
George Karpenkovb1b791b2018-08-17 21:43:27 +00001403 if (AE && *AE == DecRef && isISLObjectRef(Ty)) {
George Karpenkov6e9fd132018-08-22 01:17:09 +00001404 state = setRefBinding(
1405 state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
George Karpenkovb1b791b2018-08-17 21:43:27 +00001406 } else if (isISLObjectRef(Ty)) {
George Karpenkov70c2ee32018-08-17 21:41:07 +00001407 state = setRefBinding(
1408 state, Sym,
1409 RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
1410 }
1411 }
1412
1413 Ctx.addTransition(state);
1414}
1415
1416void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
1417 CheckerContext &Ctx) const {
George Karpenkov04553e52018-09-21 20:37:20 +00001418 ExplodedNode *Pred = processReturn(RS, Ctx);
1419
1420 // Created state cached out.
1421 if (!Pred) {
1422 return;
1423 }
1424
1425 ProgramStateRef state = Pred->getState();
George Karpenkov70c2ee32018-08-17 21:41:07 +00001426 RefBindingsTy B = state->get<RefBindings>();
George Karpenkov70c2ee32018-08-17 21:41:07 +00001427
1428 // Don't process anything within synthesized bodies.
1429 const LocationContext *LCtx = Pred->getLocationContext();
1430 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
1431 assert(!LCtx->inTopFrame());
1432 return;
1433 }
1434
1435 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1436 state = handleAutoreleaseCounts(state, Pred, /*Tag=*/nullptr, Ctx,
1437 I->first, I->second);
1438 if (!state)
1439 return;
1440 }
1441
1442 // If the current LocationContext has a parent, don't check for leaks.
1443 // We will do that later.
1444 // FIXME: we should instead check for imbalances of the retain/releases,
1445 // and suggest annotations.
1446 if (LCtx->getParent())
1447 return;
1448
1449 B = state->get<RefBindings>();
1450 SmallVector<SymbolRef, 10> Leaked;
1451
1452 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
1453 state = handleSymbolDeath(state, I->first, I->second, Leaked);
1454
1455 processLeaks(state, Leaked, Ctx, Pred);
1456}
1457
George Karpenkov70c2ee32018-08-17 21:41:07 +00001458void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1459 CheckerContext &C) const {
1460 ExplodedNode *Pred = C.getPredecessor();
1461
1462 ProgramStateRef state = C.getState();
1463 RefBindingsTy B = state->get<RefBindings>();
1464 SmallVector<SymbolRef, 10> Leaked;
1465
1466 // Update counts from autorelease pools
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001467 for (const auto &I: state->get<RefBindings>()) {
1468 SymbolRef Sym = I.first;
1469 if (SymReaper.isDead(Sym)) {
Artem Dergachev65b4d7d2018-10-15 17:47:56 +00001470 static CheckerProgramPointTag Tag(this, "DeadSymbolAutorelease");
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001471 const RefVal &V = I.second;
1472 state = handleAutoreleaseCounts(state, Pred, &Tag, C, Sym, V);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001473 if (!state)
1474 return;
1475
1476 // Fetch the new reference count from the state, and use it to handle
1477 // this symbol.
Artem Dergachevbbc6d682018-11-30 03:27:50 +00001478 state = handleSymbolDeath(state, Sym, *getRefBinding(state, Sym), Leaked);
George Karpenkov70c2ee32018-08-17 21:41:07 +00001479 }
1480 }
1481
1482 if (Leaked.empty()) {
1483 C.addTransition(state);
1484 return;
1485 }
1486
1487 Pred = processLeaks(state, Leaked, C, Pred);
1488
1489 // Did we cache out?
1490 if (!Pred)
1491 return;
1492
1493 // Now generate a new node that nukes the old bindings.
1494 // The only bindings left at this point are the leaked symbols.
1495 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
1496 B = state->get<RefBindings>();
1497
1498 for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(),
1499 E = Leaked.end();
1500 I != E; ++I)
1501 B = F.remove(B, *I);
1502
1503 state = state->set<RefBindings>(B);
1504 C.addTransition(state, Pred);
1505}
1506
1507void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
1508 const char *NL, const char *Sep) const {
1509
1510 RefBindingsTy B = State->get<RefBindings>();
1511
1512 if (B.isEmpty())
1513 return;
1514
1515 Out << Sep << NL;
1516
1517 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1518 Out << I->first << " : ";
1519 I->second.print(Out);
1520 Out << NL;
1521 }
1522}
1523
1524//===----------------------------------------------------------------------===//
George Karpenkov70c2ee32018-08-17 21:41:07 +00001525// Checker registration.
1526//===----------------------------------------------------------------------===//
1527
1528void ento::registerRetainCountChecker(CheckerManager &Mgr) {
Kristof Umannc83b0dd2018-11-02 15:48:10 +00001529 auto *Chk = Mgr.registerChecker<RetainCountChecker>();
George Karpenkov27db3302018-12-07 20:21:51 +00001530 Chk->TrackObjCAndCFObjects = true;
1531}
Kristof Umannc83b0dd2018-11-02 15:48:10 +00001532
George Karpenkovd1081ec2018-12-11 01:13:58 +00001533// FIXME: remove this, hack for backwards compatibility:
1534// it should be possible to enable the NS/CF retain count checker as
1535// osx.cocoa.RetainCount, and it should be possible to disable
1536// osx.OSObjectRetainCount using osx.cocoa.RetainCount:CheckOSObject=false.
1537static bool hasPrevCheckOSObjectOptionDisabled(AnalyzerOptions &Options) {
1538 auto I = Options.Config.find("osx.cocoa.RetainCount:CheckOSObject");
1539 if (I != Options.Config.end())
1540 return I->getValue() == "false";
1541 return false;
1542}
1543
George Karpenkov27db3302018-12-07 20:21:51 +00001544void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1545 auto *Chk = Mgr.registerChecker<RetainCountChecker>();
George Karpenkovd1081ec2018-12-11 01:13:58 +00001546 if (!hasPrevCheckOSObjectOptionDisabled(Mgr.getAnalyzerOptions()))
1547 Chk->TrackOSObjects = true;
George Karpenkov70c2ee32018-08-17 21:41:07 +00001548}