BasicObjCFoundationChecks.cpp revision 9c378f705405d37f49795d5e915989de774fe11f
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 160b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis#include "ClangSACheckers.h" 17928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek#include "clang/Analysis/DomainSpecific/CocoaConventions.h" 18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 19695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 20983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 229b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 239b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" 249b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 259b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 26c4a1dea2dc56bd1357ec91b829a0b9e68229a13eDaniel Dunbar#include "clang/AST/DeclObjC.h" 2799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/Expr.h" 28f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#include "clang/AST/ExprObjC.h" 2999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/ASTContext.h" 3099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek 3199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekusing namespace clang; 329ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 33f1ae705460552655fe7275327804444c62e86baeTed Kremenek 342ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremeneknamespace { 352ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekclass APIMisuse : public BugType { 362ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekpublic: 372ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {} 382ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek}; 392ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek} // end anonymous namespace 402ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 412ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===// 422ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek// Utility functions. 432ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===// 442ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 45b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlssonstatic const char* GetReceiverNameType(const ObjCMessage &msg) { 46432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface()) 47b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson return ID->getIdentifier()->getNameStart(); 48b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson return 0; 49f1ae705460552655fe7275327804444c62e86baeTed Kremenek} 50f1ae705460552655fe7275327804444c62e86baeTed Kremenek 51b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlssonstatic bool isReceiverClassOrSuperclass(const ObjCInterfaceDecl *ID, 525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName) { 53b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson if (ID->getIdentifier()->getName() == ClassName) 54b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson return true; 55b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson 56b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson if (const ObjCInterfaceDecl *Super = ID->getSuperClass()) 57b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson return isReceiverClassOrSuperclass(Super, ClassName); 58f1ae705460552655fe7275327804444c62e86baeTed Kremenek 59b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson return false; 602ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek} 611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 622ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekstatic inline bool isNil(SVal X) { 632ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return isa<loc::ConcreteInt>(X); 642ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek} 651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 662ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===// 672ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek// NilArgChecker - Check for prohibited nil arguments to ObjC method calls. 682ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek//===----------------------------------------------------------------------===// 6999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek 70cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramernamespace { 71ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis class NilArgChecker : public Checker<check::PreObjCMessage> { 7274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable llvm::OwningPtr<APIMisuse> BT; 7374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis 7474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis void WarnNilArg(CheckerContext &C, 7574eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis const ObjCMessage &msg, unsigned Arg) const; 7674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis 77cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer public: 7874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; 79cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer }; 80cb9c07418b699bd2b8384d31ff4392df7d76eb7cBenjamin Kramer} 811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 822ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenekvoid NilArgChecker::WarnNilArg(CheckerContext &C, 83432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis const ObjCMessage &msg, 8474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis unsigned int Arg) const 852ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek{ 862ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!BT) 8774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis BT.reset(new APIMisuse("nil argument")); 882ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 89d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateSink()) { 902ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::SmallString<128> sbuf; 912ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::raw_svector_ostream os(sbuf); 92432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis os << "Argument to '" << GetReceiverNameType(msg) << "' method '" 93432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis << msg.getSelector().getAsString() << "' cannot be nil"; 941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 954988a9a278c50fddf46d38331e4a136a91487b7dBenjamin Kramer RangedBugReport *R = new RangedBugReport(*BT, os.str(), N); 96432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis R->addRange(msg.getArgSourceRange(Arg)); 972ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek C.EmitReport(R); 98f1ae705460552655fe7275327804444c62e86baeTed Kremenek } 99527556184b276c545be1355ad596fce29a0400fbTed Kremenek} 100527556184b276c545be1355ad596fce29a0400fbTed Kremenek 10174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid NilArgChecker::checkPreObjCMessage(ObjCMessage msg, 10274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis CheckerContext &C) const { 103b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson const ObjCInterfaceDecl *ID = msg.getReceiverInterface(); 104b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson if (!ID) 1052ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 1062ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 107b62bdce3e981ea4f357126bc391be1cbc1efa4dfAnders Carlsson if (isReceiverClassOrSuperclass(ID, "NSString")) { 108432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis Selector S = msg.getSelector(); 1092ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 1102ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (S.isUnarySelector()) 1112ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 1122ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 1132ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // FIXME: This is going to be really slow doing these checks with 1142ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // lexical comparisons. 1152ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 1162ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek std::string NameStr = S.getAsString(); 1175f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Name(NameStr); 1182ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek assert(!Name.empty()); 1192ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 1202ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // FIXME: Checking for initWithFormat: will not work in most cases 1212ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // yet because [NSString alloc] returns id, not NSString*. We will 1222ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // need support for tracking expected-type information in the analyzer 1232ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // to find these errors. 1242ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (Name == "caseInsensitiveCompare:" || 1252ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "compare:" || 1262ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "compare:options:" || 1272ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "compare:options:range:" || 1282ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "compare:options:range:locale:" || 1292ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "componentsSeparatedByCharactersInSet:" || 1302ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Name == "initWithFormat:") { 131432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis if (isNil(msg.getArgSVal(0, C.getState()))) 132432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis WarnNilArg(C, msg, 0); 1332ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek } 1344ba6283f9c7db4513ca2d9cbde7df3a58ba941f7Ted Kremenek } 13599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek} 13604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 13704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===// 13804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek// Error reporting. 13904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek//===----------------------------------------------------------------------===// 14004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 14104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace { 142ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > { 14374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable llvm::OwningPtr<APIMisuse> BT; 14474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable IdentifierInfo* II; 14504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekpublic: 14674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis CFNumberCreateChecker() : II(0) {} 14774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis 14874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 14974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis 15004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekprivate: 1519c378f705405d37f49795d5e915989de774fe11fTed Kremenek void EmitError(const TypedRegion* R, const Expr *Ex, 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind); 15304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}; 15404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} // end anonymous namespace 15504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 15604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekenum CFNumberType { 15704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberSInt8Type = 1, 15804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberSInt16Type = 2, 15904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberSInt32Type = 3, 16004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberSInt64Type = 4, 16104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberFloat32Type = 5, 16204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberFloat64Type = 6, 16304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberCharType = 7, 16404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberShortType = 8, 16504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberIntType = 9, 16604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberLongType = 10, 16704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberLongLongType = 11, 16804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberFloatType = 12, 16904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberDoubleType = 13, 17004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberCFIndexType = 14, 17104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberNSIntegerType = 15, 17204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek kCFNumberCGFloatType = 16 17304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek}; 17404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 17504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremeneknamespace { 17604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek template<typename T> 17704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek class Optional { 17804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek bool IsKnown; 17904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek T Val; 18004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek public: 18104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek Optional() : IsKnown(false), Val(0) {} 18204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek Optional(const T& val) : IsKnown(true), Val(val) {} 1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek bool isKnown() const { return IsKnown; } 18504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 18604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek const T& getValue() const { 18704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek assert (isKnown()); 18804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return Val; 18904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek } 19004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 19104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek operator const T&() const { 19204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return getValue(); 19304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek } 19404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek }; 19504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} 19604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 1979c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic Optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) { 1982550d70aabb5f603e8f74cc5fb6a69a7af5b51f3Nuno Lopes static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 }; 1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek if (i < kCFNumberCharType) 20104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return FixedSize[i-1]; 2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek QualType T; 2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek switch (i) { 20604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberCharType: T = Ctx.CharTy; break; 20704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberShortType: T = Ctx.ShortTy; break; 20804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberIntType: T = Ctx.IntTy; break; 20904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberLongType: T = Ctx.LongTy; break; 21004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberLongLongType: T = Ctx.LongLongTy; break; 21104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberFloatType: T = Ctx.FloatTy; break; 21204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberDoubleType: T = Ctx.DoubleTy; break; 21304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberCFIndexType: 21404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberNSIntegerType: 21504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek case kCFNumberCGFloatType: 2161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: We need a way to map from names to Type*. 21704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek default: 21804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return Optional<uint64_t>(); 21904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek } 2201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return Ctx.getTypeSize(T); 22204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} 22304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 22404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#if 0 22504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenekstatic const char* GetCFNumberTypeStr(uint64_t i) { 22604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek static const char* Names[] = { 22704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberSInt8Type", 22804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberSInt16Type", 22904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberSInt32Type", 23004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberSInt64Type", 23104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberFloat32Type", 23204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberFloat64Type", 23304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberCharType", 23404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberShortType", 23504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberIntType", 23604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberLongType", 23704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberLongLongType", 23804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberFloatType", 23904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberDoubleType", 24004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberCFIndexType", 24104bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberNSIntegerType", 24204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek "kCFNumberCGFloatType" 24304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek }; 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType"; 24604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} 24704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek#endif 24804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 24974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, 25074eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis CheckerContext &C) const { 2519c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *Callee = CE->getCallee(); 2522ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek const GRState *state = C.getState(); 2532ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek SVal CallV = state->getSVal(Callee); 2549c378f705405d37f49795d5e915989de774fe11fTed Kremenek const FunctionDecl *FD = CallV.getAsFunctionDecl(); 25504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 2562ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!FD) 2572ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2582ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 2592ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek ASTContext &Ctx = C.getASTContext(); 2602ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!II) 2612ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek II = &Ctx.Idents.get("CFNumberCreate"); 2622ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 2632ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (FD->getIdentifier() != II || CE->getNumArgs() != 3) 2642ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // Get the value of the "theType" argument. 2672ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek SVal TheTypeVal = state->getSVal(CE->getArg(1)); 2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2692ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // FIXME: We really should allow ranges of valid theType values, and 2702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // bifurcate the state appropriately. 2711c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal); 27204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek if (!V) 2732ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek uint64_t NumberKind = V->getValue().getLimitedValue(); 27604bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind); 2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // FIXME: In some cases we can emit an error. 27904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek if (!TargetSize.isKnown()) 2802ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // Look at the value of the integer being passed by reference. Essentially 28304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // we want to catch cases where the value passed in is not equal to the 28404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // size of the type being created. 2852ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek SVal TheValueExpr = state->getSVal(CE->getArg(2)); 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // FIXME: Eventually we should handle arbitrary locations. We can do this 28804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // by having an enhanced memory model that does low-level typing. 2891c96b24285d05c0eac455ae96d7c9ff43d42bc96Zhongxing Xu loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr); 29004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek if (!LV) 2912ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2939697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts()); 2945e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek if (!R) 2952ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 2965e77ebae47099d76020e84e604b33bb33c9006c3Ted Kremenek 297018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu QualType T = Ctx.getCanonicalType(R->getValueType()); 2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29904bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // FIXME: If the pointee isn't an integer type, should we flag a warning? 30004bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // People can do weird stuff with pointers. 3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (!T->isIntegerType()) 3032ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek uint64_t SourceSize = Ctx.getTypeSize(T); 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 30704bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // CHECK: is SourceSize == TargetSize 30804bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek if (SourceSize == TargetSize) 3092ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek return; 3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3112ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // Generate an error. Only generate a sink if 'SourceSize < TargetSize'; 3122ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // otherwise generate a regular node. 3132ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // 31404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // FIXME: We can actually create an abstract "CFNumber" object that has 31504bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek // the bits initialized to the provided values. 3162ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek // 317d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink() 318d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek : C.generateNode()) { 3192ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::SmallString<128> sbuf; 3202ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::raw_svector_ostream os(sbuf); 3212ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 3222ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek os << (SourceSize == 8 ? "An " : "A ") 3232ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << SourceSize << " bit integer is used to initialize a CFNumber " 3242ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek "object that represents " 3252ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << (TargetSize == 8 ? "an " : "a ") 3262ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << TargetSize << " bit integer. "; 3272ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 3282ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (SourceSize < TargetSize) 3292ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek os << (TargetSize - SourceSize) 3302ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << " bits of the CFNumber value will be garbage." ; 3312ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek else 3322ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek os << (SourceSize - TargetSize) 3332ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << " bits of the input integer will be lost."; 33404bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 3352ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!BT) 33674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis BT.reset(new APIMisuse("Bad use of CFNumberCreate")); 3372ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 3382ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek RangedBugReport *report = new RangedBugReport(*BT, os.str(), N); 3392ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek report->addRange(CE->getArg(2)->getSourceRange()); 3402ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek C.EmitReport(report); 3412ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek } 34204bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek} 34304bc87683acacce119967dfa5f7c35b4ecef012aTed Kremenek 34478d46242e3351484c2b773f5610beba5d316914bTed Kremenek//===----------------------------------------------------------------------===// 34561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose// CFRetain/CFRelease checking for null arguments. 34679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===// 34779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek 34879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremeneknamespace { 349ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > { 35074eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable llvm::OwningPtr<APIMisuse> BT; 35174eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable IdentifierInfo *Retain, *Release; 35279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenekpublic: 35374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis CFRetainReleaseChecker(): Retain(0), Release(0) {} 3549c378f705405d37f49795d5e915989de774fe11fTed Kremenek void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 35579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek}; 35679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek} // end anonymous namespace 35779b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek 35879b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek 3599c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE, 3609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CheckerContext &C) const { 36179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek // If the CallExpr doesn't have exactly 1 argument just give up checking. 36279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek if (CE->getNumArgs() != 1) 36361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Get the function declaration of the callee. 3669c378f705405d37f49795d5e915989de774fe11fTed Kremenek const GRState *state = C.getState(); 3671397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal X = state->getSVal(CE->getCallee()); 3689c378f705405d37f49795d5e915989de774fe11fTed Kremenek const FunctionDecl *FD = X.getAsFunctionDecl(); 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37079b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek if (!FD) 37161fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 3722ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 3732ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!BT) { 3742ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek ASTContext &Ctx = C.getASTContext(); 3752ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Retain = &Ctx.Idents.get("CFRetain"); 3762ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek Release = &Ctx.Idents.get("CFRelease"); 37774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis BT.reset(new APIMisuse("null passed to CFRetain/CFRelease")); 3782ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek } 3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Check if we called CFRetain/CFRelease. 3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const IdentifierInfo *FuncII = FD->getIdentifier(); 38279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek if (!(FuncII == Retain || FuncII == Release)) 38361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 38461fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 38561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // FIXME: The rest of this just checks that the argument is non-null. 38661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // It should probably be refactored and combined with AttrNonNullChecker. 38761fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 38861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Get the argument's value. 38961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose const Expr *Arg = CE->getArg(0); 39061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose SVal ArgVal = state->getSVal(Arg); 39161fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal); 39261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose if (!DefArgVal) 39361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 39461fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 39561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Get a NULL value. 396c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 397c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType())); 39861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 39961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Make an expression asserting that they're equal. 400c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal); 40161fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 40261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // Are they equal? 40361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose const GRState *stateTrue, *stateFalse; 40428f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull); 40561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose 40661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose if (stateTrue && !stateFalse) { 407d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(stateTrue); 40861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose if (!N) 40961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 41179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek const char *description = (FuncII == Retain) 41279b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek ? "Null pointer argument in call to CFRetain" 41379b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek : "Null pointer argument in call to CFRelease"; 41479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek 41561fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT, description, N); 41661fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose report->addRange(Arg->getSourceRange()); 41761fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Arg); 41861fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose C.EmitReport(report); 41961fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose return; 42061fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose } 4211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42261fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose // From here on, we know the argument is non-null. 42361fb55c87909bd749a367f7c12b302e39aa3e392Jordy Rose C.addTransition(stateFalse); 42479b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek} 42579b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek 42679b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===// 42750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek// Check for sending 'retain', 'release', or 'autorelease' directly to a Class. 42850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===// 42950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 43050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremeneknamespace { 431ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass ClassReleaseChecker : public Checker<check::PreObjCMessage> { 43274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable Selector releaseS; 43374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable Selector retainS; 43474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable Selector autoreleaseS; 43574eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable Selector drainS; 43674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mutable llvm::OwningPtr<BugType> BT; 43750e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 43874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidispublic: 43974eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; 44050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek}; 44150e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek} 44250e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 44374eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidisvoid ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg, 44474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis CheckerContext &C) const { 4452ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 4462ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek if (!BT) { 44774eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis BT.reset(new APIMisuse("message incorrectly sent to class instead of class " 44874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis "instance")); 4492ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 4502ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek ASTContext &Ctx = C.getASTContext(); 4512ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek releaseS = GetNullarySelector("release", Ctx); 4522ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek retainS = GetNullarySelector("retain", Ctx); 4532ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek autoreleaseS = GetNullarySelector("autorelease", Ctx); 4542ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek drainS = GetNullarySelector("drain", Ctx); 4552ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek } 4562ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek 457432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis if (msg.isInstanceMessage()) 45850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek return; 459432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis const ObjCInterfaceDecl *Class = msg.getReceiverInterface(); 460432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis assert(Class); 46104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 462432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis Selector S = msg.getSelector(); 463921ddc4e7ef35d77965205d91582c356cb54f5efBenjamin Kramer if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS)) 46450e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek return; 46550e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 466d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode()) { 4672ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::SmallString<200> buf; 4682ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek llvm::raw_svector_ostream os(buf); 46950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 4702ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek os << "The '" << S.getAsString() << "' message should be sent to instances " 4712ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek "of class '" << Class->getName() 4722ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek << "' and not the class directly"; 47350e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 4742ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek RangedBugReport *report = new RangedBugReport(*BT, os.str(), N); 475432424d67641d609e4990d791baa782fc161027eArgyrios Kyrtzidis report->addRange(msg.getSourceRange()); 4762ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek C.EmitReport(report); 4772ce2baa81f1bdd5f1a2504bbf812d30f10e45bb5Ted Kremenek } 47850e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek} 47950e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek 48050e837b3cbc9315b6808daabb96c5c7cccf11ea7Ted Kremenek//===----------------------------------------------------------------------===// 4814597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson// Check for passing non-Objective-C types to variadic methods that expect 4824597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson// only Objective-C types. 4834597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson//===----------------------------------------------------------------------===// 4844597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 4854597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonnamespace { 4864597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonclass VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> { 4874597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable Selector arrayWithObjectsS; 4884597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable Selector dictionaryWithObjectsAndKeysS; 4894597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable Selector setWithObjectsS; 4904597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable Selector initWithObjectsS; 4914597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable Selector initWithObjectsAndKeysS; 4924597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mutable llvm::OwningPtr<BugType> BT; 4934597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 4944597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson bool isVariadicMessage(const ObjCMessage &msg) const; 4954597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 4964597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonpublic: 4974597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; 4984597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson}; 4994597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson} 5004597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5014597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson/// isVariadicMessage - Returns whether the given message is a variadic message, 5024597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson/// where all arguments must be Objective-C types. 5034597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonbool 5044597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders CarlssonVariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const { 5054597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson const ObjCMethodDecl *MD = msg.getMethodDecl(); 5069281efe614741f3742ebf8196a703f6c923c6ff0Ted Kremenek 5079281efe614741f3742ebf8196a703f6c923c6ff0Ted Kremenek if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext())) 5084597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return false; 5094597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5104597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson Selector S = msg.getSelector(); 5114597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5124597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (msg.isInstanceMessage()) { 5134597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // FIXME: Ideally we'd look at the receiver interface here, but that's not 5144597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // useful for init, because alloc returns 'id'. In theory, this could lead 5154597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // to false positives, for example if there existed a class that had an 5164597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // initWithObjects: implementation that does accept non-Objective-C pointer 5174597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // types, but the chance of that happening is pretty small compared to the 5184597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // gains that this analysis gives. 5194597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson const ObjCInterfaceDecl *Class = MD->getClassInterface(); 5204597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5214597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSArray initWithObjects:] 5224597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSArray") && 5234597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == initWithObjectsS) 5244597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5254597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5264597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSDictionary initWithObjectsAndKeys:] 5274597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSDictionary") && 5284597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == initWithObjectsAndKeysS) 5294597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5304597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5314597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSSet initWithObjects:] 5324597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSSet") && 5334597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == initWithObjectsS) 5344597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5354597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson } else { 5364597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson const ObjCInterfaceDecl *Class = msg.getReceiverInterface(); 5374597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5384597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSArray arrayWithObjects:] 5394597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSArray") && 5404597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == arrayWithObjectsS) 5414597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5424597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5434597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSDictionary dictionaryWithObjectsAndKeys:] 5444597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSDictionary") && 5454597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == dictionaryWithObjectsAndKeysS) 5464597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5474597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5484597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // -[NSSet setWithObjects:] 5494597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (isReceiverClassOrSuperclass(Class, "NSSet") && 5504597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson S == setWithObjectsS) 5514597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return true; 5524597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson } 5534597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5544597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return false; 5554597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson} 5564597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5574597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonvoid VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, 5584597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson CheckerContext &C) const { 5594597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (!BT) { 5604597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson BT.reset(new APIMisuse("Arguments passed to variadic method aren't all " 5614597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson "Objective-C pointer types")); 5624597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5634597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson ASTContext &Ctx = C.getASTContext(); 5644597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx); 5654597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson dictionaryWithObjectsAndKeysS = 5664597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx); 5674597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson setWithObjectsS = GetUnarySelector("setWithObjects", Ctx); 5684597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5694597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson initWithObjectsS = GetUnarySelector("initWithObjects", Ctx); 5704597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson initWithObjectsAndKeysS = GetUnarySelector("initWithObjectsAndKeys", Ctx); 5714597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson } 5724597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5734597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (!isVariadicMessage(msg)) 5744597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return; 5754597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5764597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // We are not interested in the selector arguments since they have 5774597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // well-defined types, so the compiler will issue a warning for them. 5784597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson unsigned variadicArgsBegin = msg.getSelector().getNumArgs(); 5794597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5804597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // We're not interested in the last argument since it has to be nil or the 5814597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // compiler would have issued a warning for it elsewhere. 5824597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson unsigned variadicArgsEnd = msg.getNumArgs() - 1; 5834597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5844597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (variadicArgsEnd <= variadicArgsBegin) 5854597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson return; 5864597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 5874597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson // Verify that all arguments have Objective-C types. 5886fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek llvm::Optional<ExplodedNode*> errorNode; 589d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek const GRState *state = C.getState(); 5906fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek 5914597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) { 5924597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson QualType ArgTy = msg.getArgType(I); 5934597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (ArgTy->isObjCObjectPointerType()) 5944597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson continue; 5954597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 596f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson // Block pointers are treaded as Objective-C pointers. 597f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson if (ArgTy->isBlockPointerType()) 598f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson continue; 599f05982b5f8f69a1d618c3bd844ab6efd3a6e2953Anders Carlsson 600d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek // Ignore pointer constants. 601d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek if (isa<loc::ConcreteInt>(msg.getArgSVal(I, state))) 602d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek continue; 603928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek 604f3f929386254a53c398fa884848738113a73ca23Ted Kremenek // Ignore pointer types annotated with 'NSObject' attribute. 605f3f929386254a53c398fa884848738113a73ca23Ted Kremenek if (C.getASTContext().isObjCNSObjectType(ArgTy)) 606f3f929386254a53c398fa884848738113a73ca23Ted Kremenek continue; 607f3f929386254a53c398fa884848738113a73ca23Ted Kremenek 608928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek // Ignore CF references, which can be toll-free bridged. 6090556048ae8ff743d0abb9fa88a0d0ee8e9123742Ted Kremenek if (coreFoundation::isCFObjectRef(ArgTy)) 610928c415d5dde89b7c01e41f0dfa8a782cbfa8e7dTed Kremenek continue; 611d5fde2106af8e78cc1b97d6369ad0de5d0875491Ted Kremenek 6126fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek // Generate only one error node to use for all bug reports. 6136fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek if (!errorNode.hasValue()) { 6146fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek errorNode = C.generateNode(); 6156fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek } 6166fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek 6176fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek if (!errorNode.getValue()) 6184597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson continue; 6194597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6204597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson llvm::SmallString<128> sbuf; 6214597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson llvm::raw_svector_ostream os(sbuf); 6224597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6234597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson if (const char *TypeName = GetReceiverNameType(msg)) 6244597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson os << "Argument to '" << TypeName << "' method '"; 6254597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson else 6264597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson os << "Argument to method '"; 6274597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6284597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson os << msg.getSelector().getAsString() 6294597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson << "' should be an Objective-C pointer type, not '" 6304597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson << ArgTy.getAsString() << "'"; 6314597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6326fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek RangedBugReport *R = new RangedBugReport(*BT, os.str(), 6336fb5c1facaf36795a8c1050cd901e0e829ac1a64Ted Kremenek errorNode.getValue()); 6344597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson R->addRange(msg.getArgSourceRange(I)); 6354597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson C.EmitReport(R); 6364597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson } 6374597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson} 6384597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6394597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson//===----------------------------------------------------------------------===// 64078d46242e3351484c2b773f5610beba5d316914bTed Kremenek// Check registration. 64179b4f7d37530a1c41df26b6ac3a159f7cd6388d6Ted Kremenek//===----------------------------------------------------------------------===// 6420b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis 643695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerNilArgChecker(CheckerManager &mgr) { 64474eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mgr.registerChecker<NilArgChecker>(); 6450b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis} 6460b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis 647695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCFNumberCreateChecker(CheckerManager &mgr) { 64874eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mgr.registerChecker<CFNumberCreateChecker>(); 6490b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis} 6500b1ba6227c67d5e04b589ed8a08afa2345a40666Argyrios Kyrtzidis 651695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCFRetainReleaseChecker(CheckerManager &mgr) { 65274eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mgr.registerChecker<CFRetainReleaseChecker>(); 65378d46242e3351484c2b773f5610beba5d316914bTed Kremenek} 654695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis 655695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerClassReleaseChecker(CheckerManager &mgr) { 65674eed0ea03598cc5ef58b72fd5ed929631a11631Argyrios Kyrtzidis mgr.registerChecker<ClassReleaseChecker>(); 657695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis} 6584597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson 6594597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlssonvoid ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) { 6604597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson mgr.registerChecker<VariadicMethodTypeChecker>(); 6614597b7b28e3a71f3c4f0ee3a3bd6a34423e6f885Anders Carlsson} 662