1 //==--- RetainCountChecker.h - Checks for leaks and other issues -*- C++ -*--// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the methods for RetainCountChecker, which implements 11 // a reference count checker for Core Foundation and Cocoa on (Mac OS X). 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H 16 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H 17 18 #include "../ClangSACheckers.h" 19 #include "RetainCountDiagnostics.h" 20 #include "clang/AST/Attr.h" 21 #include "clang/AST/DeclCXX.h" 22 #include "clang/AST/DeclObjC.h" 23 #include "clang/AST/ParentMap.h" 24 #include "clang/Analysis/DomainSpecific/CocoaConventions.h" 25 #include "clang/Basic/LangOptions.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/Analysis/SelectorExtras.h" 28 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 29 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 30 #include "clang/StaticAnalyzer/Core/Checker.h" 31 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 32 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 33 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 34 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 35 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 36 #include "clang/StaticAnalyzer/Core/RetainSummaryManager.h" 37 #include "llvm/ADT/DenseMap.h" 38 #include "llvm/ADT/FoldingSet.h" 39 #include "llvm/ADT/ImmutableList.h" 40 #include "llvm/ADT/ImmutableMap.h" 41 #include "llvm/ADT/STLExtras.h" 42 #include "llvm/ADT/SmallString.h" 43 #include "llvm/ADT/StringExtras.h" 44 #include <cstdarg> 45 #include <utility> 46 47 namespace clang { 48 namespace ento { 49 namespace retaincountchecker { 50 51 /// Metadata on reference. 52 class RefVal { 53 public: 54 enum Kind { 55 Owned = 0, // Owning reference. 56 NotOwned, // Reference is not owned by still valid (not freed). 57 Released, // Object has been released. 58 ReturnedOwned, // Returned object passes ownership to caller. 59 ReturnedNotOwned, // Return object does not pass ownership to caller. 60 ERROR_START, 61 ErrorDeallocNotOwned, // -dealloc called on non-owned object. 62 ErrorUseAfterRelease, // Object used after released. 63 ErrorReleaseNotOwned, // Release of an object that was not owned. 64 ERROR_LEAK_START, 65 ErrorLeak, // A memory leak due to excessive reference counts. 66 ErrorLeakReturned, // A memory leak due to the returning method not having 67 // the correct naming conventions. 68 ErrorOverAutorelease, 69 ErrorReturnedNotOwned 70 }; 71 72 /// Tracks how an object referenced by an ivar has been used. 73 /// 74 /// This accounts for us not knowing if an arbitrary ivar is supposed to be 75 /// stored at +0 or +1. 76 enum class IvarAccessHistory { 77 None, 78 AccessedDirectly, 79 ReleasedAfterDirectAccess 80 }; 81 82 private: 83 /// The number of outstanding retains. 84 unsigned Cnt; 85 /// The number of outstanding autoreleases. 86 unsigned ACnt; 87 /// The (static) type of the object at the time we started tracking it. 88 QualType T; 89 90 /// The current state of the object. 91 /// 92 /// See the RefVal::Kind enum for possible values. 93 unsigned RawKind : 5; 94 95 /// The kind of object being tracked (CF or ObjC or OSObject), if known. 96 /// 97 /// See the RetEffect::ObjKind enum for possible values. 98 unsigned RawObjectKind : 3; 99 100 /// True if the current state and/or retain count may turn out to not be the 101 /// best possible approximation of the reference counting state. 102 /// 103 /// If true, the checker may decide to throw away ("override") this state 104 /// in favor of something else when it sees the object being used in new ways. 105 /// 106 /// This setting should not be propagated to state derived from this state. 107 /// Once we start deriving new states, it would be inconsistent to override 108 /// them. 109 unsigned RawIvarAccessHistory : 2; 110 111 RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t, 112 IvarAccessHistory IvarAccess) 113 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)), 114 RawObjectKind(static_cast<unsigned>(o)), 115 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) { 116 assert(getKind() == k && "not enough bits for the kind"); 117 assert(getObjKind() == o && "not enough bits for the object kind"); 118 assert(getIvarAccessHistory() == IvarAccess && "not enough bits"); 119 } 120 121 public: 122 Kind getKind() const { return static_cast<Kind>(RawKind); } 123 124 RetEffect::ObjKind getObjKind() const { 125 return static_cast<RetEffect::ObjKind>(RawObjectKind); 126 } 127 128 unsigned getCount() const { return Cnt; } 129 unsigned getAutoreleaseCount() const { return ACnt; } 130 unsigned getCombinedCounts() const { return Cnt + ACnt; } 131 void clearCounts() { 132 Cnt = 0; 133 ACnt = 0; 134 } 135 void setCount(unsigned i) { 136 Cnt = i; 137 } 138 void setAutoreleaseCount(unsigned i) { 139 ACnt = i; 140 } 141 142 QualType getType() const { return T; } 143 144 /// Returns what the analyzer knows about direct accesses to a particular 145 /// instance variable. 146 /// 147 /// If the object with this refcount wasn't originally from an Objective-C 148 /// ivar region, this should always return IvarAccessHistory::None. 149 IvarAccessHistory getIvarAccessHistory() const { 150 return static_cast<IvarAccessHistory>(RawIvarAccessHistory); 151 } 152 153 bool isOwned() const { 154 return getKind() == Owned; 155 } 156 157 bool isNotOwned() const { 158 return getKind() == NotOwned; 159 } 160 161 bool isReturnedOwned() const { 162 return getKind() == ReturnedOwned; 163 } 164 165 bool isReturnedNotOwned() const { 166 return getKind() == ReturnedNotOwned; 167 } 168 169 /// Create a state for an object whose lifetime is the responsibility of the 170 /// current function, at least partially. 171 /// 172 /// Most commonly, this is an owned object with a retain count of +1. 173 static RefVal makeOwned(RetEffect::ObjKind o, QualType t) { 174 return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None); 175 } 176 177 /// Create a state for an object whose lifetime is not the responsibility of 178 /// the current function. 179 /// 180 /// Most commonly, this is an unowned object with a retain count of +0. 181 static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t) { 182 return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None); 183 } 184 185 RefVal operator-(size_t i) const { 186 return RefVal(getKind(), getObjKind(), getCount() - i, 187 getAutoreleaseCount(), getType(), getIvarAccessHistory()); 188 } 189 190 RefVal operator+(size_t i) const { 191 return RefVal(getKind(), getObjKind(), getCount() + i, 192 getAutoreleaseCount(), getType(), getIvarAccessHistory()); 193 } 194 195 RefVal operator^(Kind k) const { 196 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(), 197 getType(), getIvarAccessHistory()); 198 } 199 200 RefVal autorelease() const { 201 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1, 202 getType(), getIvarAccessHistory()); 203 } 204 205 RefVal withIvarAccess() const { 206 assert(getIvarAccessHistory() == IvarAccessHistory::None); 207 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(), 208 getType(), IvarAccessHistory::AccessedDirectly); 209 } 210 211 RefVal releaseViaIvar() const { 212 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly); 213 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(), 214 getType(), IvarAccessHistory::ReleasedAfterDirectAccess); 215 } 216 217 // Comparison, profiling, and pretty-printing. 218 bool hasSameState(const RefVal &X) const { 219 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt && 220 getIvarAccessHistory() == X.getIvarAccessHistory(); 221 } 222 223 bool operator==(const RefVal& X) const { 224 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind(); 225 } 226 227 void Profile(llvm::FoldingSetNodeID& ID) const { 228 ID.Add(T); 229 ID.AddInteger(RawKind); 230 ID.AddInteger(Cnt); 231 ID.AddInteger(ACnt); 232 ID.AddInteger(RawObjectKind); 233 ID.AddInteger(RawIvarAccessHistory); 234 } 235 236 void print(raw_ostream &Out) const; 237 }; 238 239 class RetainCountChecker 240 : public Checker< check::Bind, 241 check::DeadSymbols, 242 check::EndAnalysis, 243 check::BeginFunction, 244 check::EndFunction, 245 check::PostStmt<BlockExpr>, 246 check::PostStmt<CastExpr>, 247 check::PostStmt<ObjCArrayLiteral>, 248 check::PostStmt<ObjCDictionaryLiteral>, 249 check::PostStmt<ObjCBoxedExpr>, 250 check::PostStmt<ObjCIvarRefExpr>, 251 check::PostCall, 252 check::RegionChanges, 253 eval::Assume, 254 eval::Call > { 255 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned; 256 mutable std::unique_ptr<CFRefBug> deallocNotOwned; 257 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned; 258 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn; 259 260 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap; 261 262 // This map is only used to ensure proper deletion of any allocated tags. 263 mutable SymbolTagMap DeadSymbolTags; 264 265 mutable std::unique_ptr<RetainSummaryManager> Summaries; 266 mutable SummaryLogTy SummaryLog; 267 268 mutable bool ShouldResetSummaryLog; 269 270 public: 271 272 /// Track Objective-C and CoreFoundation objects. 273 bool TrackObjCAndCFObjects = false; 274 275 /// Track sublcasses of OSObject. 276 bool TrackOSObjects = false; 277 278 RetainCountChecker() : ShouldResetSummaryLog(false) {} 279 280 ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); } 281 282 void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR, 283 ExprEngine &Eng) const; 284 285 CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts) const; 286 287 CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts) const; 288 289 RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const { 290 // FIXME: We don't support ARC being turned on and off during one analysis. 291 // (nor, for that matter, do we support changing ASTContexts) 292 bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount; 293 if (!Summaries) { 294 Summaries.reset(new RetainSummaryManager( 295 Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects)); 296 } else { 297 assert(Summaries->isARCEnabled() == ARCEnabled); 298 } 299 return *Summaries; 300 } 301 302 RetainSummaryManager &getSummaryManager(CheckerContext &C) const { 303 return getSummaryManager(C.getASTContext()); 304 } 305 306 void printState(raw_ostream &Out, ProgramStateRef State, 307 const char *NL, const char *Sep) const override; 308 309 void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const; 310 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; 311 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const; 312 313 void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const; 314 void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const; 315 void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const; 316 317 void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const; 318 319 void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 320 321 void checkSummary(const RetainSummary &Summ, const CallEvent &Call, 322 CheckerContext &C) const; 323 324 void processSummaryOfInlined(const RetainSummary &Summ, 325 const CallEvent &Call, 326 CheckerContext &C) const; 327 328 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 329 330 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, 331 bool Assumption) const; 332 333 ProgramStateRef 334 checkRegionChanges(ProgramStateRef state, 335 const InvalidatedSymbols *invalidated, 336 ArrayRef<const MemRegion *> ExplicitRegions, 337 ArrayRef<const MemRegion *> Regions, 338 const LocationContext* LCtx, 339 const CallEvent *Call) const; 340 341 ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C, 342 ExplodedNode *Pred, RetEffect RE, RefVal X, 343 SymbolRef Sym, ProgramStateRef state) const; 344 345 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 346 void checkBeginFunction(CheckerContext &C) const; 347 void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; 348 349 ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, 350 RefVal V, ArgEffect E, RefVal::Kind &hasErr, 351 CheckerContext &C) const; 352 353 void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange, 354 RefVal::Kind ErrorKind, SymbolRef Sym, 355 CheckerContext &C) const; 356 357 void processObjCLiterals(CheckerContext &C, const Expr *Ex) const; 358 359 const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const; 360 361 ProgramStateRef handleSymbolDeath(ProgramStateRef state, 362 SymbolRef sid, RefVal V, 363 SmallVectorImpl<SymbolRef> &Leaked) const; 364 365 ProgramStateRef 366 handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, 367 const ProgramPointTag *Tag, CheckerContext &Ctx, 368 SymbolRef Sym, 369 RefVal V, 370 const ReturnStmt *S=nullptr) const; 371 372 ExplodedNode *processLeaks(ProgramStateRef state, 373 SmallVectorImpl<SymbolRef> &Leaked, 374 CheckerContext &Ctx, 375 ExplodedNode *Pred = nullptr) const; 376 377 private: 378 /// Perform the necessary checks and state adjustments at the end of the 379 /// function. 380 /// \p S Return statement, may be null. 381 ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const; 382 }; 383 384 //===----------------------------------------------------------------------===// 385 // RefBindings - State used to track object reference counts. 386 //===----------------------------------------------------------------------===// 387 388 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym); 389 390 ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, 391 RefVal Val); 392 393 ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym); 394 395 /// Returns true if this stack frame is for an Objective-C method that is a 396 /// property getter or setter whose body has been synthesized by the analyzer. 397 inline bool isSynthesizedAccessor(const StackFrameContext *SFC) { 398 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl()); 399 if (!Method || !Method->isPropertyAccessor()) 400 return false; 401 402 return SFC->getAnalysisDeclContext()->isBodyAutosynthesized(); 403 } 404 405 } // end namespace retaincountchecker 406 } // end namespace ento 407 } // end namespace clang 408 409 #endif 410