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