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