1 // RetainCountDiagnostics.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 diagnostics for RetainCountChecker, which implements
10 //  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RetainCountDiagnostics.h"
15 #include "RetainCountChecker.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 
19 using namespace clang;
20 using namespace ento;
21 using namespace retaincountchecker;
22 
23 StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugKind BT) {
24   switch (BT) {
25   case UseAfterRelease:
26     return "Use-after-release";
27   case ReleaseNotOwned:
28     return "Bad release";
29   case DeallocNotOwned:
30     return "-dealloc sent to non-exclusively owned object";
31   case FreeNotOwned:
32     return "freeing non-exclusively owned object";
33   case OverAutorelease:
34     return "Object autoreleased too many times";
35   case ReturnNotOwnedForOwned:
36     return "Method should return an owned object";
37   case LeakWithinFunction:
38     return "Leak";
39   case LeakAtReturn:
40     return "Leak of returned object";
41   }
42   llvm_unreachable("Unknown RefCountBugKind");
43 }
44 
45 StringRef RefCountBug::getDescription() const {
46   switch (BT) {
47   case UseAfterRelease:
48     return "Reference-counted object is used after it is released";
49   case ReleaseNotOwned:
50     return "Incorrect decrement of the reference count of an object that is "
51            "not owned at this point by the caller";
52   case DeallocNotOwned:
53     return "-dealloc sent to object that may be referenced elsewhere";
54   case FreeNotOwned:
55     return  "'free' called on an object that may be referenced elsewhere";
56   case OverAutorelease:
57     return "Object autoreleased too many times";
58   case ReturnNotOwnedForOwned:
59     return "Object with a +0 retain count returned to caller where a +1 "
60            "(owning) retain count is expected";
61   case LeakWithinFunction:
62   case LeakAtReturn:
63     return "";
64   }
65   llvm_unreachable("Unknown RefCountBugKind");
66 }
67 
68 RefCountBug::RefCountBug(CheckerNameRef Checker, RefCountBugKind BT)
69     : BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount,
70               /*SuppressOnSink=*/BT == LeakWithinFunction ||
71                   BT == LeakAtReturn),
72       BT(BT) {}
73 
74 static bool isNumericLiteralExpression(const Expr *E) {
75   // FIXME: This set of cases was copied from SemaExprObjC.
76   return isa<IntegerLiteral>(E) ||
77          isa<CharacterLiteral>(E) ||
78          isa<FloatingLiteral>(E) ||
79          isa<ObjCBoolLiteralExpr>(E) ||
80          isa<CXXBoolLiteralExpr>(E);
81 }
82 
83 /// If type represents a pointer to CXXRecordDecl,
84 /// and is not a typedef, return the decl name.
85 /// Otherwise, return the serialization of type.
86 static std::string getPrettyTypeName(QualType QT) {
87   QualType PT = QT->getPointeeType();
88   if (!PT.isNull() && !QT->getAs<TypedefType>())
89     if (const auto *RD = PT->getAsCXXRecordDecl())
90       return std::string(RD->getName());
91   return QT.getAsString();
92 }
93 
94 /// Write information about the type state change to @c os,
95 /// return whether the note should be generated.
96 static bool shouldGenerateNote(llvm::raw_string_ostream &os,
97                                const RefVal *PrevT,
98                                const RefVal &CurrV,
99                                bool DeallocSent) {
100   // Get the previous type state.
101   RefVal PrevV = *PrevT;
102 
103   // Specially handle -dealloc.
104   if (DeallocSent) {
105     // Determine if the object's reference count was pushed to zero.
106     assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
107     // We may not have transitioned to 'release' if we hit an error.
108     // This case is handled elsewhere.
109     if (CurrV.getKind() == RefVal::Released) {
110       assert(CurrV.getCombinedCounts() == 0);
111       os << "Object released by directly sending the '-dealloc' message";
112       return true;
113     }
114   }
115 
116   // Determine if the typestate has changed.
117   if (!PrevV.hasSameState(CurrV))
118     switch (CurrV.getKind()) {
119     case RefVal::Owned:
120     case RefVal::NotOwned:
121       if (PrevV.getCount() == CurrV.getCount()) {
122         // Did an autorelease message get sent?
123         if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
124           return false;
125 
126         assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
127         os << "Object autoreleased";
128         return true;
129       }
130 
131       if (PrevV.getCount() > CurrV.getCount())
132         os << "Reference count decremented.";
133       else
134         os << "Reference count incremented.";
135 
136       if (unsigned Count = CurrV.getCount())
137         os << " The object now has a +" << Count << " retain count.";
138 
139       return true;
140 
141     case RefVal::Released:
142       if (CurrV.getIvarAccessHistory() ==
143               RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
144           CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
145         os << "Strong instance variable relinquished. ";
146       }
147       os << "Object released.";
148       return true;
149 
150     case RefVal::ReturnedOwned:
151       // Autoreleases can be applied after marking a node ReturnedOwned.
152       if (CurrV.getAutoreleaseCount())
153         return false;
154 
155       os << "Object returned to caller as an owning reference (single "
156             "retain count transferred to caller)";
157       return true;
158 
159     case RefVal::ReturnedNotOwned:
160       os << "Object returned to caller with a +0 retain count";
161       return true;
162 
163     default:
164       return false;
165     }
166   return true;
167 }
168 
169 /// Finds argument index of the out paramter in the call @c S
170 /// corresponding to the symbol @c Sym.
171 /// If none found, returns None.
172 static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
173                                              const LocationContext *LCtx,
174                                              SymbolRef &Sym,
175                                              Optional<CallEventRef<>> CE) {
176   if (!CE)
177     return None;
178 
179   for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)
180     if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())
181       if (const auto *TR = dyn_cast<TypedValueRegion>(MR))
182         if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymbol() == Sym)
183           return Idx;
184 
185   return None;
186 }
187 
188 static Optional<std::string> findMetaClassAlloc(const Expr *Callee) {
189   if (const auto *ME = dyn_cast<MemberExpr>(Callee)) {
190     if (ME->getMemberDecl()->getNameAsString() != "alloc")
191       return None;
192     const Expr *This = ME->getBase()->IgnoreParenImpCasts();
193     if (const auto *DRE = dyn_cast<DeclRefExpr>(This)) {
194       const ValueDecl *VD = DRE->getDecl();
195       if (VD->getNameAsString() != "metaClass")
196         return None;
197 
198       if (const auto *RD = dyn_cast<CXXRecordDecl>(VD->getDeclContext()))
199         return RD->getNameAsString();
200 
201     }
202   }
203   return None;
204 }
205 
206 static std::string findAllocatedObjectName(const Stmt *S, QualType QT) {
207   if (const auto *CE = dyn_cast<CallExpr>(S))
208     if (auto Out = findMetaClassAlloc(CE->getCallee()))
209       return *Out;
210   return getPrettyTypeName(QT);
211 }
212 
213 static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
214                                            const LocationContext *LCtx,
215                                            const RefVal &CurrV, SymbolRef &Sym,
216                                            const Stmt *S,
217                                            llvm::raw_string_ostream &os) {
218   CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
219   if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
220     // Get the name of the callee (if it is available)
221     // from the tracked SVal.
222     SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
223     const FunctionDecl *FD = X.getAsFunctionDecl();
224 
225     // If failed, try to get it from AST.
226     if (!FD)
227       FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
228 
229     if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
230       os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
231     } else if (FD) {
232       os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
233     } else {
234       os << "function call";
235     }
236   } else if (isa<CXXNewExpr>(S)) {
237     os << "Operator 'new'";
238   } else {
239     assert(isa<ObjCMessageExpr>(S));
240     CallEventRef<ObjCMethodCall> Call =
241         Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
242 
243     switch (Call->getMessageKind()) {
244     case OCM_Message:
245       os << "Method";
246       break;
247     case OCM_PropertyAccess:
248       os << "Property";
249       break;
250     case OCM_Subscript:
251       os << "Subscript";
252       break;
253     }
254   }
255 
256   Optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx);
257   auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
258 
259   // If index is not found, we assume that the symbol was returned.
260   if (!Idx) {
261     os << " returns ";
262   } else {
263     os << " writes ";
264   }
265 
266   if (CurrV.getObjKind() == ObjKind::CF) {
267     os << "a Core Foundation object of type '"
268        << Sym->getType().getAsString() << "' with a ";
269   } else if (CurrV.getObjKind() == ObjKind::OS) {
270     os << "an OSObject of type '" << findAllocatedObjectName(S, Sym->getType())
271        << "' with a ";
272   } else if (CurrV.getObjKind() == ObjKind::Generalized) {
273     os << "an object of type '" << Sym->getType().getAsString()
274        << "' with a ";
275   } else {
276     assert(CurrV.getObjKind() == ObjKind::ObjC);
277     QualType T = Sym->getType();
278     if (!isa<ObjCObjectPointerType>(T)) {
279       os << "an Objective-C object with a ";
280     } else {
281       const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
282       os << "an instance of " << PT->getPointeeType().getAsString()
283          << " with a ";
284     }
285   }
286 
287   if (CurrV.isOwned()) {
288     os << "+1 retain count";
289   } else {
290     assert(CurrV.isNotOwned());
291     os << "+0 retain count";
292   }
293 
294   if (Idx) {
295     os << " into an out parameter '";
296     const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
297     PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
298                               /*Qualified=*/false);
299     os << "'";
300 
301     QualType RT = (*CE)->getResultType();
302     if (!RT.isNull() && !RT->isVoidType()) {
303       SVal RV = (*CE)->getReturnValue();
304       if (CurrSt->isNull(RV).isConstrainedTrue()) {
305         os << " (assuming the call returns zero)";
306       } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
307         os << " (assuming the call returns non-zero)";
308       }
309 
310     }
311   }
312 }
313 
314 namespace clang {
315 namespace ento {
316 namespace retaincountchecker {
317 
318 class RefCountReportVisitor : public BugReporterVisitor {
319 protected:
320   SymbolRef Sym;
321 
322 public:
323   RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
324 
325   void Profile(llvm::FoldingSetNodeID &ID) const override {
326     static int x = 0;
327     ID.AddPointer(&x);
328     ID.AddPointer(Sym);
329   }
330 
331   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
332                                    BugReporterContext &BRC,
333                                    PathSensitiveBugReport &BR) override;
334 
335   PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
336                                     const ExplodedNode *N,
337                                     PathSensitiveBugReport &BR) override;
338 };
339 
340 class RefLeakReportVisitor : public RefCountReportVisitor {
341 public:
342   RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
343       : RefCountReportVisitor(Sym), LastBinding(LastBinding) {}
344 
345   PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
346                                     const ExplodedNode *N,
347                                     PathSensitiveBugReport &BR) override;
348 
349 private:
350   const MemRegion *LastBinding;
351 };
352 
353 } // end namespace retaincountchecker
354 } // end namespace ento
355 } // end namespace clang
356 
357 
358 /// Find the first node with the parent stack frame.
359 static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
360   const StackFrameContext *SC = Pred->getStackFrame();
361   if (SC->inTopFrame())
362     return nullptr;
363   const StackFrameContext *PC = SC->getParent()->getStackFrame();
364   if (!PC)
365     return nullptr;
366 
367   const ExplodedNode *N = Pred;
368   while (N && N->getStackFrame() != PC) {
369     N = N->getFirstPred();
370   }
371   return N;
372 }
373 
374 
375 /// Insert a diagnostic piece at function exit
376 /// if a function parameter is annotated as "os_consumed",
377 /// but it does not actually consume the reference.
378 static std::shared_ptr<PathDiagnosticEventPiece>
379 annotateConsumedSummaryMismatch(const ExplodedNode *N,
380                                 CallExitBegin &CallExitLoc,
381                                 const SourceManager &SM,
382                                 CallEventManager &CEMgr) {
383 
384   const ExplodedNode *CN = getCalleeNode(N);
385   if (!CN)
386     return nullptr;
387 
388   CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
389 
390   std::string sbuf;
391   llvm::raw_string_ostream os(sbuf);
392   ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
393   for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
394     const ParmVarDecl *PVD = Parameters[I];
395 
396     if (!PVD->hasAttr<OSConsumedAttr>())
397       continue;
398 
399     if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
400       const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
401       const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
402 
403       if (!CountBeforeCall || !CountAtExit)
404         continue;
405 
406       unsigned CountBefore = CountBeforeCall->getCount();
407       unsigned CountAfter = CountAtExit->getCount();
408 
409       bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
410       if (!AsExpected) {
411         os << "Parameter '";
412         PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
413                                   /*Qualified=*/false);
414         os << "' is marked as consuming, but the function did not consume "
415            << "the reference\n";
416       }
417     }
418   }
419 
420   if (os.str().empty())
421     return nullptr;
422 
423   PathDiagnosticLocation L = PathDiagnosticLocation::create(CallExitLoc, SM);
424   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
425 }
426 
427 /// Annotate the parameter at the analysis entry point.
428 static std::shared_ptr<PathDiagnosticEventPiece>
429 annotateStartParameter(const ExplodedNode *N, SymbolRef Sym,
430                        const SourceManager &SM) {
431   auto PP = N->getLocationAs<BlockEdge>();
432   if (!PP)
433     return nullptr;
434 
435   const CFGBlock *Src = PP->getSrc();
436   const RefVal *CurrT = getRefBinding(N->getState(), Sym);
437 
438   if (&Src->getParent()->getEntry() != Src || !CurrT ||
439       getRefBinding(N->getFirstPred()->getState(), Sym))
440     return nullptr;
441 
442   const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion());
443   const auto *PVD = cast<ParmVarDecl>(VR->getDecl());
444   PathDiagnosticLocation L = PathDiagnosticLocation(PVD, SM);
445 
446   std::string s;
447   llvm::raw_string_ostream os(s);
448   os << "Parameter '" << PVD->getDeclName() << "' starts at +";
449   if (CurrT->getCount() == 1) {
450     os << "1, as it is marked as consuming";
451   } else {
452     assert(CurrT->getCount() == 0);
453     os << "0";
454   }
455   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
456 }
457 
458 PathDiagnosticPieceRef
459 RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
460                                  PathSensitiveBugReport &BR) {
461 
462   const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
463 
464   bool IsFreeUnowned = BT.getBugType() == RefCountBug::FreeNotOwned ||
465                        BT.getBugType() == RefCountBug::DeallocNotOwned;
466 
467   const SourceManager &SM = BRC.getSourceManager();
468   CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
469   if (auto CE = N->getLocationAs<CallExitBegin>())
470     if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
471       return PD;
472 
473   if (auto PD = annotateStartParameter(N, Sym, SM))
474     return PD;
475 
476   // FIXME: We will eventually need to handle non-statement-based events
477   // (__attribute__((cleanup))).
478   if (!N->getLocation().getAs<StmtPoint>())
479     return nullptr;
480 
481   // Check if the type state has changed.
482   const ExplodedNode *PrevNode = N->getFirstPred();
483   ProgramStateRef PrevSt = PrevNode->getState();
484   ProgramStateRef CurrSt = N->getState();
485   const LocationContext *LCtx = N->getLocationContext();
486 
487   const RefVal* CurrT = getRefBinding(CurrSt, Sym);
488   if (!CurrT)
489     return nullptr;
490 
491   const RefVal &CurrV = *CurrT;
492   const RefVal *PrevT = getRefBinding(PrevSt, Sym);
493 
494   // Create a string buffer to constain all the useful things we want
495   // to tell the user.
496   std::string sbuf;
497   llvm::raw_string_ostream os(sbuf);
498 
499   if (PrevT && IsFreeUnowned && CurrV.isNotOwned() && PrevT->isOwned()) {
500     os << "Object is now not exclusively owned";
501     auto Pos = PathDiagnosticLocation::create(N->getLocation(), SM);
502     return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
503   }
504 
505   // This is the allocation site since the previous node had no bindings
506   // for this symbol.
507   if (!PrevT) {
508     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
509 
510     if (isa<ObjCIvarRefExpr>(S) &&
511         isSynthesizedAccessor(LCtx->getStackFrame())) {
512       S = LCtx->getStackFrame()->getCallSite();
513     }
514 
515     if (isa<ObjCArrayLiteral>(S)) {
516       os << "NSArray literal is an object with a +0 retain count";
517     } else if (isa<ObjCDictionaryLiteral>(S)) {
518       os << "NSDictionary literal is an object with a +0 retain count";
519     } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
520       if (isNumericLiteralExpression(BL->getSubExpr()))
521         os << "NSNumber literal is an object with a +0 retain count";
522       else {
523         const ObjCInterfaceDecl *BoxClass = nullptr;
524         if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
525           BoxClass = Method->getClassInterface();
526 
527         // We should always be able to find the boxing class interface,
528         // but consider this future-proofing.
529         if (BoxClass) {
530           os << *BoxClass << " b";
531         } else {
532           os << "B";
533         }
534 
535         os << "oxed expression produces an object with a +0 retain count";
536       }
537     } else if (isa<ObjCIvarRefExpr>(S)) {
538       os << "Object loaded from instance variable";
539     } else {
540       generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
541     }
542 
543     PathDiagnosticLocation Pos(S, SM, N->getLocationContext());
544     return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
545   }
546 
547   // Gather up the effects that were performed on the object at this
548   // program point
549   bool DeallocSent = false;
550 
551   const ProgramPointTag *Tag = N->getLocation().getTag();
552 
553   if (Tag == &RetainCountChecker::getCastFailTag()) {
554     os << "Assuming dynamic cast returns null due to type mismatch";
555   }
556 
557   if (Tag == &RetainCountChecker::getDeallocSentTag()) {
558     // We only have summaries attached to nodes after evaluating CallExpr and
559     // ObjCMessageExprs.
560     const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
561 
562     if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
563       // Iterate through the parameter expressions and see if the symbol
564       // was ever passed as an argument.
565       unsigned i = 0;
566 
567       for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
568 
569         // Retrieve the value of the argument.  Is it the symbol
570         // we are interested in?
571         if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
572           continue;
573 
574         // We have an argument.  Get the effect!
575         DeallocSent = true;
576       }
577     } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
578       if (const Expr *receiver = ME->getInstanceReceiver()) {
579         if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
580               .getAsLocSymbol() == Sym) {
581           // The symbol we are tracking is the receiver.
582           DeallocSent = true;
583         }
584       }
585     }
586   }
587 
588   if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
589     return nullptr;
590 
591   if (os.str().empty())
592     return nullptr; // We have nothing to say!
593 
594   const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
595   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
596                                 N->getLocationContext());
597   auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
598 
599   // Add the range by scanning the children of the statement for any bindings
600   // to Sym.
601   for (const Stmt *Child : S->children())
602     if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
603       if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
604         P->addRange(Exp->getSourceRange());
605         break;
606       }
607 
608   return std::move(P);
609 }
610 
611 static Optional<std::string> describeRegion(const MemRegion *MR) {
612   if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
613     return std::string(VR->getDecl()->getName());
614   // Once we support more storage locations for bindings,
615   // this would need to be improved.
616   return None;
617 }
618 
619 using Bindings = llvm::SmallVector<std::pair<const MemRegion *, SVal>, 4>;
620 
621 class VarBindingsCollector : public StoreManager::BindingsHandler {
622   SymbolRef Sym;
623   Bindings &Result;
624 
625 public:
626   VarBindingsCollector(SymbolRef Sym, Bindings &ToFill)
627       : Sym(Sym), Result(ToFill) {}
628 
629   bool HandleBinding(StoreManager &SMgr, Store Store, const MemRegion *R,
630                      SVal Val) override {
631     SymbolRef SymV = Val.getAsLocSymbol();
632     if (!SymV || SymV != Sym)
633       return true;
634 
635     if (isa<NonParamVarRegion>(R))
636       Result.emplace_back(R, Val);
637 
638     return true;
639   }
640 };
641 
642 Bindings getAllVarBindingsForSymbol(ProgramStateManager &Manager,
643                                     const ExplodedNode *Node, SymbolRef Sym) {
644   Bindings Result;
645   VarBindingsCollector Collector{Sym, Result};
646   while (Result.empty() && Node) {
647     Manager.iterBindings(Node->getState(), Collector);
648     Node = Node->getFirstPred();
649   }
650 
651   return Result;
652 }
653 
654 namespace {
655 // Find the first node in the current function context that referred to the
656 // tracked symbol and the memory location that value was stored to. Note, the
657 // value is only reported if the allocation occurred in the same function as
658 // the leak. The function can also return a location context, which should be
659 // treated as interesting.
660 struct AllocationInfo {
661   const ExplodedNode* N;
662   const MemRegion *R;
663   const LocationContext *InterestingMethodContext;
664   AllocationInfo(const ExplodedNode *InN,
665                  const MemRegion *InR,
666                  const LocationContext *InInterestingMethodContext) :
667     N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
668 };
669 } // end anonymous namespace
670 
671 static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
672                                         const ExplodedNode *N, SymbolRef Sym) {
673   const ExplodedNode *AllocationNode = N;
674   const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
675   const MemRegion *FirstBinding = nullptr;
676   const LocationContext *LeakContext = N->getLocationContext();
677 
678   // The location context of the init method called on the leaked object, if
679   // available.
680   const LocationContext *InitMethodContext = nullptr;
681 
682   while (N) {
683     ProgramStateRef St = N->getState();
684     const LocationContext *NContext = N->getLocationContext();
685 
686     if (!getRefBinding(St, Sym))
687       break;
688 
689     StoreManager::FindUniqueBinding FB(Sym);
690     StateMgr.iterBindings(St, FB);
691 
692     if (FB) {
693       const MemRegion *R = FB.getRegion();
694       // Do not show local variables belonging to a function other than
695       // where the error is reported.
696       if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
697         if (MR->getStackFrame() == LeakContext->getStackFrame())
698           FirstBinding = R;
699     }
700 
701     // AllocationNode is the last node in which the symbol was tracked.
702     AllocationNode = N;
703 
704     // AllocationNodeInCurrentContext, is the last node in the current or
705     // parent context in which the symbol was tracked.
706     //
707     // Note that the allocation site might be in the parent context. For example,
708     // the case where an allocation happens in a block that captures a reference
709     // to it and that reference is overwritten/dropped by another call to
710     // the block.
711     if (NContext == LeakContext || NContext->isParentOf(LeakContext))
712       AllocationNodeInCurrentOrParentContext = N;
713 
714     // Find the last init that was called on the given symbol and store the
715     // init method's location context.
716     if (!InitMethodContext)
717       if (auto CEP = N->getLocation().getAs<CallEnter>()) {
718         const Stmt *CE = CEP->getCallExpr();
719         if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
720           const Stmt *RecExpr = ME->getInstanceReceiver();
721           if (RecExpr) {
722             SVal RecV = St->getSVal(RecExpr, NContext);
723             if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
724               InitMethodContext = CEP->getCalleeContext();
725           }
726         }
727       }
728 
729     N = N->getFirstPred();
730   }
731 
732   // If we are reporting a leak of the object that was allocated with alloc,
733   // mark its init method as interesting.
734   const LocationContext *InterestingMethodContext = nullptr;
735   if (InitMethodContext) {
736     const ProgramPoint AllocPP = AllocationNode->getLocation();
737     if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
738       if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
739         if (ME->getMethodFamily() == OMF_alloc)
740           InterestingMethodContext = InitMethodContext;
741   }
742 
743   // If allocation happened in a function different from the leak node context,
744   // do not report the binding.
745   assert(N && "Could not find allocation node");
746 
747   if (AllocationNodeInCurrentOrParentContext &&
748       AllocationNodeInCurrentOrParentContext->getLocationContext() !=
749       LeakContext)
750     FirstBinding = nullptr;
751 
752   return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,
753                         InterestingMethodContext);
754 }
755 
756 PathDiagnosticPieceRef
757 RefCountReportVisitor::getEndPath(BugReporterContext &BRC,
758                                   const ExplodedNode *EndN,
759                                   PathSensitiveBugReport &BR) {
760   BR.markInteresting(Sym);
761   return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
762 }
763 
764 PathDiagnosticPieceRef
765 RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
766                                  const ExplodedNode *EndN,
767                                  PathSensitiveBugReport &BR) {
768 
769   // Tell the BugReporterContext to report cases when the tracked symbol is
770   // assigned to different variables, etc.
771   BR.markInteresting(Sym);
772 
773   PathDiagnosticLocation L = cast<RefLeakReport>(BR).getEndOfPath();
774 
775   std::string sbuf;
776   llvm::raw_string_ostream os(sbuf);
777 
778   os << "Object leaked: ";
779 
780   Optional<std::string> RegionDescription = describeRegion(LastBinding);
781   if (RegionDescription) {
782     os << "object allocated and stored into '" << *RegionDescription << '\'';
783   } else {
784     os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
785        << "'";
786   }
787 
788   // Get the retain count.
789   const RefVal *RV = getRefBinding(EndN->getState(), Sym);
790   assert(RV);
791 
792   if (RV->getKind() == RefVal::ErrorLeakReturned) {
793     // FIXME: Per comments in rdar://6320065, "create" only applies to CF
794     // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
795     // to the caller for NS objects.
796     const Decl *D = &EndN->getCodeDecl();
797 
798     os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
799                                   : " is returned from a function ");
800 
801     if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
802       os << "that is annotated as CF_RETURNS_NOT_RETAINED";
803     } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
804       os << "that is annotated as NS_RETURNS_NOT_RETAINED";
805     } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
806       os << "that is annotated as OS_RETURNS_NOT_RETAINED";
807     } else {
808       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
809         if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
810           os << "managed by Automatic Reference Counting";
811         } else {
812           os << "whose name ('" << MD->getSelector().getAsString()
813              << "') does not start with "
814                 "'copy', 'mutableCopy', 'alloc' or 'new'."
815                 "  This violates the naming convention rules"
816                 " given in the Memory Management Guide for Cocoa";
817         }
818       } else {
819         const FunctionDecl *FD = cast<FunctionDecl>(D);
820         ObjKind K = RV->getObjKind();
821         if (K == ObjKind::ObjC || K == ObjKind::CF) {
822           os << "whose name ('" << *FD
823              << "') does not contain 'Copy' or 'Create'.  This violates the "
824                 "naming"
825                 " convention rules given in the Memory Management Guide for "
826                 "Core"
827                 " Foundation";
828         } else if (RV->getObjKind() == ObjKind::OS) {
829           std::string FuncName = FD->getNameAsString();
830           os << "whose name ('" << FuncName << "') starts with '"
831              << StringRef(FuncName).substr(0, 3) << "'";
832         }
833       }
834     }
835   } else {
836     os << " is not referenced later in this execution path and has a retain "
837           "count of +"
838        << RV->getCount();
839   }
840 
841   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
842 }
843 
844 RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
845                                ExplodedNode *n, SymbolRef sym, bool isLeak)
846     : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
847       isLeak(isLeak) {
848   if (!isLeak)
849     addVisitor<RefCountReportVisitor>(sym);
850 }
851 
852 RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
853                                ExplodedNode *n, SymbolRef sym,
854                                StringRef endText)
855     : PathSensitiveBugReport(D, D.getDescription(), endText, n) {
856 
857   addVisitor<RefCountReportVisitor>(sym);
858 }
859 
860 void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
861   const SourceManager &SMgr = Ctx.getSourceManager();
862 
863   if (!Sym->getOriginRegion())
864     return;
865 
866   auto *Region = dyn_cast<DeclRegion>(Sym->getOriginRegion());
867   if (Region) {
868     const Decl *PDecl = Region->getDecl();
869     if (isa_and_nonnull<ParmVarDecl>(PDecl)) {
870       PathDiagnosticLocation ParamLocation =
871           PathDiagnosticLocation::create(PDecl, SMgr);
872       Location = ParamLocation;
873       UniqueingLocation = ParamLocation;
874       UniqueingDecl = Ctx.getLocationContext()->getDecl();
875     }
876   }
877 }
878 
879 void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
880   // Most bug reports are cached at the location where they occurred.
881   // With leaks, we want to unique them by the location where they were
882   // allocated, and only report a single path.  To do this, we need to find
883   // the allocation site of a piece of tracked memory, which we do via a
884   // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
885   // Note that this is *not* the trimmed graph; we are guaranteed, however,
886   // that all ancestor nodes that represent the allocation site have the
887   // same SourceLocation.
888   const ExplodedNode *AllocNode = nullptr;
889 
890   const SourceManager &SMgr = Ctx.getSourceManager();
891 
892   AllocationInfo AllocI =
893       GetAllocationSite(Ctx.getStateManager(), getErrorNode(), Sym);
894 
895   AllocNode = AllocI.N;
896   AllocFirstBinding = AllocI.R;
897   markInteresting(AllocI.InterestingMethodContext);
898 
899   // Get the SourceLocation for the allocation site.
900   // FIXME: This will crash the analyzer if an allocation comes from an
901   // implicit call (ex: a destructor call).
902   // (Currently there are no such allocations in Cocoa, though.)
903   AllocStmt = AllocNode->getStmtForDiagnostics();
904 
905   if (!AllocStmt) {
906     AllocFirstBinding = nullptr;
907     return;
908   }
909 
910   PathDiagnosticLocation AllocLocation = PathDiagnosticLocation::createBegin(
911       AllocStmt, SMgr, AllocNode->getLocationContext());
912   Location = AllocLocation;
913 
914   // Set uniqieing info, which will be used for unique the bug reports. The
915   // leaks should be uniqued on the allocation site.
916   UniqueingLocation = AllocLocation;
917   UniqueingDecl = AllocNode->getLocationContext()->getDecl();
918 }
919 
920 void RefLeakReport::createDescription(CheckerContext &Ctx) {
921   assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
922   Description.clear();
923   llvm::raw_string_ostream os(Description);
924   os << "Potential leak of an object";
925 
926   Optional<std::string> RegionDescription =
927       describeRegion(AllocBindingToReport);
928   if (RegionDescription) {
929     os << " stored into '" << *RegionDescription << '\'';
930   } else {
931 
932     // If we can't figure out the name, just supply the type information.
933     os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
934   }
935 }
936 
937 void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
938                                         ExplodedNode *Node) {
939   if (!AllocFirstBinding)
940     // If we don't have any bindings, we won't be able to find any
941     // better binding to report.
942     return;
943 
944   // If the original region still contains the leaking symbol...
945   if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {
946     // ...it is the best binding to report.
947     AllocBindingToReport = AllocFirstBinding;
948     return;
949   }
950 
951   // At this point, we know that the original region doesn't contain the leaking
952   // when the actual leak happens.  It means that it can be confusing for the
953   // user to see such description in the message.
954   //
955   // Let's consider the following example:
956   //   Object *Original = allocate(...);
957   //   Object *New = Original;
958   //   Original = allocate(...);
959   //   Original->release();
960   //
961   // Complaining about a leaking object "stored into Original" might cause a
962   // rightful confusion because 'Original' is actually released.
963   // We should complain about 'New' instead.
964   Bindings AllVarBindings =
965       getAllVarBindingsForSymbol(Ctx.getStateManager(), Node, Sym);
966 
967   // While looking for the last var bindings, we can still find
968   // `AllocFirstBinding` to be one of them.  In situations like this,
969   // it would still be the easiest case to explain to our users.
970   if (!AllVarBindings.empty() &&
971       llvm::count_if(AllVarBindings,
972                      [this](const std::pair<const MemRegion *, SVal> Binding) {
973                        return Binding.first == AllocFirstBinding;
974                      }) == 0) {
975     // Let's pick one of them at random (if there is something to pick from).
976     AllocBindingToReport = AllVarBindings[0].first;
977 
978     // Because 'AllocBindingToReport' is not the the same as
979     // 'AllocFirstBinding', we need to explain how the leaking object
980     // got from one to another.
981     //
982     // NOTE: We use the actual SVal stored in AllocBindingToReport here because
983     //       trackStoredValue compares SVal's and it can get trickier for
984     //       something like derived regions if we want to construct SVal from
985     //       Sym. Instead, we take the value that is definitely stored in that
986     //       region, thus guaranteeing that trackStoredValue will work.
987     bugreporter::trackStoredValue(AllVarBindings[0].second.castAs<KnownSVal>(),
988                                   AllocBindingToReport, *this);
989   } else {
990     AllocBindingToReport = AllocFirstBinding;
991   }
992 }
993 
994 RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
995                              ExplodedNode *N, SymbolRef Sym,
996                              CheckerContext &Ctx)
997     : RefCountReport(D, LOpts, N, Sym, /*isLeak=*/true) {
998 
999   deriveAllocLocation(Ctx);
1000   findBindingToReport(Ctx, N);
1001 
1002   if (!AllocFirstBinding)
1003     deriveParamLocation(Ctx);
1004 
1005   createDescription(Ctx);
1006 
1007   addVisitor<RefLeakReportVisitor>(Sym, AllocBindingToReport);
1008 }
1009