BasicObjCFoundationChecks.cpp revision 2550d70aabb5f603e8f74cc5fb6a69a7af5b51f3
199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- C++ -*--
299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//                     The LLVM Compiler Infrastructure
499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// This file is distributed under the University of Illinois Open Source
699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// License. See LICENSE.TXT for details.
799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
1099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  This file defines BasicObjCFoundationChecks, a class that encapsulates
1199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  a set of simple checks to run on Objective-C code using Apple's Foundation
1299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//  classes.
1399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//
1499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
1599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
16527556184b276c545be1355ad596fce29a0400fbTed Kremenek#include "BasicObjCFoundationChecks.h"
17527556184b276c545be1355ad596fce29a0400fbTed Kremenek
1899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
1999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
2078d46242e3351484c2b773f5610beba5d316914bTed Kremenek#include "clang/Analysis/PathSensitive/GRExprEngine.h"
214adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek#include "clang/Analysis/PathSensitive/GRState.h"
22f1ae705460552655fe7275327804444c62e86baeTed Kremenek#include "clang/Analysis/PathSensitive/BugReporter.h"
239e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek#include "clang/Analysis/PathSensitive/MemRegion.h"
2499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/Analysis/PathDiagnostic.h"
2550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
2678d46242e3351484c2b773f5610beba5d316914bTed Kremenek#include "clang/Analysis/LocalCheckers.h"
27c4a1dea2dc56bd1357ec91b829a0b9e68229a13eDaniel Dunbar#include "clang/AST/DeclObjC.h"
2899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/Expr.h"
29f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#include "clang/AST/ExprObjC.h"
3099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/ASTContext.h"
3199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekusing namespace clang;
33f1ae705460552655fe7275327804444c62e86baeTed Kremenek
3414108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffstatic const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {
3514108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  const Expr* Receiver = ME->getReceiver();
361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37f1ae705460552655fe7275327804444c62e86baeTed Kremenek  if (!Receiver)
38f1ae705460552655fe7275327804444c62e86baeTed Kremenek    return NULL;
391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4014108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  if (const ObjCObjectPointerType *PT =
41183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall      Receiver->getType()->getAs<ObjCObjectPointerType>())
4214108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff    return PT->getInterfaceType();
43c1ff3cd5fe4436bb14309fdc5ee7e1c2b702b7c3Ted Kremenek
44c1ff3cd5fe4436bb14309fdc5ee7e1c2b702b7c3Ted Kremenek  return NULL;
45f1ae705460552655fe7275327804444c62e86baeTed Kremenek}
46f1ae705460552655fe7275327804444c62e86baeTed Kremenek
4714108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffstatic const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
48e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar  if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME))
49e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar    return ReceiverType->getDecl()->getIdentifier()->getNameStart();
50e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar  return NULL;
51f1ae705460552655fe7275327804444c62e86baeTed Kremenek}
52f1ae705460552655fe7275327804444c62e86baeTed Kremenek
5399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremeneknamespace {
54b344f91f00021b88e365a4a38502090c3b0cef12Ted Kremenek
55ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass APIMisuse : public BugType {
56f1ae705460552655fe7275327804444c62e86baeTed Kremenekpublic:
57cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
58f1ae705460552655fe7275327804444c62e86baeTed Kremenek};
591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
60ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass BasicObjCFoundationChecks : public GRSimpleAPICheck {
61cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse *BT;
62cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter& BR;
63e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  ASTContext &Ctx;
641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
66031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
69031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  void WarnNilArg(ExplodedNode* N, const Expr* E);
701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
71031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  bool CheckNilArg(ExplodedNode* N, unsigned Arg);
7299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
7399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekpublic:
741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br)
7523ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek    : BT(0), BR(br), Ctx(ctx) {}
761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
77c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpprivate:
801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void WarnNilArg(ExplodedNode* N, const ObjCMessageExpr* ME, unsigned Arg) {
81cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    std::string sbuf;
82cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    llvm::raw_string_ostream os(sbuf);
83cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
84cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek       << ME->getSelector().getAsString() << "' cannot be nil.";
851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
86cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    // Lazily create the BugType object for NilArg.  This will be owned
87cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    // by the BugReporter object 'BR' once we call BR.EmitWarning.
88cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    if (!BT) BT = new APIMisuse("nil argument");
891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
904988a9a278c50fddf46d38331e4a136a91487b7dBenjamin Kramer    RangedBugReport *R = new RangedBugReport(*BT, os.str(), N);
91cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    R->addRange(ME->getArg(Arg)->getSourceRange());
92cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    BR.EmitReport(R);
93f1ae705460552655fe7275327804444c62e86baeTed Kremenek  }
9499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek} // end anonymous namespace
9799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
9899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
99527556184b276c545be1355ad596fce29a0400fbTed KremenekGRSimpleAPICheck*
10023ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenekclang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) {
1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return new BasicObjCFoundationChecks(Ctx, BR);
102527556184b276c545be1355ad596fce29a0400fbTed Kremenek}
103527556184b276c545be1355ad596fce29a0400fbTed Kremenek
1044ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
10599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
106c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xubool BasicObjCFoundationChecks::Audit(ExplodedNode* N,
1074adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek                                      GRStateManager&) {
1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1095f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const ObjCMessageExpr* ME =
1104ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1114ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
11214108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (!ReceiverType)
115f74279447d4ad0a0c0f2e6e6740d5a0f4c242e0cNuno Lopes    return false;
1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
117d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  if (isNSString(ReceiverType,
11801eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar                 ReceiverType->getDecl()->getIdentifier()->getName()))
11999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return AuditNSString(N, ME);
12099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
121f74279447d4ad0a0c0f2e6e6740d5a0f4c242e0cNuno Lopes  return false;
12299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
12399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1241c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xustatic inline bool isNil(SVal X) {
1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return isa<loc::ConcreteInt>(X);
126e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek}
127e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
12899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
12999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// Error reporting.
13099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
13199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
132031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xubool BasicObjCFoundationChecks::CheckNilArg(ExplodedNode* N, unsigned Arg) {
1335f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const ObjCMessageExpr* ME =
1344ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1365f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Expr * E = ME->getArg(Arg);
1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13823ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  if (isNil(N->getState()->getSVal(E))) {
139f1ae705460552655fe7275327804444c62e86baeTed Kremenek    WarnNilArg(N, ME, Arg);
1404ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return true;
1414ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  }
1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1434ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  return false;
1444ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
1454ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
14699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
14799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// NSString checking.
14899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
14999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
15014108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffbool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType *T,
151d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar                                           llvm::StringRef ClassName) {
152d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  return ClassName == "NSString" || ClassName == "NSMutableString";
15399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
15499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N,
1565f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek                                              const ObjCMessageExpr* ME) {
1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  Selector S = ME->getSelector();
1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (S.isUnarySelector())
16199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return false;
16299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
16399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  // FIXME: This is going to be really slow doing these checks with
16499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  //  lexical comparisons.
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
166077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  std::string name = S.getAsString();
1679b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  assert (!name.empty());
1689b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  const char* cstr = &name[0];
1699b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  unsigned len = name.size();
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1719b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  switch (len) {
1729b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek    default:
1739b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    case 8:
1754ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:"))
1764ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1784ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1808730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek    case 15:
1818730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      // FIXME: Checking for initWithFormat: will not work in most cases
1828730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  yet because [NSString alloc] returns id, not NSString*.  We will
1838730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  need support for tracking expected-type information in the analyzer
1848730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  to find these errors.
1858730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      if (!strcmp(cstr, "initWithFormat:"))
1868730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek        return CheckNilArg(N, 0);
1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1888730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      break;
1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1904ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 16:
1914ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:"))
1924ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1944ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1964ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 22:
1974ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:"))
1984ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2004ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2024ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 23:
2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2044ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "caseInsensitiveCompare:"))
2054ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2079b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
2088730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek
2094ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 29:
2104ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:locale:"))
2114ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      break;
2141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2154ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 37:
2164ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    if (!strcmp(cstr, "componentsSeparatedByCharactersInSet:"))
2174ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      return CheckNilArg(N, 0);
2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    break;
22099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  }
2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
22299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  return false;
22399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
22404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
22504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
22604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek// Error reporting.
22704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
22804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
22904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
23004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
231ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass AuditCFNumberCreate : public GRSimpleAPICheck {
232cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse* BT;
2331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
23404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: Either this should be refactored into GRSimpleAPICheck, or
23504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //   it should always be passed with a call to Audit.  The latter
23604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //   approach makes this class more stateless.
23704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  ASTContext& Ctx;
23804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  IdentifierInfo* II;
239cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter& BR;
24023ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek
24104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekpublic:
2421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  AuditCFNumberCreate(ASTContext& ctx, BugReporter& br)
24323ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){}
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
245cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  ~AuditCFNumberCreate() {}
2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
247c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
24904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekprivate:
250c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  void AddError(const TypedRegion* R, const Expr* Ex, ExplodedNode *N,
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
25204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
25304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} // end anonymous namespace
25404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
25504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekenum CFNumberType {
25604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt8Type = 1,
25704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt16Type = 2,
25804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt32Type = 3,
25904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt64Type = 4,
26004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat32Type = 5,
26104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat64Type = 6,
26204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCharType = 7,
26304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberShortType = 8,
26404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberIntType = 9,
26504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongType = 10,
26604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongLongType = 11,
26704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloatType = 12,
26804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberDoubleType = 13,
26904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCFIndexType = 14,
27004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberNSIntegerType = 15,
27104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCGFloatType = 16
27204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
27304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
27404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
27504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  template<typename T>
27604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  class Optional {
27704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool IsKnown;
27804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    T Val;
27904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  public:
28004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional() : IsKnown(false), Val(0) {}
28104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional(const T& val) : IsKnown(true), Val(val) {}
2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
28304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool isKnown() const { return IsKnown; }
28404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
28504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    const T& getValue() const {
28604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      assert (isKnown());
28704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Val;
28804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
28904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
29004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    operator const T&() const {
29104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return getValue();
29204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
29304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
29404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
29504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
29604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic Optional<uint64_t> GetCFNumberSize(ASTContext& Ctx, uint64_t i) {
2972550d70aabb5f603e8f74cc5fb6a69a7af5b51f3Nuno Lopes  static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
29904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (i < kCFNumberCharType)
30004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return FixedSize[i-1];
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  QualType T;
3031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  switch (i) {
30504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCharType:     T = Ctx.CharTy;     break;
30604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberShortType:    T = Ctx.ShortTy;    break;
30704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberIntType:      T = Ctx.IntTy;      break;
30804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongType:     T = Ctx.LongTy;     break;
30904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
31004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
31104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
31204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCFIndexType:
31304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberNSIntegerType:
31404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCGFloatType:
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // FIXME: We need a way to map from names to Type*.
31604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    default:
31704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Optional<uint64_t>();
31804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  }
3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return Ctx.getTypeSize(T);
32104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
32204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
32304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#if 0
32404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic const char* GetCFNumberTypeStr(uint64_t i) {
32504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  static const char* Names[] = {
32604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt8Type",
32704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt16Type",
32804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt32Type",
32904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt64Type",
33004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat32Type",
33104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat64Type",
33204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCharType",
33304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberShortType",
33404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberIntType",
33504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongType",
33604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongLongType",
33704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloatType",
33804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberDoubleType",
33904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCFIndexType",
34004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberNSIntegerType",
34104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCGFloatType"
34204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
34504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
34604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#endif
34704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
3495f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const CallExpr* CE =
3505f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
3511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Expr* Callee = CE->getCallee();
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  SVal CallV = N->getState()->getSVal(Callee);
353369f447eded97e6048ced02c0c2be3842f61fc1cZhongxing Xu  const FunctionDecl* FD = CallV.getAsFunctionDecl();
35404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
355369f447eded97e6048ced02c0c2be3842f61fc1cZhongxing Xu  if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
35604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Get the value of the "theType" argument.
35923ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));
3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    // FIXME: We really should allow ranges of valid theType values, and
36204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    //   bifurcate the state appropriately.
3631c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!V)
36604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t NumberKind = V->getValue().getLimitedValue();
36904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: In some cases we can emit an error.
37204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!TargetSize.isKnown())
37304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Look at the value of the integer being passed by reference.  Essentially
37604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // we want to catch cases where the value passed in is not equal to the
37704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // size of the type being created.
37823ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));
3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
38004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: Eventually we should handle arbitrary locations.  We can do this
38104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  by having an enhanced memory model that does low-level typing.
3821c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
38304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
38404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!LV)
38504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
387479529e679957fbb92b56e116e3c86734429331eZhongxing Xu  const TypedRegion* R = dyn_cast<TypedRegion>(LV->StripCasts());
3885e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek
3895e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek  if (!R)
3905e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek    return false;
3915e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek
392a82d8aa5b3b3d24998b4d98b9f45a43cc84cac6fZhongxing Xu  QualType T = Ctx.getCanonicalType(R->getValueType(Ctx));
3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: If the pointee isn't an integer type, should we flag a warning?
39504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  People can do weird stuff with pointers.
3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (!T->isIntegerType())
39804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t SourceSize = Ctx.getTypeSize(T);
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // CHECK: is SourceSize == TargetSize
4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (SourceSize == TargetSize)
40504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4079e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek  AddError(R, CE->getArg(2), N, SourceSize, TargetSize, NumberKind);
4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: We can actually create an abstract "CFNumber" object that has
41004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  the bits initialized to the provided values.
41104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return SourceSize < TargetSize;
41204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
41304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
4145f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekvoid AuditCFNumberCreate::AddError(const TypedRegion* R, const Expr* Ex,
415c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                   ExplodedNode *N,
41604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek                                   uint64_t SourceSize, uint64_t TargetSize,
41704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek                                   uint64_t NumberKind) {
4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
419cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  std::string sbuf;
420cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::raw_string_ostream os(sbuf);
4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
42204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  os << (SourceSize == 8 ? "An " : "A ")
42304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek     << SourceSize << " bit integer is used to initialize a CFNumber "
42404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek        "object that represents "
42504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek     << (TargetSize == 8 ? "an " : "a ")
4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump     << TargetSize << " bit integer. ";
42704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
42804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (SourceSize < TargetSize)
42904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    os << (TargetSize - SourceSize)
4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump       << " bits of the CFNumber value will be garbage." ;
43104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  else
43204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    os << (SourceSize - TargetSize)
43304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek       << " bits of the input integer will be lost.";
4341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
435cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Lazily create the BugType object.  This will be owned
436cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // by the BugReporter object 'BR' once we call BR.EmitWarning.
437cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!BT) BT = new APIMisuse("Bad use of CFNumberCreate");
4384988a9a278c50fddf46d38331e4a136a91487b7dBenjamin Kramer  RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
439cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  report->addRange(Ex->getSourceRange());
440cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BR.EmitReport(report);
44104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
44204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
44304bc87683acacce119967dfa5f7c35b4ecef012aTed KremenekGRSimpleAPICheck*
4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
44523ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  return new AuditCFNumberCreate(Ctx, BR);
44604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
44704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
44878d46242e3351484c2b773f5610beba5d316914bTed Kremenek//===----------------------------------------------------------------------===//
44979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek// CFRetain/CFRelease auditing for null arguments.
45079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
45179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
45279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremeneknamespace {
453ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass AuditCFRetainRelease : public GRSimpleAPICheck {
45479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  APIMisuse *BT;
4551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
45679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: Either this should be refactored into GRSimpleAPICheck, or
45779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  //   it should always be passed with a call to Audit.  The latter
45879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  //   approach makes this class more stateless.
45979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  ASTContext& Ctx;
46079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  IdentifierInfo *Retain, *Release;
46179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  BugReporter& BR;
4621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
46379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenekpublic:
4641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  AuditCFRetainRelease(ASTContext& ctx, BugReporter& br)
46579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  : BT(0), Ctx(ctx),
46679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    Retain(&Ctx.Idents.get("CFRetain")), Release(&Ctx.Idents.get("CFRelease")),
46779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    BR(br){}
4681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
46979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  ~AuditCFRetainRelease() {}
4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
471c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
47279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek};
47379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek} // end anonymous namespace
47479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
47579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
476c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xubool AuditCFRetainRelease::Audit(ExplodedNode* N, GRStateManager&) {
4775f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
4781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
47979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // If the CallExpr doesn't have exactly 1 argument just give up checking.
48079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (CE->getNumArgs() != 1)
48179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // Check if we called CFRetain/CFRelease.
48479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  const GRState* state = N->getState();
48579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  SVal X = state->getSVal(CE->getCallee());
48679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  const FunctionDecl* FD = X.getAsFunctionDecl();
4871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!FD)
48979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const IdentifierInfo *FuncII = FD->getIdentifier();
49279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!(FuncII == Retain || FuncII == Release))
49379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
49579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // Finally, check if the argument is NULL.
49679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: We should be able to bifurcate the state here, as a successful
49779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // check will result in the value not being NULL afterwards.
49879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: Need a way to register vistors for the BugReporter.  Would like
49979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // to benefit from the same diagnostics that regular null dereference
50079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // reporting has.
50179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (state->getStateManager().isEqual(state, CE->getArg(0), 0)) {
50279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    if (!BT)
50379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek      BT = new APIMisuse("null passed to CFRetain/CFRelease");
5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
50579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    const char *description = (FuncII == Retain)
50679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            ? "Null pointer argument in call to CFRetain"
50779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            : "Null pointer argument in call to CFRelease";
50879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
50979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    RangedBugReport *report = new RangedBugReport(*BT, description, N);
51079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    report->addRange(CE->getArg(0)->getSourceRange());
51179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    BR.EmitReport(report);
51279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return true;
51379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  }
51479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
51579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  return false;
51679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}
5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
51979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted KremenekGRSimpleAPICheck*
5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclang::CreateAuditCFRetainRelease(ASTContext& Ctx, BugReporter& BR) {
52179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  return new AuditCFRetainRelease(Ctx, BR);
52279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}
52379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
52479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
52550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
52650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
52750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
52850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremeneknamespace {
529ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass ClassReleaseChecker :
53050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    public CheckerVisitor<ClassReleaseChecker> {
53150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector releaseS;
53250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector retainS;
53350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector autoreleaseS;
53450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector drainS;
53550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  BugType *BT;
53650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenekpublic:
53750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  ClassReleaseChecker(ASTContext &Ctx)
53850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    : releaseS(GetNullarySelector("release", Ctx)),
53950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      retainS(GetNullarySelector("retain", Ctx)),
54050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      autoreleaseS(GetNullarySelector("autorelease", Ctx)),
54150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      drainS(GetNullarySelector("drain", Ctx)),
54250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      BT(0) {}
54350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
54450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  static void *getTag() { static int x = 0; return &x; }
54550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
54650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
54750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek};
54850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
54950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenekvoid ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
55150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek                                                  const ObjCMessageExpr *ME) {
55250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  const IdentifierInfo *ClsName = ME->getClassName();
55450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!ClsName)
55550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
55650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector S = ME->getSelector();
558921ddc4e7ef35d77965205d91582c356cb54f5efBenjamin Kramer  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
55950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
56050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
56150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!BT)
56250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    BT = new APIMisuse("message incorrectly sent to class instead of class "
56350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek                       "instance");
56450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
56519d67b52b73c04ef8eb663980330a1de2b47c845Ted Kremenek  ExplodedNode *N = C.GenerateNode();
56619d67b52b73c04ef8eb663980330a1de2b47c845Ted Kremenek
56750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!N)
56850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
56950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  llvm::SmallString<200> buf;
57150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  llvm::raw_svector_ostream os(buf);
57250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  os << "The '" << S.getAsString() << "' message should be sent to instances "
57450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek        "of class '" << ClsName->getName()
57550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek     << "' and not the class directly";
57650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
57850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  report->addRange(ME->getSourceRange());
57950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  C.EmitReport(report);
58050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
58150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
58250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
58378d46242e3351484c2b773f5610beba5d316914bTed Kremenek// Check registration.
58479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
58578d46242e3351484c2b773f5610beba5d316914bTed Kremenek
5865ab128b02d3b10413fb30738ec9f401dcfb47252Zhongxing Xuvoid clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
58778d46242e3351484c2b773f5610beba5d316914bTed Kremenek  ASTContext& Ctx = Eng.getContext();
588cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter &BR = Eng.getBugReporter();
58978d46242e3351484c2b773f5610beba5d316914bTed Kremenek
59023ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR),
59178d46242e3351484c2b773f5610beba5d316914bTed Kremenek               Stmt::ObjCMessageExprClass);
5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR), Stmt::CallExprClass);
59379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5955ab128b02d3b10413fb30738ec9f401dcfb47252Zhongxing Xu  RegisterNSErrorChecks(BR, Eng, D);
59654cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek  RegisterNSAutoreleasePoolChecks(Eng);
59750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Eng.registerCheck(new ClassReleaseChecker(Ctx));
59878d46242e3351484c2b773f5610beba5d316914bTed Kremenek}
599