CallAndMessageChecker.cpp revision fe6a011a113b3ddcb32f42af152d7476054e7f79
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// This defines CallAndMessageChecker, a builtin checker that checks for various 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// errors of call and objc message expressions. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ClangSACheckers.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "clang/AST/ParentMap.h" 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "clang/Basic/TargetInfo.h" 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "llvm/ADT/SmallString.h" 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CallAndMessageChecker 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::PreCall > { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_null; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_undef; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_arg; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_msg_undef; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_objc_prop_undef; 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mutable OwningPtr<BugType> BT_msg_arg; 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mutable OwningPtr<BugType> BT_msg_ret; 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochpublic: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool PreVisitProcessArg(CheckerContext &C, SVal V, 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SourceRange argRange, const Expr *argEx, 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const bool checkUninitFields, 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const char *BT_desc, OwningPtr<BugType> &BT); 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE); 52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg, 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExplodedNode *N) const; 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void HandleNilReceiver(CheckerContext &C, 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ProgramStateRef state, 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const ObjCMethodCall &msg) const; 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static void LazyInit_BT(const char *desc, OwningPtr<BugType> &BT) { 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!BT) 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BT.reset(new BuiltinBug(desc)); 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // end anonymous namespace 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C, 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const CallExpr *CE) { 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExplodedNode *N = C.generateSink(); 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!N) 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BugReport *R = new BugReport(*BT, BT->getName(), N); 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bugreporter::GetCalleeExpr(N), R)); 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch C.EmitReport(R); 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SVal V, SourceRange argRange, 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const Expr *argEx, 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const bool checkUninitFields, 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const char *BT_desc, 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OwningPtr<BugType> &BT) { 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (V.isUndef()) { 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (ExplodedNode *N = C.generateSink()) { 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LazyInit_BT("Uninitialized argument value", BT); 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Generate a report for this bug. 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BugReport *R = new BugReport(*BT, BT_desc, N); 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch R->addRange(argRange); 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (argEx) 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx, 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch R)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.EmitReport(R); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!checkUninitFields) 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (const nonloc::LazyCompoundVal *LV = 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dyn_cast<nonloc::LazyCompoundVal>(&V)) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class FindUninitializedField { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SmallVector<const FieldDecl *, 10> FieldChain; 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StoreManager &StoreMgr; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemRegionManager &MrMgr; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Store store; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindUninitializedField(StoreManager &storeMgr, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemRegionManager &mrMgr, Store s) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Find(const TypedValueRegion *R) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType T = R->getValueType(); 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (const RecordType *RT = T->getAsStructureType()) { 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const RecordDecl *RD = RT->getDecl()->getDefinition(); 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch assert(RD && "Referred record has no definition"); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RecordDecl::field_iterator I = 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RD->field_begin(), E = RD->field_end(); I!=E; ++I) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FieldRegion *FR = MrMgr.getFieldRegion(*I, R); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.push_back(*I); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T = I->getType(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (T->getAsStructureType()) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Find(FR)) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch else { 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR)); 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (V.isUndef()) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.pop_back(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const LazyCompoundValData *D = LV->getCVData(); 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch FindUninitializedField F(C.getState()->getStateManager().getStoreManager(), 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.getSValBuilder().getRegionManager(), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D->getStore()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (F.Find(D->getRegion())) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink()) { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LazyInit_BT(BT_desc, BT); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SmallString<512> Str; 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) llvm::raw_svector_ostream os(Str); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os << "Passed-by-value struct argument contains uninitialized data"; 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (F.FieldChain.size() == 1) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os << " (e.g., field: '" << *F.FieldChain[0] << "')"; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else { 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os << " (e.g., via the field chain: '"; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool first = true; 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (SmallVectorImpl<const FieldDecl *>::iterator 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first = false; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << '.'; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << **DI; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "')"; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Generate a report for this bug. 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BugReport *R = new BugReport(*BT, os.str(), N); 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch R->addRange(argRange); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: enhance track back for uninitialized value for arbitrary 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // memregions 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) C.EmitReport(R); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext &C) const{ 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Expr *Callee = CE->getCallee()->IgnoreParens(); 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramStateRef State = C.getState(); 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const LocationContext *LCtx = C.getLocationContext(); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal L = State->getSVal(Callee, LCtx); 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (L.isUndef()) { 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BT_call_undef) 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BT_call_undef.reset(new BuiltinBug("Called function pointer is an " 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "uninitalized pointer value")); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EmitBadCall(BT_call_undef.get(), C, CE); 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (L.isZeroConstant()) { 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!BT_call_null) 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) BT_call_null.reset( 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new BuiltinBug("Called function pointer is null (null dereference)")); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EmitBadCall(BT_call_null.get(), C, CE); 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CallAndMessageChecker::checkPreCall(const CallEvent &Call, 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext &C) const { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Don't check for uninitialized field values in arguments if the 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // caller has a body that is available and we have the chance to inline it. 2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This is a hack, but is a reasonable compromise betweens sometimes warning 2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // and sometimes not depending on if we decide to inline a function. 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Decl *D = Call.getDecl(); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool checkUninitFields = 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !(C.getAnalysisManager().shouldInlineCall() && 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (D && D->getBody())); 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OwningPtr<BugType> *BT; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *Desc; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (Call.getKind()) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CE_ObjCPropertyAccess: 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BT = &BT_msg_arg; 228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Getters do not have arguments, so we don't need to worry about this. 2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Desc = "Argument for property setter is an uninitialized value"; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case CE_ObjCMessage: 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BT = &BT_msg_arg; 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Desc = "Argument in message expression is an uninitialized value"; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case CE_Block: 2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BT = &BT_call_arg; 2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Desc = "Block call argument is an uninitialized value"; 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BT = &BT_call_arg; 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Desc = "Function call argument is an uninitialized value"; 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (PreVisitProcessArg(C, Call.getArgSVal(i), 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Call.getArgSourceRange(i), Call.getArgExpr(i), 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch checkUninitFields, Desc, *BT)) 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg, 253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckerContext &C) const { 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SVal recVal = msg.getReceiverSVal(); 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (recVal.isUndef()) { 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ExplodedNode *N = C.generateSink()) { 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BugType *BT = 0; 2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (isa<ObjCPropertyAccess>(msg)) { 2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!BT_objc_prop_undef) 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BT_objc_prop_undef.reset(new BuiltinBug("Property access on an " 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "uninitialized object pointer")); 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BT = BT_objc_prop_undef.get(); 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!BT_msg_undef) 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BT_msg_undef.reset(new BuiltinBug("Receiver in message expression " 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "is an uninitialized value")); 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BT = BT_msg_undef.get(); 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BugReport *R = new BugReport(*BT, BT->getName(), N); 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) R->addRange(msg.getReceiverSourceRange()); 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet. 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (const Expr *ReceiverE = msg.getInstanceReceiverExpr()) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceiverE, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R)); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.EmitReport(R); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bifurcate the state into nil and non-nil ones. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state = C.getState(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef notNilState, nilState; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::tie(notNilState, nilState) = state->assume(receiverVal); 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Handle receiver must be nil. 289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (nilState && !notNilState) { 290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HandleNilReceiver(C, state, msg); 291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMethodCall &msg, 298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExplodedNode *N) const { 299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!BT_msg_ret) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_msg_ret.reset( 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BuiltinBug("Receiver in message expression is " 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'nil' and returns a garbage value")); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SmallString<200> buf; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::raw_svector_ostream os(buf); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "The receiver of message '" << msg.getSelector().getAsString() 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' is nil and returns a value of type '"; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.getResultType().print(os, C.getLangOpts()); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "' that will be garbage"; 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BugReport *report = new BugReport(*BT_msg_ret, os.str(), N); 3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // FIXME: This won't track "self" in messages to super. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const Expr *receiver = msg.getInstanceReceiverExpr()) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report->addRange(receiver->getSourceRange()); 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch receiver, 318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch report)); 319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch C.EmitReport(report); 321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool supportsNilWithFloatRet(const llvm::Triple &triple) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (triple.getVendor() == llvm::Triple::Apple && 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (triple.getOS() == llvm::Triple::IOS || 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !triple.isMacOSXVersionLT(10,5))); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state, 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMethodCall &Msg) const { 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASTContext &Ctx = C.getASTContext(); 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the return type of the message expression. A message to nil will 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return different values depending on the return type and the architecture. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType RetTy = Msg.getResultType(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CanQualType CanRetTy = Ctx.getCanonicalType(RetTy); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *LCtx = C.getLocationContext(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (CanRetTy->isStructureOrClassType()) { 3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Structure returns are safe since the compiler zeroes them out. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = C.getSValBuilder().makeZeroVal(RetTy); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V)); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Other cases: check if sizeof(return type) > sizeof(void*) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap() 349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .isConsumedExpr(Msg.getOriginExpr())) { 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Compute: sizeof(void *) and sizeof(return type) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (voidPtrSize < returnTypeSize && 3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) && 3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (Ctx.FloatTy == CanRetTy || 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.DoubleTy == CanRetTy || 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.LongDoubleTy == CanRetTy || 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.LongLongTy == CanRetTy || 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.UnsignedLongLongTy == CanRetTy))) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink(state)) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) emitNilReceiverBug(C, Msg, N); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Handle the safe cases where the return value is 0 if the 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // receiver is nil. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: For now take the conservative approach that we only 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return null values if we *know* that the receiver is nil. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is because we can have surprises like: 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... = [[NSScreens screens] objectAtIndex:0]; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // What can happen is that [... screens] could return nil, but 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it most likely isn't nil. We should assume the semantics 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of this case unless we have *a lot* more knowledge. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = C.getSValBuilder().makeZeroVal(RetTy); 3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V)); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.addTransition(state); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ento::registerCallAndMessageChecker(CheckerManager &mgr) { 3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mgr.registerChecker<CallAndMessageChecker>(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)