Coverage Report

Created: 2023-09-21 18:56

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