]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / BasicObjCFoundationChecks.cpp
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 }