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