BasicObjCFoundationChecks.cpp revision 921ddc4e7ef35d77965205d91582c356cb54f5ef
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#include "llvm/Support/Compiler.h"
3299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
3399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekusing namespace clang;
34f1ae705460552655fe7275327804444c62e86baeTed Kremenek
3514108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffstatic const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {
3614108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  const Expr* Receiver = ME->getReceiver();
371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
38f1ae705460552655fe7275327804444c62e86baeTed Kremenek  if (!Receiver)
39f1ae705460552655fe7275327804444c62e86baeTed Kremenek    return NULL;
401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4114108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  if (const ObjCObjectPointerType *PT =
42183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall      Receiver->getType()->getAs<ObjCObjectPointerType>())
4314108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff    return PT->getInterfaceType();
44c1ff3cd5fe4436bb14309fdc5ee7e1c2b702b7c3Ted Kremenek
45c1ff3cd5fe4436bb14309fdc5ee7e1c2b702b7c3Ted Kremenek  return NULL;
46f1ae705460552655fe7275327804444c62e86baeTed Kremenek}
47f1ae705460552655fe7275327804444c62e86baeTed Kremenek
4814108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffstatic const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
49e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar  if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME))
50e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar    return ReceiverType->getDecl()->getIdentifier()->getNameStart();
51e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar  return NULL;
52f1ae705460552655fe7275327804444c62e86baeTed Kremenek}
53f1ae705460552655fe7275327804444c62e86baeTed Kremenek
5499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremeneknamespace {
55b344f91f00021b88e365a4a38502090c3b0cef12Ted Kremenek
56cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenekclass VISIBILITY_HIDDEN APIMisuse : public BugType {
57f1ae705460552655fe7275327804444c62e86baeTed Kremenekpublic:
58cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
59f1ae705460552655fe7275327804444c62e86baeTed Kremenek};
601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekclass VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
62cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse *BT;
63cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter& BR;
64e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek  ASTContext &Ctx;
651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
66d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
67031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
70031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  void WarnNilArg(ExplodedNode* N, const Expr* E);
711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
72031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  bool CheckNilArg(ExplodedNode* N, unsigned Arg);
7399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
7499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekpublic:
751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br)
7623ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek    : BT(0), BR(br), Ctx(ctx) {}
771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
78c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpprivate:
811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  void WarnNilArg(ExplodedNode* N, const ObjCMessageExpr* ME, unsigned Arg) {
82cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    std::string sbuf;
83cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    llvm::raw_string_ostream os(sbuf);
84cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
85cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek       << ME->getSelector().getAsString() << "' cannot be nil.";
861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
87cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    // Lazily create the BugType object for NilArg.  This will be owned
88cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    // by the BugReporter object 'BR' once we call BR.EmitWarning.
89cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    if (!BT) BT = new APIMisuse("nil argument");
901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    RangedBugReport *R = new RangedBugReport(*BT, os.str().c_str(), N);
92cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    R->addRange(ME->getArg(Arg)->getSourceRange());
93cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek    BR.EmitReport(R);
94f1ae705460552655fe7275327804444c62e86baeTed Kremenek  }
9599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek} // end anonymous namespace
9899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
9999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
100527556184b276c545be1355ad596fce29a0400fbTed KremenekGRSimpleAPICheck*
10123ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenekclang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) {
1021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return new BasicObjCFoundationChecks(Ctx, BR);
103527556184b276c545be1355ad596fce29a0400fbTed Kremenek}
104527556184b276c545be1355ad596fce29a0400fbTed Kremenek
1054ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
10699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
107c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xubool BasicObjCFoundationChecks::Audit(ExplodedNode* N,
1084adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek                                      GRStateManager&) {
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1105f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const ObjCMessageExpr* ME =
1114ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1124ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
11314108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (!ReceiverType)
116f74279447d4ad0a0c0f2e6e6740d5a0f4c242e0cNuno Lopes    return false;
1171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
118d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  if (isNSString(ReceiverType,
11901eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar                 ReceiverType->getDecl()->getIdentifier()->getName()))
12099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return AuditNSString(N, ME);
12199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
122f74279447d4ad0a0c0f2e6e6740d5a0f4c242e0cNuno Lopes  return false;
12399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
12499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1251c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xustatic inline bool isNil(SVal X) {
1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return isa<loc::ConcreteInt>(X);
127e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek}
128e5d5c204c761cc3b2a6374a15b035420f207c7afTed Kremenek
12999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
13099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// Error reporting.
13199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
13299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
133031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xubool BasicObjCFoundationChecks::CheckNilArg(ExplodedNode* N, unsigned Arg) {
1345f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const ObjCMessageExpr* ME =
1354ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
1361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1375f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Expr * E = ME->getArg(Arg);
1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13923ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  if (isNil(N->getState()->getSVal(E))) {
140f1ae705460552655fe7275327804444c62e86baeTed Kremenek    WarnNilArg(N, ME, Arg);
1414ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    return true;
1424ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  }
1431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1444ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek  return false;
1454ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek}
1464ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek
14799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
14899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek// NSString checking.
14999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek//===----------------------------------------------------------------------===//
15099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
15114108da7f7fc059772711e4ffee1322a27b152a7Steve Naroffbool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType *T,
152d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar                                           llvm::StringRef ClassName) {
153d777d58714fc26c645e061ed7aa43ecb05ab41a8Daniel Dunbar  return ClassName == "NSString" || ClassName == "NSMutableString";
15499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
15599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N,
1575f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek                                              const ObjCMessageExpr* ME) {
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  Selector S = ME->getSelector();
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  if (S.isUnarySelector())
16299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek    return false;
16399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
16499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  // FIXME: This is going to be really slow doing these checks with
16599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  //  lexical comparisons.
1661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
167077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  std::string name = S.getAsString();
1689b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  assert (!name.empty());
1699b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  const char* cstr = &name[0];
1709b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  unsigned len = name.size();
1711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1729b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek  switch (len) {
1739b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek    default:
1749b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
1751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    case 8:
1764ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:"))
1774ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
1781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1794ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1818730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek    case 15:
1828730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      // FIXME: Checking for initWithFormat: will not work in most cases
1838730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  yet because [NSString alloc] returns id, not NSString*.  We will
1848730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  need support for tracking expected-type information in the analyzer
1858730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      //  to find these errors.
1868730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      if (!strcmp(cstr, "initWithFormat:"))
1878730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek        return CheckNilArg(N, 0);
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1898730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek      break;
1901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1914ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 16:
1924ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:"))
1934ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1954ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1974ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 22:
1984ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:"))
1994ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2014ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      break;
2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2034ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 23:
2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2054ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "caseInsensitiveCompare:"))
2064ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2089b3fdeaca3660789d89e3980dc7d41e8676cd901Ted Kremenek      break;
2098730e130ab77ae5739e6339e1544b4ca9ab28450Ted Kremenek
2104ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 29:
2114ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      if (!strcmp(cstr, "compare:options:range:locale:"))
2124ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek        return CheckNilArg(N, 0);
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      break;
2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2164ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    case 37:
2174ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek    if (!strcmp(cstr, "componentsSeparatedByCharactersInSet:"))
2184ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek      return CheckNilArg(N, 0);
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    break;
22199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  }
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
22399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek  return false;
22499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek}
22504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
22604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
22704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek// Error reporting.
22804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===//
22904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
23004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
23104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
23204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekclass VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
233cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  APIMisuse* BT;
2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
23504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: Either this should be refactored into GRSimpleAPICheck, or
23604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //   it should always be passed with a call to Audit.  The latter
23704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //   approach makes this class more stateless.
23804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  ASTContext& Ctx;
23904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  IdentifierInfo* II;
240cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter& BR;
24123ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek
24204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekpublic:
2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  AuditCFNumberCreate(ASTContext& ctx, BugReporter& br)
24423ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){}
2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
246cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  ~AuditCFNumberCreate() {}
2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
248c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
25004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekprivate:
251c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  void AddError(const TypedRegion* R, const Expr* Ex, ExplodedNode *N,
2521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
25304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
25404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} // end anonymous namespace
25504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
25604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekenum CFNumberType {
25704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt8Type = 1,
25804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt16Type = 2,
25904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt32Type = 3,
26004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberSInt64Type = 4,
26104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat32Type = 5,
26204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloat64Type = 6,
26304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCharType = 7,
26404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberShortType = 8,
26504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberIntType = 9,
26604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongType = 10,
26704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberLongLongType = 11,
26804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberFloatType = 12,
26904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberDoubleType = 13,
27004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCFIndexType = 14,
27104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberNSIntegerType = 15,
27204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  kCFNumberCGFloatType = 16
27304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek};
27404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
27504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace {
27604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  template<typename T>
27704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  class Optional {
27804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool IsKnown;
27904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    T Val;
28004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  public:
28104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional() : IsKnown(false), Val(0) {}
28204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    Optional(const T& val) : IsKnown(true), Val(val) {}
2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
28404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    bool isKnown() const { return IsKnown; }
28504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
28604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    const T& getValue() const {
28704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      assert (isKnown());
28804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Val;
28904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
29004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
29104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    operator const T&() const {
29204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return getValue();
29304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    }
29404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
29504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
29604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
29704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic Optional<uint64_t> GetCFNumberSize(ASTContext& Ctx, uint64_t i) {
29804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  static unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
2991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (i < kCFNumberCharType)
30104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return FixedSize[i-1];
3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  QualType T;
3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  switch (i) {
30604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCharType:     T = Ctx.CharTy;     break;
30704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberShortType:    T = Ctx.ShortTy;    break;
30804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberIntType:      T = Ctx.IntTy;      break;
30904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongType:     T = Ctx.LongTy;     break;
31004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
31104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberFloatType:    T = Ctx.FloatTy;    break;
31204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberDoubleType:   T = Ctx.DoubleTy;   break;
31304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCFIndexType:
31404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberNSIntegerType:
31504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    case kCFNumberCGFloatType:
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // FIXME: We need a way to map from names to Type*.
31704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    default:
31804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek      return Optional<uint64_t>();
31904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  }
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return Ctx.getTypeSize(T);
32204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
32304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
32404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#if 0
32504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic const char* GetCFNumberTypeStr(uint64_t i) {
32604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  static const char* Names[] = {
32704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt8Type",
32804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt16Type",
32904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt32Type",
33004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberSInt64Type",
33104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat32Type",
33204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloat64Type",
33304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCharType",
33404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberShortType",
33504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberIntType",
33604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongType",
33704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberLongLongType",
33804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberFloatType",
33904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberDoubleType",
34004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCFIndexType",
34104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberNSIntegerType",
34204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    "kCFNumberCGFloatType"
34304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  };
3441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
34604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
34704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#endif
34804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
3505f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const CallExpr* CE =
3515f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Expr* Callee = CE->getCallee();
3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  SVal CallV = N->getState()->getSVal(Callee);
354369f447eded97e6048ced02c0c2be3842f61fc1cZhongxing Xu  const FunctionDecl* FD = CallV.getAsFunctionDecl();
35504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
356369f447eded97e6048ced02c0c2be3842f61fc1cZhongxing Xu  if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
35704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Get the value of the "theType" argument.
36023ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));
3611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    // FIXME: We really should allow ranges of valid theType values, and
36304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    //   bifurcate the state appropriately.
3641c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
3651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!V)
36704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t NumberKind = V->getValue().getLimitedValue();
37004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: In some cases we can emit an error.
37304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!TargetSize.isKnown())
37404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // Look at the value of the integer being passed by reference.  Essentially
37704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // we want to catch cases where the value passed in is not equal to the
37804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // size of the type being created.
37923ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));
3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
38104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: Eventually we should handle arbitrary locations.  We can do this
38204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  by having an enhanced memory model that does low-level typing.
3831c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
38404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
38504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (!LV)
38604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
388479529e679957fbb92b56e116e3c86734429331eZhongxing Xu  const TypedRegion* R = dyn_cast<TypedRegion>(LV->StripCasts());
3895e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek
3905e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek  if (!R)
3915e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek    return false;
3925e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek
393a82d8aa5b3b3d24998b4d98b9f45a43cc84cac6fZhongxing Xu  QualType T = Ctx.getCanonicalType(R->getValueType(Ctx));
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: If the pointee isn't an integer type, should we flag a warning?
39604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  People can do weird stuff with pointers.
3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (!T->isIntegerType())
39904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  uint64_t SourceSize = Ctx.getTypeSize(T);
4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // CHECK: is SourceSize == TargetSize
4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (SourceSize == TargetSize)
40604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    return false;
4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4089e24049bef26b6289cce9ac9b483c5cbb096e3aeTed Kremenek  AddError(R, CE->getArg(2), N, SourceSize, TargetSize, NumberKind);
4091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
41004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  // FIXME: We can actually create an abstract "CFNumber" object that has
41104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  //  the bits initialized to the provided values.
41204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  return SourceSize < TargetSize;
41304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
41404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
4155f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekvoid AuditCFNumberCreate::AddError(const TypedRegion* R, const Expr* Ex,
416c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu                                   ExplodedNode *N,
41704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek                                   uint64_t SourceSize, uint64_t TargetSize,
41804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek                                   uint64_t NumberKind) {
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
420cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  std::string sbuf;
421cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  llvm::raw_string_ostream os(sbuf);
4221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
42304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  os << (SourceSize == 8 ? "An " : "A ")
42404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek     << SourceSize << " bit integer is used to initialize a CFNumber "
42504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek        "object that represents "
42604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek     << (TargetSize == 8 ? "an " : "a ")
4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump     << TargetSize << " bit integer. ";
42804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
42904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  if (SourceSize < TargetSize)
43004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    os << (TargetSize - SourceSize)
4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump       << " bits of the CFNumber value will be garbage." ;
43204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek  else
43304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek    os << (SourceSize - TargetSize)
43404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek       << " bits of the input integer will be lost.";
4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
436cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // Lazily create the BugType object.  This will be owned
437cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  // by the BugReporter object 'BR' once we call BR.EmitWarning.
438cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  if (!BT) BT = new APIMisuse("Bad use of CFNumberCreate");
439cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  RangedBugReport *report = new RangedBugReport(*BT, os.str().c_str(), N);
440cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  report->addRange(Ex->getSourceRange());
441cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BR.EmitReport(report);
44204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
44304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
44404bc87683acacce119967dfa5f7c35b4ecef012aTed KremenekGRSimpleAPICheck*
4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
44623ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  return new AuditCFNumberCreate(Ctx, BR);
44704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}
44804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek
44978d46242e3351484c2b773f5610beba5d316914bTed Kremenek//===----------------------------------------------------------------------===//
45079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek// CFRetain/CFRelease auditing for null arguments.
45179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
45279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
45379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremeneknamespace {
45479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenekclass VISIBILITY_HIDDEN AuditCFRetainRelease : public GRSimpleAPICheck {
45579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  APIMisuse *BT;
4561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
45779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: Either this should be refactored into GRSimpleAPICheck, or
45879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  //   it should always be passed with a call to Audit.  The latter
45979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  //   approach makes this class more stateless.
46079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  ASTContext& Ctx;
46179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  IdentifierInfo *Retain, *Release;
46279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  BugReporter& BR;
4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
46479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenekpublic:
4651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  AuditCFRetainRelease(ASTContext& ctx, BugReporter& br)
46679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  : BT(0), Ctx(ctx),
46779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    Retain(&Ctx.Idents.get("CFRetain")), Release(&Ctx.Idents.get("CFRelease")),
46879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    BR(br){}
4691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
47079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  ~AuditCFRetainRelease() {}
4711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
472c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  bool Audit(ExplodedNode* N, GRStateManager&);
47379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek};
47479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek} // end anonymous namespace
47579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
47679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
477c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xubool AuditCFRetainRelease::Audit(ExplodedNode* N, GRStateManager&) {
4785f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // If the CallExpr doesn't have exactly 1 argument just give up checking.
48179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (CE->getNumArgs() != 1)
48279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // Check if we called CFRetain/CFRelease.
48579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  const GRState* state = N->getState();
48679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  SVal X = state->getSVal(CE->getCallee());
48779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  const FunctionDecl* FD = X.getAsFunctionDecl();
4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!FD)
49079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const IdentifierInfo *FuncII = FD->getIdentifier();
49379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (!(FuncII == Retain || FuncII == Release))
49479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return false;
4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
49679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // Finally, check if the argument is NULL.
49779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: We should be able to bifurcate the state here, as a successful
49879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // check will result in the value not being NULL afterwards.
49979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // FIXME: Need a way to register vistors for the BugReporter.  Would like
50079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // to benefit from the same diagnostics that regular null dereference
50179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  // reporting has.
50279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  if (state->getStateManager().isEqual(state, CE->getArg(0), 0)) {
50379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    if (!BT)
50479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek      BT = new APIMisuse("null passed to CFRetain/CFRelease");
5051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
50679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    const char *description = (FuncII == Retain)
50779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            ? "Null pointer argument in call to CFRetain"
50879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek                            : "Null pointer argument in call to CFRelease";
50979b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
51079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    RangedBugReport *report = new RangedBugReport(*BT, description, N);
51179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    report->addRange(CE->getArg(0)->getSourceRange());
51279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    BR.EmitReport(report);
51379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek    return true;
51479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  }
51579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
51679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  return false;
51779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}
5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
52079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted KremenekGRSimpleAPICheck*
5211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpclang::CreateAuditCFRetainRelease(ASTContext& Ctx, BugReporter& BR) {
52279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  return new AuditCFRetainRelease(Ctx, BR);
52379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}
52479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek
52579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
52650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
52750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
52850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
52950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremeneknamespace {
53050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenekclass VISIBILITY_HIDDEN ClassReleaseChecker :
53150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    public CheckerVisitor<ClassReleaseChecker> {
53250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector releaseS;
53350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector retainS;
53450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector autoreleaseS;
53550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector drainS;
53650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  BugType *BT;
53750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenekpublic:
53850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  ClassReleaseChecker(ASTContext &Ctx)
53950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    : releaseS(GetNullarySelector("release", Ctx)),
54050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      retainS(GetNullarySelector("retain", Ctx)),
54150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      autoreleaseS(GetNullarySelector("autorelease", Ctx)),
54250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      drainS(GetNullarySelector("drain", Ctx)),
54350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek      BT(0) {}
54450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
54550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  static void *getTag() { static int x = 0; return &x; }
54650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
54750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
54850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek};
54950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
55050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenekvoid ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
55250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek                                                  const ObjCMessageExpr *ME) {
55350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  const IdentifierInfo *ClsName = ME->getClassName();
55550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!ClsName)
55650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
55750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
55850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Selector S = ME->getSelector();
559921ddc4e7ef35d77965205d91582c356cb54f5efBenjamin Kramer  if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
56050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
56150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
56250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!BT)
56350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    BT = new APIMisuse("message incorrectly sent to class instead of class "
56450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek                       "instance");
56550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
56650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  ExplodedNode *N = C.GenerateNode(ME, C.getState(), false);
56750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  if (!N)
56850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek    return;
56950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  C.addTransition(N);
57150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  llvm::SmallString<200> buf;
57350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  llvm::raw_svector_ostream os(buf);
57450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  os << "The '" << S.getAsString() << "' message should be sent to instances "
57650e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek        "of class '" << ClsName->getName()
57750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek     << "' and not the class directly";
57850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
57950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
58050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  report->addRange(ME->getSourceRange());
58150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  C.EmitReport(report);
58250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}
58350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek
58450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===//
58578d46242e3351484c2b773f5610beba5d316914bTed Kremenek// Check registration.
58679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===//
58778d46242e3351484c2b773f5610beba5d316914bTed Kremenek
5885ab128b02d3b10413fb30738ec9f401dcfb47252Zhongxing Xuvoid clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
58978d46242e3351484c2b773f5610beba5d316914bTed Kremenek  ASTContext& Ctx = Eng.getContext();
590cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  BugReporter &BR = Eng.getBugReporter();
59178d46242e3351484c2b773f5610beba5d316914bTed Kremenek
59223ec48cd3369c8d7d1ab3c3f2226cfcffd2cd3d3Ted Kremenek  Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR),
59378d46242e3351484c2b773f5610beba5d316914bTed Kremenek               Stmt::ObjCMessageExprClass);
5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR), Stmt::CallExprClass);
59579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek  Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5975ab128b02d3b10413fb30738ec9f401dcfb47252Zhongxing Xu  RegisterNSErrorChecks(BR, Eng, D);
59854cb7ccc769a5e81a13812e08c21daf52a781262Ted Kremenek  RegisterNSAutoreleasePoolChecks(Eng);
59950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek  Eng.registerCheck(new ClassReleaseChecker(Ctx));
60078d46242e3351484c2b773f5610beba5d316914bTed Kremenek}
601