BasicObjCFoundationChecks.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. //== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- 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 BasicObjCFoundationChecks, a class that encapsulates
  11. // a set of simple checks to run on Objective-C code using Apple's Foundation
  12. // classes.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "ClangSACheckers.h"
  16. #include "clang/AST/ASTContext.h"
  17. #include "clang/AST/DeclObjC.h"
  18. #include "clang/AST/Expr.h"
  19. #include "clang/AST/ExprObjC.h"
  20. #include "clang/AST/StmtObjC.h"
  21. #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
  22. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  23. #include "clang/StaticAnalyzer/Core/Checker.h"
  24. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  25. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  26. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  27. #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
  28. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  29. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  30. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  31. #include "llvm/ADT/SmallString.h"
  32. #include "llvm/ADT/StringMap.h"
  33. #include "llvm/Support/raw_ostream.h"
  34. using namespace clang;
  35. using namespace ento;
  36. namespace {
  37. class APIMisuse : public BugType {
  38. public:
  39. APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
  40. };
  41. } // end anonymous namespace
  42. //===----------------------------------------------------------------------===//
  43. // Utility functions.
  44. //===----------------------------------------------------------------------===//
  45. static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
  46. if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
  47. return ID->getIdentifier()->getName();
  48. return StringRef();
  49. }
  50. enum FoundationClass {
  51. FC_None,
  52. FC_NSArray,
  53. FC_NSDictionary,
  54. FC_NSEnumerator,
  55. FC_NSNull,
  56. FC_NSOrderedSet,
  57. FC_NSSet,
  58. FC_NSString
  59. };
  60. static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID,
  61. bool IncludeSuperclasses = true) {
  62. static llvm::StringMap<FoundationClass> Classes;
  63. if (Classes.empty()) {
  64. Classes["NSArray"] = FC_NSArray;
  65. Classes["NSDictionary"] = FC_NSDictionary;
  66. Classes["NSEnumerator"] = FC_NSEnumerator;
  67. Classes["NSNull"] = FC_NSNull;
  68. Classes["NSOrderedSet"] = FC_NSOrderedSet;
  69. Classes["NSSet"] = FC_NSSet;
  70. Classes["NSString"] = FC_NSString;
  71. }
  72. // FIXME: Should we cache this at all?
  73. FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
  74. if (result == FC_None && IncludeSuperclasses)
  75. if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
  76. return findKnownClass(Super);
  77. return result;
  78. }
  79. //===----------------------------------------------------------------------===//
  80. // NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
  81. //===----------------------------------------------------------------------===//
  82. namespace {
  83. class NilArgChecker : public Checker<check::PreObjCMessage,
  84. check::PostStmt<ObjCDictionaryLiteral>,
  85. check::PostStmt<ObjCArrayLiteral> > {
  86. mutable OwningPtr<APIMisuse> BT;
  87. void warnIfNilExpr(const Expr *E,
  88. const char *Msg,
  89. CheckerContext &C) const;
  90. void warnIfNilArg(CheckerContext &C,
  91. const ObjCMethodCall &msg, unsigned Arg,
  92. FoundationClass Class,
  93. bool CanBeSubscript = false) const;
  94. void generateBugReport(ExplodedNode *N,
  95. StringRef Msg,
  96. SourceRange Range,
  97. const Expr *Expr,
  98. CheckerContext &C) const;
  99. public:
  100. void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  101. void checkPostStmt(const ObjCDictionaryLiteral *DL,
  102. CheckerContext &C) const;
  103. void checkPostStmt(const ObjCArrayLiteral *AL,
  104. CheckerContext &C) const;
  105. };
  106. }
  107. void NilArgChecker::warnIfNilExpr(const Expr *E,
  108. const char *Msg,
  109. CheckerContext &C) const {
  110. ProgramStateRef State = C.getState();
  111. if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
  112. if (ExplodedNode *N = C.generateSink()) {
  113. generateBugReport(N, Msg, E->getSourceRange(), E, C);
  114. }
  115. }
  116. }
  117. void NilArgChecker::warnIfNilArg(CheckerContext &C,
  118. const ObjCMethodCall &msg,
  119. unsigned int Arg,
  120. FoundationClass Class,
  121. bool CanBeSubscript) const {
  122. // Check if the argument is nil.
  123. ProgramStateRef State = C.getState();
  124. if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
  125. return;
  126. if (ExplodedNode *N = C.generateSink()) {
  127. SmallString<128> sbuf;
  128. llvm::raw_svector_ostream os(sbuf);
  129. if (CanBeSubscript && msg.getMessageKind() == OCM_Subscript) {
  130. if (Class == FC_NSArray) {
  131. os << "Array element cannot be nil";
  132. } else if (Class == FC_NSDictionary) {
  133. if (Arg == 0) {
  134. os << "Value stored into '";
  135. os << GetReceiverInterfaceName(msg) << "' cannot be nil";
  136. } else {
  137. assert(Arg == 1);
  138. os << "'"<< GetReceiverInterfaceName(msg) << "' key cannot be nil";
  139. }
  140. } else
  141. llvm_unreachable("Missing foundation class for the subscript expr");
  142. } else {
  143. if (Class == FC_NSDictionary) {
  144. if (Arg == 0)
  145. os << "Value argument ";
  146. else {
  147. assert(Arg == 1);
  148. os << "Key argument ";
  149. }
  150. os << "to '" << msg.getSelector().getAsString() << "' cannot be nil";
  151. } else {
  152. os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '"
  153. << msg.getSelector().getAsString() << "' cannot be nil";
  154. }
  155. }
  156. generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
  157. msg.getArgExpr(Arg), C);
  158. }
  159. }
  160. void NilArgChecker::generateBugReport(ExplodedNode *N,
  161. StringRef Msg,
  162. SourceRange Range,
  163. const Expr *E,
  164. CheckerContext &C) const {
  165. if (!BT)
  166. BT.reset(new APIMisuse("nil argument"));
  167. BugReport *R = new BugReport(*BT, Msg, N);
  168. R->addRange(Range);
  169. bugreporter::trackNullOrUndefValue(N, E, *R);
  170. C.emitReport(R);
  171. }
  172. void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
  173. CheckerContext &C) const {
  174. const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
  175. if (!ID)
  176. return;
  177. FoundationClass Class = findKnownClass(ID);
  178. static const unsigned InvalidArgIndex = UINT_MAX;
  179. unsigned Arg = InvalidArgIndex;
  180. bool CanBeSubscript = false;
  181. if (Class == FC_NSString) {
  182. Selector S = msg.getSelector();
  183. if (S.isUnarySelector())
  184. return;
  185. // FIXME: This is going to be really slow doing these checks with
  186. // lexical comparisons.
  187. std::string NameStr = S.getAsString();
  188. StringRef Name(NameStr);
  189. assert(!Name.empty());
  190. // FIXME: Checking for initWithFormat: will not work in most cases
  191. // yet because [NSString alloc] returns id, not NSString*. We will
  192. // need support for tracking expected-type information in the analyzer
  193. // to find these errors.
  194. if (Name == "caseInsensitiveCompare:" ||
  195. Name == "compare:" ||
  196. Name == "compare:options:" ||
  197. Name == "compare:options:range:" ||
  198. Name == "compare:options:range:locale:" ||
  199. Name == "componentsSeparatedByCharactersInSet:" ||
  200. Name == "initWithFormat:") {
  201. Arg = 0;
  202. }
  203. } else if (Class == FC_NSArray) {
  204. Selector S = msg.getSelector();
  205. if (S.isUnarySelector())
  206. return;
  207. if (S.getNameForSlot(0).equals("addObject")) {
  208. Arg = 0;
  209. } else if (S.getNameForSlot(0).equals("insertObject") &&
  210. S.getNameForSlot(1).equals("atIndex")) {
  211. Arg = 0;
  212. } else if (S.getNameForSlot(0).equals("replaceObjectAtIndex") &&
  213. S.getNameForSlot(1).equals("withObject")) {
  214. Arg = 1;
  215. } else if (S.getNameForSlot(0).equals("setObject") &&
  216. S.getNameForSlot(1).equals("atIndexedSubscript")) {
  217. Arg = 0;
  218. CanBeSubscript = true;
  219. } else if (S.getNameForSlot(0).equals("arrayByAddingObject")) {
  220. Arg = 0;
  221. }
  222. } else if (Class == FC_NSDictionary) {
  223. Selector S = msg.getSelector();
  224. if (S.isUnarySelector())
  225. return;
  226. if (S.getNameForSlot(0).equals("dictionaryWithObject") &&
  227. S.getNameForSlot(1).equals("forKey")) {
  228. Arg = 0;
  229. warnIfNilArg(C, msg, /* Arg */1, Class);
  230. } else if (S.getNameForSlot(0).equals("setObject") &&
  231. S.getNameForSlot(1).equals("forKey")) {
  232. Arg = 0;
  233. warnIfNilArg(C, msg, /* Arg */1, Class);
  234. } else if (S.getNameForSlot(0).equals("setObject") &&
  235. S.getNameForSlot(1).equals("forKeyedSubscript")) {
  236. CanBeSubscript = true;
  237. Arg = 0;
  238. warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
  239. } else if (S.getNameForSlot(0).equals("removeObjectForKey")) {
  240. Arg = 0;
  241. }
  242. }
  243. // If argument is '0', report a warning.
  244. if ((Arg != InvalidArgIndex))
  245. warnIfNilArg(C, msg, Arg, Class, CanBeSubscript);
  246. }
  247. void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
  248. CheckerContext &C) const {
  249. unsigned NumOfElements = AL->getNumElements();
  250. for (unsigned i = 0; i < NumOfElements; ++i) {
  251. warnIfNilExpr(AL->getElement(i), "Array element cannot be nil", C);
  252. }
  253. }
  254. void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
  255. CheckerContext &C) const {
  256. unsigned NumOfElements = DL->getNumElements();
  257. for (unsigned i = 0; i < NumOfElements; ++i) {
  258. ObjCDictionaryElement Element = DL->getKeyValueElement(i);
  259. warnIfNilExpr(Element.Key, "Dictionary key cannot be nil", C);
  260. warnIfNilExpr(Element.Value, "Dictionary value cannot be nil", C);
  261. }
  262. }
  263. //===----------------------------------------------------------------------===//
  264. // Error reporting.
  265. //===----------------------------------------------------------------------===//
  266. namespace {
  267. class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
  268. mutable OwningPtr<APIMisuse> BT;
  269. mutable IdentifierInfo* II;
  270. public:
  271. CFNumberCreateChecker() : II(0) {}
  272. void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  273. private:
  274. void EmitError(const TypedRegion* R, const Expr *Ex,
  275. uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
  276. };
  277. } // end anonymous namespace
  278. enum CFNumberType {
  279. kCFNumberSInt8Type = 1,
  280. kCFNumberSInt16Type = 2,
  281. kCFNumberSInt32Type = 3,
  282. kCFNumberSInt64Type = 4,
  283. kCFNumberFloat32Type = 5,
  284. kCFNumberFloat64Type = 6,
  285. kCFNumberCharType = 7,
  286. kCFNumberShortType = 8,
  287. kCFNumberIntType = 9,
  288. kCFNumberLongType = 10,
  289. kCFNumberLongLongType = 11,
  290. kCFNumberFloatType = 12,
  291. kCFNumberDoubleType = 13,
  292. kCFNumberCFIndexType = 14,
  293. kCFNumberNSIntegerType = 15,
  294. kCFNumberCGFloatType = 16
  295. };
  296. static Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) {
  297. static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
  298. if (i < kCFNumberCharType)
  299. return FixedSize[i-1];
  300. QualType T;
  301. switch (i) {
  302. case kCFNumberCharType: T = Ctx.CharTy; break;
  303. case kCFNumberShortType: T = Ctx.ShortTy; break;
  304. case kCFNumberIntType: T = Ctx.IntTy; break;
  305. case kCFNumberLongType: T = Ctx.LongTy; break;
  306. case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
  307. case kCFNumberFloatType: T = Ctx.FloatTy; break;
  308. case kCFNumberDoubleType: T = Ctx.DoubleTy; break;
  309. case kCFNumberCFIndexType:
  310. case kCFNumberNSIntegerType:
  311. case kCFNumberCGFloatType:
  312. // FIXME: We need a way to map from names to Type*.
  313. default:
  314. return None;
  315. }
  316. return Ctx.getTypeSize(T);
  317. }
  318. #if 0
  319. static const char* GetCFNumberTypeStr(uint64_t i) {
  320. static const char* Names[] = {
  321. "kCFNumberSInt8Type",
  322. "kCFNumberSInt16Type",
  323. "kCFNumberSInt32Type",
  324. "kCFNumberSInt64Type",
  325. "kCFNumberFloat32Type",
  326. "kCFNumberFloat64Type",
  327. "kCFNumberCharType",
  328. "kCFNumberShortType",
  329. "kCFNumberIntType",
  330. "kCFNumberLongType",
  331. "kCFNumberLongLongType",
  332. "kCFNumberFloatType",
  333. "kCFNumberDoubleType",
  334. "kCFNumberCFIndexType",
  335. "kCFNumberNSIntegerType",
  336. "kCFNumberCGFloatType"
  337. };
  338. return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
  339. }
  340. #endif
  341. void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
  342. CheckerContext &C) const {
  343. ProgramStateRef state = C.getState();
  344. const FunctionDecl *FD = C.getCalleeDecl(CE);
  345. if (!FD)
  346. return;
  347. ASTContext &Ctx = C.getASTContext();
  348. if (!II)
  349. II = &Ctx.Idents.get("CFNumberCreate");
  350. if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
  351. return;
  352. // Get the value of the "theType" argument.
  353. const LocationContext *LCtx = C.getLocationContext();
  354. SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
  355. // FIXME: We really should allow ranges of valid theType values, and
  356. // bifurcate the state appropriately.
  357. Optional<nonloc::ConcreteInt> V = TheTypeVal.getAs<nonloc::ConcreteInt>();
  358. if (!V)
  359. return;
  360. uint64_t NumberKind = V->getValue().getLimitedValue();
  361. Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
  362. // FIXME: In some cases we can emit an error.
  363. if (!OptTargetSize)
  364. return;
  365. uint64_t TargetSize = *OptTargetSize;
  366. // Look at the value of the integer being passed by reference. Essentially
  367. // we want to catch cases where the value passed in is not equal to the
  368. // size of the type being created.
  369. SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
  370. // FIXME: Eventually we should handle arbitrary locations. We can do this
  371. // by having an enhanced memory model that does low-level typing.
  372. Optional<loc::MemRegionVal> LV = TheValueExpr.getAs<loc::MemRegionVal>();
  373. if (!LV)
  374. return;
  375. const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
  376. if (!R)
  377. return;
  378. QualType T = Ctx.getCanonicalType(R->getValueType());
  379. // FIXME: If the pointee isn't an integer type, should we flag a warning?
  380. // People can do weird stuff with pointers.
  381. if (!T->isIntegralOrEnumerationType())
  382. return;
  383. uint64_t SourceSize = Ctx.getTypeSize(T);
  384. // CHECK: is SourceSize == TargetSize
  385. if (SourceSize == TargetSize)
  386. return;
  387. // Generate an error. Only generate a sink if 'SourceSize < TargetSize';
  388. // otherwise generate a regular node.
  389. //
  390. // FIXME: We can actually create an abstract "CFNumber" object that has
  391. // the bits initialized to the provided values.
  392. //
  393. if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
  394. : C.addTransition()) {
  395. SmallString<128> sbuf;
  396. llvm::raw_svector_ostream os(sbuf);
  397. os << (SourceSize == 8 ? "An " : "A ")
  398. << SourceSize << " bit integer is used to initialize a CFNumber "
  399. "object that represents "
  400. << (TargetSize == 8 ? "an " : "a ")
  401. << TargetSize << " bit integer. ";
  402. if (SourceSize < TargetSize)
  403. os << (TargetSize - SourceSize)
  404. << " bits of the CFNumber value will be garbage." ;
  405. else
  406. os << (SourceSize - TargetSize)
  407. << " bits of the input integer will be lost.";
  408. if (!BT)
  409. BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
  410. BugReport *report = new BugReport(*BT, os.str(), N);
  411. report->addRange(CE->getArg(2)->getSourceRange());
  412. C.emitReport(report);
  413. }
  414. }
  415. //===----------------------------------------------------------------------===//
  416. // CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
  417. //===----------------------------------------------------------------------===//
  418. namespace {
  419. class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
  420. mutable OwningPtr<APIMisuse> BT;
  421. mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
  422. public:
  423. CFRetainReleaseChecker(): Retain(0), Release(0), MakeCollectable(0) {}
  424. void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  425. };
  426. } // end anonymous namespace
  427. void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
  428. CheckerContext &C) const {
  429. // If the CallExpr doesn't have exactly 1 argument just give up checking.
  430. if (CE->getNumArgs() != 1)
  431. return;
  432. ProgramStateRef state = C.getState();
  433. const FunctionDecl *FD = C.getCalleeDecl(CE);
  434. if (!FD)
  435. return;
  436. if (!BT) {
  437. ASTContext &Ctx = C.getASTContext();
  438. Retain = &Ctx.Idents.get("CFRetain");
  439. Release = &Ctx.Idents.get("CFRelease");
  440. MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
  441. BT.reset(
  442. new APIMisuse("null passed to CFRetain/CFRelease/CFMakeCollectable"));
  443. }
  444. // Check if we called CFRetain/CFRelease/CFMakeCollectable.
  445. const IdentifierInfo *FuncII = FD->getIdentifier();
  446. if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
  447. return;
  448. // FIXME: The rest of this just checks that the argument is non-null.
  449. // It should probably be refactored and combined with NonNullParamChecker.
  450. // Get the argument's value.
  451. const Expr *Arg = CE->getArg(0);
  452. SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
  453. Optional<DefinedSVal> DefArgVal = ArgVal.getAs<DefinedSVal>();
  454. if (!DefArgVal)
  455. return;
  456. // Get a NULL value.
  457. SValBuilder &svalBuilder = C.getSValBuilder();
  458. DefinedSVal zero =
  459. svalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
  460. // Make an expression asserting that they're equal.
  461. DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
  462. // Are they equal?
  463. ProgramStateRef stateTrue, stateFalse;
  464. llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
  465. if (stateTrue && !stateFalse) {
  466. ExplodedNode *N = C.generateSink(stateTrue);
  467. if (!N)
  468. return;
  469. const char *description;
  470. if (FuncII == Retain)
  471. description = "Null pointer argument in call to CFRetain";
  472. else if (FuncII == Release)
  473. description = "Null pointer argument in call to CFRelease";
  474. else if (FuncII == MakeCollectable)
  475. description = "Null pointer argument in call to CFMakeCollectable";
  476. else
  477. llvm_unreachable("impossible case");
  478. BugReport *report = new BugReport(*BT, description, N);
  479. report->addRange(Arg->getSourceRange());
  480. bugreporter::trackNullOrUndefValue(N, Arg, *report);
  481. C.emitReport(report);
  482. return;
  483. }
  484. // From here on, we know the argument is non-null.
  485. C.addTransition(stateFalse);
  486. }
  487. //===----------------------------------------------------------------------===//
  488. // Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
  489. //===----------------------------------------------------------------------===//
  490. namespace {
  491. class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
  492. mutable Selector releaseS;
  493. mutable Selector retainS;
  494. mutable Selector autoreleaseS;
  495. mutable Selector drainS;
  496. mutable OwningPtr<BugType> BT;
  497. public:
  498. void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
  499. };
  500. }
  501. void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
  502. CheckerContext &C) const {
  503. if (!BT) {
  504. BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
  505. "instance"));
  506. ASTContext &Ctx = C.getASTContext();
  507. releaseS = GetNullarySelector("release", Ctx);
  508. retainS = GetNullarySelector("retain", Ctx);
  509. autoreleaseS = GetNullarySelector("autorelease", Ctx);
  510. drainS = GetNullarySelector("drain", Ctx);
  511. }
  512. if (msg.isInstanceMessage())
  513. return;
  514. const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
  515. assert(Class);
  516. Selector S = msg.getSelector();
  517. if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
  518. return;
  519. if (ExplodedNode *N = C.addTransition()) {
  520. SmallString<200> buf;
  521. llvm::raw_svector_ostream os(buf);
  522. os << "The '" << S.getAsString() << "' message should be sent to instances "
  523. "of class '" << Class->getName()
  524. << "' and not the class directly";
  525. BugReport *report = new BugReport(*BT, os.str(), N);
  526. report->addRange(msg.getSourceRange());
  527. C.emitReport(report);
  528. }
  529. }
  530. //===----------------------------------------------------------------------===//
  531. // Check for passing non-Objective-C types to variadic methods that expect
  532. // only Objective-C types.
  533. //===----------------------------------------------------------------------===//
  534. namespace {
  535. class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
  536. mutable Selector arrayWithObjectsS;
  537. mutable Selector dictionaryWithObjectsAndKeysS;
  538. mutable Selector setWithObjectsS;
  539. mutable Selector orderedSetWithObjectsS;
  540. mutable Selector initWithObjectsS;
  541. mutable Selector initWithObjectsAndKeysS;
  542. mutable OwningPtr<BugType> BT;
  543. bool isVariadicMessage(const ObjCMethodCall &msg) const;
  544. public:
  545. void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
  546. };
  547. }
  548. /// isVariadicMessage - Returns whether the given message is a variadic message,
  549. /// where all arguments must be Objective-C types.
  550. bool
  551. VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
  552. const ObjCMethodDecl *MD = msg.getDecl();
  553. if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
  554. return false;
  555. Selector S = msg.getSelector();
  556. if (msg.isInstanceMessage()) {
  557. // FIXME: Ideally we'd look at the receiver interface here, but that's not
  558. // useful for init, because alloc returns 'id'. In theory, this could lead
  559. // to false positives, for example if there existed a class that had an
  560. // initWithObjects: implementation that does accept non-Objective-C pointer
  561. // types, but the chance of that happening is pretty small compared to the
  562. // gains that this analysis gives.
  563. const ObjCInterfaceDecl *Class = MD->getClassInterface();
  564. switch (findKnownClass(Class)) {
  565. case FC_NSArray:
  566. case FC_NSOrderedSet:
  567. case FC_NSSet:
  568. return S == initWithObjectsS;
  569. case FC_NSDictionary:
  570. return S == initWithObjectsAndKeysS;
  571. default:
  572. return false;
  573. }
  574. } else {
  575. const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
  576. switch (findKnownClass(Class)) {
  577. case FC_NSArray:
  578. return S == arrayWithObjectsS;
  579. case FC_NSOrderedSet:
  580. return S == orderedSetWithObjectsS;
  581. case FC_NSSet:
  582. return S == setWithObjectsS;
  583. case FC_NSDictionary:
  584. return S == dictionaryWithObjectsAndKeysS;
  585. default:
  586. return false;
  587. }
  588. }
  589. }
  590. void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
  591. CheckerContext &C) const {
  592. if (!BT) {
  593. BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
  594. "Objective-C pointer types"));
  595. ASTContext &Ctx = C.getASTContext();
  596. arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
  597. dictionaryWithObjectsAndKeysS =
  598. GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
  599. setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
  600. orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
  601. initWithObjectsS = GetUnarySelector("initWithObjects", Ctx);
  602. initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx);
  603. }
  604. if (!isVariadicMessage(msg))
  605. return;
  606. // We are not interested in the selector arguments since they have
  607. // well-defined types, so the compiler will issue a warning for them.
  608. unsigned variadicArgsBegin = msg.getSelector().getNumArgs();
  609. // We're not interested in the last argument since it has to be nil or the
  610. // compiler would have issued a warning for it elsewhere.
  611. unsigned variadicArgsEnd = msg.getNumArgs() - 1;
  612. if (variadicArgsEnd <= variadicArgsBegin)
  613. return;
  614. // Verify that all arguments have Objective-C types.
  615. Optional<ExplodedNode*> errorNode;
  616. ProgramStateRef state = C.getState();
  617. for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
  618. QualType ArgTy = msg.getArgExpr(I)->getType();
  619. if (ArgTy->isObjCObjectPointerType())
  620. continue;
  621. // Block pointers are treaded as Objective-C pointers.
  622. if (ArgTy->isBlockPointerType())
  623. continue;
  624. // Ignore pointer constants.
  625. if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
  626. continue;
  627. // Ignore pointer types annotated with 'NSObject' attribute.
  628. if (C.getASTContext().isObjCNSObjectType(ArgTy))
  629. continue;
  630. // Ignore CF references, which can be toll-free bridged.
  631. if (coreFoundation::isCFObjectRef(ArgTy))
  632. continue;
  633. // Generate only one error node to use for all bug reports.
  634. if (!errorNode.hasValue())
  635. errorNode = C.addTransition();
  636. if (!errorNode.getValue())
  637. continue;
  638. SmallString<128> sbuf;
  639. llvm::raw_svector_ostream os(sbuf);
  640. StringRef TypeName = GetReceiverInterfaceName(msg);
  641. if (!TypeName.empty())
  642. os << "Argument to '" << TypeName << "' method '";
  643. else
  644. os << "Argument to method '";
  645. os << msg.getSelector().getAsString()
  646. << "' should be an Objective-C pointer type, not '";
  647. ArgTy.print(os, C.getLangOpts());
  648. os << "'";
  649. BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
  650. R->addRange(msg.getArgSourceRange(I));
  651. C.emitReport(R);
  652. }
  653. }
  654. //===----------------------------------------------------------------------===//
  655. // Improves the modeling of loops over Cocoa collections.
  656. //===----------------------------------------------------------------------===//
  657. // The map from container symbol to the container count symbol.
  658. // We currently will remember the last countainer count symbol encountered.
  659. REGISTER_MAP_WITH_PROGRAMSTATE(ContainerCountMap, SymbolRef, SymbolRef)
  660. REGISTER_MAP_WITH_PROGRAMSTATE(ContainerNonEmptyMap, SymbolRef, bool)
  661. namespace {
  662. class ObjCLoopChecker
  663. : public Checker<check::PostStmt<ObjCForCollectionStmt>,
  664. check::PostObjCMessage,
  665. check::DeadSymbols,
  666. check::PointerEscape > {
  667. mutable IdentifierInfo *CountSelectorII;
  668. bool isCollectionCountMethod(const ObjCMethodCall &M,
  669. CheckerContext &C) const;
  670. public:
  671. ObjCLoopChecker() : CountSelectorII(0) {}
  672. void checkPostStmt(const ObjCForCollectionStmt *FCS, CheckerContext &C) const;
  673. void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  674. void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
  675. ProgramStateRef checkPointerEscape(ProgramStateRef State,
  676. const InvalidatedSymbols &Escaped,
  677. const CallEvent *Call,
  678. PointerEscapeKind Kind) const;
  679. };
  680. }
  681. static bool isKnownNonNilCollectionType(QualType T) {
  682. const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
  683. if (!PT)
  684. return false;
  685. const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
  686. if (!ID)
  687. return false;
  688. switch (findKnownClass(ID)) {
  689. case FC_NSArray:
  690. case FC_NSDictionary:
  691. case FC_NSEnumerator:
  692. case FC_NSOrderedSet:
  693. case FC_NSSet:
  694. return true;
  695. default:
  696. return false;
  697. }
  698. }
  699. /// Assumes that the collection is non-nil.
  700. ///
  701. /// If the collection is known to be nil, returns NULL to indicate an infeasible
  702. /// path.
  703. static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
  704. ProgramStateRef State,
  705. const ObjCForCollectionStmt *FCS) {
  706. if (!State)
  707. return NULL;
  708. SVal CollectionVal = C.getSVal(FCS->getCollection());
  709. Optional<DefinedSVal> KnownCollection = CollectionVal.getAs<DefinedSVal>();
  710. if (!KnownCollection)
  711. return State;
  712. ProgramStateRef StNonNil, StNil;
  713. llvm::tie(StNonNil, StNil) = State->assume(*KnownCollection);
  714. if (StNil && !StNonNil) {
  715. // The collection is nil. This path is infeasible.
  716. return NULL;
  717. }
  718. return StNonNil;
  719. }
  720. /// Assumes that the collection elements are non-nil.
  721. ///
  722. /// This only applies if the collection is one of those known not to contain
  723. /// nil values.
  724. static ProgramStateRef checkElementNonNil(CheckerContext &C,
  725. ProgramStateRef State,
  726. const ObjCForCollectionStmt *FCS) {
  727. if (!State)
  728. return NULL;
  729. // See if the collection is one where we /know/ the elements are non-nil.
  730. if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
  731. return State;
  732. const LocationContext *LCtx = C.getLocationContext();
  733. const Stmt *Element = FCS->getElement();
  734. // FIXME: Copied from ExprEngineObjC.
  735. Optional<Loc> ElementLoc;
  736. if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
  737. const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
  738. assert(ElemDecl->getInit() == 0);
  739. ElementLoc = State->getLValue(ElemDecl, LCtx);
  740. } else {
  741. ElementLoc = State->getSVal(Element, LCtx).getAs<Loc>();
  742. }
  743. if (!ElementLoc)
  744. return State;
  745. // Go ahead and assume the value is non-nil.
  746. SVal Val = State->getSVal(*ElementLoc);
  747. return State->assume(Val.castAs<DefinedOrUnknownSVal>(), true);
  748. }
  749. /// Returns NULL state if the collection is known to contain elements
  750. /// (or is known not to contain elements if the Assumption parameter is false.)
  751. static ProgramStateRef
  752. assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
  753. SymbolRef CollectionS, bool Assumption) {
  754. if (!State || !CollectionS)
  755. return State;
  756. const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
  757. if (!CountS) {
  758. const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
  759. if (!KnownNonEmpty)
  760. return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
  761. return (Assumption == *KnownNonEmpty) ? State : NULL;
  762. }
  763. SValBuilder &SvalBuilder = C.getSValBuilder();
  764. SVal CountGreaterThanZeroVal =
  765. SvalBuilder.evalBinOp(State, BO_GT,
  766. nonloc::SymbolVal(*CountS),
  767. SvalBuilder.makeIntVal(0, (*CountS)->getType()),
  768. SvalBuilder.getConditionType());
  769. Optional<DefinedSVal> CountGreaterThanZero =
  770. CountGreaterThanZeroVal.getAs<DefinedSVal>();
  771. if (!CountGreaterThanZero) {
  772. // The SValBuilder cannot construct a valid SVal for this condition.
  773. // This means we cannot properly reason about it.
  774. return State;
  775. }
  776. return State->assume(*CountGreaterThanZero, Assumption);
  777. }
  778. static ProgramStateRef
  779. assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
  780. const ObjCForCollectionStmt *FCS,
  781. bool Assumption) {
  782. if (!State)
  783. return NULL;
  784. SymbolRef CollectionS =
  785. State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
  786. return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
  787. }
  788. /// If the fist block edge is a back edge, we are reentering the loop.
  789. static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
  790. const ObjCForCollectionStmt *FCS) {
  791. if (!N)
  792. return false;
  793. ProgramPoint P = N->getLocation();
  794. if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
  795. if (BE->getSrc()->getLoopTarget() == FCS)
  796. return true;
  797. return false;
  798. }
  799. // Keep looking for a block edge.
  800. for (ExplodedNode::const_pred_iterator I = N->pred_begin(),
  801. E = N->pred_end(); I != E; ++I) {
  802. if (alreadyExecutedAtLeastOneLoopIteration(*I, FCS))
  803. return true;
  804. }
  805. return false;
  806. }
  807. void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
  808. CheckerContext &C) const {
  809. ProgramStateRef State = C.getState();
  810. // Check if this is the branch for the end of the loop.
  811. SVal CollectionSentinel = C.getSVal(FCS);
  812. if (CollectionSentinel.isZeroConstant()) {
  813. if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
  814. State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);
  815. // Otherwise, this is a branch that goes through the loop body.
  816. } else {
  817. State = checkCollectionNonNil(C, State, FCS);
  818. State = checkElementNonNil(C, State, FCS);
  819. State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
  820. }
  821. if (!State)
  822. C.generateSink();
  823. else if (State != C.getState())
  824. C.addTransition(State);
  825. }
  826. bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
  827. CheckerContext &C) const {
  828. Selector S = M.getSelector();
  829. // Initialize the identifiers on first use.
  830. if (!CountSelectorII)
  831. CountSelectorII = &C.getASTContext().Idents.get("count");
  832. // If the method returns collection count, record the value.
  833. if (S.isUnarySelector() &&
  834. (S.getIdentifierInfoForSlot(0) == CountSelectorII))
  835. return true;
  836. return false;
  837. }
  838. void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
  839. CheckerContext &C) const {
  840. if (!M.isInstanceMessage())
  841. return;
  842. const ObjCInterfaceDecl *ClassID = M.getReceiverInterface();
  843. if (!ClassID)
  844. return;
  845. FoundationClass Class = findKnownClass(ClassID);
  846. if (Class != FC_NSDictionary &&
  847. Class != FC_NSArray &&
  848. Class != FC_NSSet &&
  849. Class != FC_NSOrderedSet)
  850. return;
  851. SymbolRef ContainerS = M.getReceiverSVal().getAsSymbol();
  852. if (!ContainerS)
  853. return;
  854. // If we are processing a call to "count", get the symbolic value returned by
  855. // a call to "count" and add it to the map.
  856. if (!isCollectionCountMethod(M, C))
  857. return;
  858. const Expr *MsgExpr = M.getOriginExpr();
  859. SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
  860. if (CountS) {
  861. ProgramStateRef State = C.getState();
  862. C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
  863. State = State->set<ContainerCountMap>(ContainerS, CountS);
  864. if (const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
  865. State = State->remove<ContainerNonEmptyMap>(ContainerS);
  866. State = assumeCollectionNonEmpty(C, State, ContainerS, *NonEmpty);
  867. }
  868. C.addTransition(State);
  869. }
  870. return;
  871. }
  872. static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) {
  873. const ObjCMethodCall *Message = dyn_cast_or_null<ObjCMethodCall>(Call);
  874. if (!Message)
  875. return 0;
  876. const ObjCMethodDecl *MD = Message->getDecl();
  877. if (!MD)
  878. return 0;
  879. const ObjCInterfaceDecl *StaticClass;
  880. if (isa<ObjCProtocolDecl>(MD->getDeclContext())) {
  881. // We can't find out where the method was declared without doing more work.
  882. // Instead, see if the receiver is statically typed as a known immutable
  883. // collection.
  884. StaticClass = Message->getOriginExpr()->getReceiverInterface();
  885. } else {
  886. StaticClass = MD->getClassInterface();
  887. }
  888. if (!StaticClass)
  889. return 0;
  890. switch (findKnownClass(StaticClass, /*IncludeSuper=*/false)) {
  891. case FC_None:
  892. return 0;
  893. case FC_NSArray:
  894. case FC_NSDictionary:
  895. case FC_NSEnumerator:
  896. case FC_NSNull:
  897. case FC_NSOrderedSet:
  898. case FC_NSSet:
  899. case FC_NSString:
  900. break;
  901. }
  902. return Message->getReceiverSVal().getAsSymbol();
  903. }
  904. ProgramStateRef
  905. ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
  906. const InvalidatedSymbols &Escaped,
  907. const CallEvent *Call,
  908. PointerEscapeKind Kind) const {
  909. SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call);
  910. // Remove the invalidated symbols form the collection count map.
  911. for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
  912. E = Escaped.end();
  913. I != E; ++I) {
  914. SymbolRef Sym = *I;
  915. // Don't invalidate this symbol's count if we know the method being called
  916. // is declared on an immutable class. This isn't completely correct if the
  917. // receiver is also passed as an argument, but in most uses of NSArray,
  918. // NSDictionary, etc. this isn't likely to happen in a dangerous way.
  919. if (Sym == ImmutableReceiver)
  920. continue;
  921. // The symbol escaped. Pessimistically, assume that the count could have
  922. // changed.
  923. State = State->remove<ContainerCountMap>(Sym);
  924. State = State->remove<ContainerNonEmptyMap>(Sym);
  925. }
  926. return State;
  927. }
  928. void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
  929. CheckerContext &C) const {
  930. ProgramStateRef State = C.getState();
  931. // Remove the dead symbols from the collection count map.
  932. ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
  933. for (ContainerCountMapTy::iterator I = Tracked.begin(),
  934. E = Tracked.end(); I != E; ++I) {
  935. SymbolRef Sym = I->first;
  936. if (SymReaper.isDead(Sym)) {
  937. State = State->remove<ContainerCountMap>(Sym);
  938. State = State->remove<ContainerNonEmptyMap>(Sym);
  939. }
  940. }
  941. C.addTransition(State);
  942. }
  943. namespace {
  944. /// \class ObjCNonNilReturnValueChecker
  945. /// \brief The checker restricts the return values of APIs known to
  946. /// never (or almost never) return 'nil'.
  947. class ObjCNonNilReturnValueChecker
  948. : public Checker<check::PostObjCMessage> {
  949. mutable bool Initialized;
  950. mutable Selector ObjectAtIndex;
  951. mutable Selector ObjectAtIndexedSubscript;
  952. mutable Selector NullSelector;
  953. public:
  954. ObjCNonNilReturnValueChecker() : Initialized(false) {}
  955. void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  956. };
  957. }
  958. static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
  959. ProgramStateRef State,
  960. CheckerContext &C) {
  961. SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
  962. if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
  963. return State->assume(*DV, true);
  964. return State;
  965. }
  966. void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
  967. CheckerContext &C)
  968. const {
  969. ProgramStateRef State = C.getState();
  970. if (!Initialized) {
  971. ASTContext &Ctx = C.getASTContext();
  972. ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
  973. ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
  974. NullSelector = GetNullarySelector("null", Ctx);
  975. }
  976. // Check the receiver type.
  977. if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
  978. // Assume that object returned from '[self init]' or '[super init]' is not
  979. // 'nil' if we are processing an inlined function/method.
  980. //
  981. // A defensive callee will (and should) check if the object returned by
  982. // '[super init]' is 'nil' before doing it's own initialization. However,
  983. // since 'nil' is rarely returned in practice, we should not warn when the
  984. // caller to the defensive constructor uses the object in contexts where
  985. // 'nil' is not accepted.
  986. if (!C.inTopFrame() && M.getDecl() &&
  987. M.getDecl()->getMethodFamily() == OMF_init &&
  988. M.isReceiverSelfOrSuper()) {
  989. State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
  990. }
  991. FoundationClass Cl = findKnownClass(Interface);
  992. // Objects returned from
  993. // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
  994. // are never 'nil'.
  995. if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
  996. Selector Sel = M.getSelector();
  997. if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
  998. // Go ahead and assume the value is non-nil.
  999. State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
  1000. }
  1001. }
  1002. // Objects returned from [NSNull null] are not nil.
  1003. if (Cl == FC_NSNull) {
  1004. if (M.getSelector() == NullSelector) {
  1005. // Go ahead and assume the value is non-nil.
  1006. State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
  1007. }
  1008. }
  1009. }
  1010. C.addTransition(State);
  1011. }
  1012. //===----------------------------------------------------------------------===//
  1013. // Check registration.
  1014. //===----------------------------------------------------------------------===//
  1015. void ento::registerNilArgChecker(CheckerManager &mgr) {
  1016. mgr.registerChecker<NilArgChecker>();
  1017. }
  1018. void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
  1019. mgr.registerChecker<CFNumberCreateChecker>();
  1020. }
  1021. void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
  1022. mgr.registerChecker<CFRetainReleaseChecker>();
  1023. }
  1024. void ento::registerClassReleaseChecker(CheckerManager &mgr) {
  1025. mgr.registerChecker<ClassReleaseChecker>();
  1026. }
  1027. void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
  1028. mgr.registerChecker<VariadicMethodTypeChecker>();
  1029. }
  1030. void ento::registerObjCLoopChecker(CheckerManager &mgr) {
  1031. mgr.registerChecker<ObjCLoopChecker>();
  1032. }
  1033. void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
  1034. mgr.registerChecker<ObjCNonNilReturnValueChecker>();
  1035. }