CallAndMessageChecker.cpp revision 5251abea41b446c26e3239c8dd6c7edea6fc335d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (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)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This defines CallAndMessageChecker, a builtin checker that checks for various 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// errors of call and objc message expressions. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ClangSACheckers.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "clang/AST/ParentMap.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "clang/Basic/TargetInfo.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "llvm/ADT/SmallString.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/raw_ostream.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace ento; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CallAndMessageChecker 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::PreCall > { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_null; 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_undef; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_cxx_call_null; 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) mutable OwningPtr<BugType> BT_cxx_call_undef; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_call_arg; 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mutable OwningPtr<BugType> BT_msg_undef; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_objc_prop_undef; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_objc_subscript_undef; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mutable OwningPtr<BugType> BT_msg_arg; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable OwningPtr<BugType> BT_msg_ret; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)private: 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static bool PreVisitProcessArg(CheckerContext &C, SVal V, 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SourceRange argRange, const Expr *argEx, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsFirstArgument, bool checkUninitFields, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CallEvent &Call, OwningPtr<BugType> &BT); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg, 57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ExplodedNode *N) const; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleNilReceiver(CheckerContext &C, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMethodCall &msg) const; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static void LazyInit_BT(const char *desc, OwningPtr<BugType> &BT) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT.reset(new BuiltinBug(desc)); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end anonymous namespace 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Expr *BadE) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *N = C.generateSink(); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!N) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BugReport *R = new BugReport(*BT, BT->getName(), N); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BadE) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R->addRange(BadE->getSourceRange()); 792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (BadE->isGLValue()) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BadE = bugreporter::getDerefExpr(BadE); 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bugreporter::trackNullOrUndefValue(N, BadE, *R); 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) C.emitReport(R); 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static StringRef describeUninitializedArgumentInCall(const CallEvent &Call, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsFirstArgument) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (Call.getKind()) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CE_ObjCMessage: { 908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (Msg.getMessageKind()) { 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case OCM_Message: 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Argument in message expression is an uninitialized value"; 947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case OCM_PropertyAccess: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Msg.isSetter() && "Getters have no args"); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Argument for property setter is an uninitialized value"; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OCM_Subscript: 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (Msg.isSetter() && IsFirstArgument) 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return "Argument for subscript setter is an uninitialized value"; 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return "Subscript index is an uninitialized value"; 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) llvm_unreachable("Unknown message kind."); 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case CE_Block: 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return "Block call argument is an uninitialized value"; 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch default: 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "Function call argument is an uninitialized value"; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C, 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SVal V, SourceRange argRange, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *argEx, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsFirstArgument, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool checkUninitFields, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const CallEvent &Call, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OwningPtr<BugType> &BT) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (V.isUndef()) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink()) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LazyInit_BT("Uninitialized argument value", BT); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate a report for this bug. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringRef Desc = describeUninitializedArgumentInCall(Call, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsFirstArgument); 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BugReport *R = new BugReport(*BT, Desc, N); 12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) R->addRange(argRange); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (argEx) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bugreporter::trackNullOrUndefValue(N, argEx, *R); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) C.emitReport(R); 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!checkUninitFields) 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (llvm::Optional<nonloc::LazyCompoundVal> LV = 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) V.getAs<nonloc::LazyCompoundVal>()) { 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) class FindUninitializedField { 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public: 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SmallVector<const FieldDecl *, 10> FieldChain; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StoreManager &StoreMgr; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MemRegionManager &MrMgr; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Store store; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FindUninitializedField(StoreManager &storeMgr, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemRegionManager &mrMgr, Store s) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Find(const TypedValueRegion *R) { 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QualType T = R->getValueType(); 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (const RecordType *RT = T->getAsStructureType()) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RecordDecl *RD = RT->getDecl()->getDefinition(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(RD && "Referred record has no definition"); 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (RecordDecl::field_iterator I = 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RD->field_begin(), E = RD->field_end(); I!=E; ++I) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const FieldRegion *FR = MrMgr.getFieldRegion(*I, R); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.push_back(*I); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T = I->getType(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (T->getAsStructureType()) { 1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (Find(FR)) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else { 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR)); 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (V.isUndef()) 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return true; 170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.pop_back(); 172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }; 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LazyCompoundValData *D = LV->getCVData(); 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FindUninitializedField F(C.getState()->getStateManager().getStoreManager(), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.getSValBuilder().getRegionManager(), 1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) D->getStore()); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (F.Find(D->getRegion())) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink()) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LazyInit_BT("Uninitialized argument value", BT); 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SmallString<512> Str; 1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) llvm::raw_svector_ostream os(Str); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "Passed-by-value struct argument contains uninitialized data"; 1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (F.FieldChain.size() == 1) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << " (e.g., field: '" << *F.FieldChain[0] << "')"; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << " (e.g., via the field chain: '"; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first = true; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SmallVectorImpl<const FieldDecl *>::iterator 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first = false; 2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) else 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << '.'; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << **DI; 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch os << "')"; 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Generate a report for this bug. 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BugReport *R = new BugReport(*BT, os.str(), N); 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) R->addRange(argRange); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // FIXME: enhance track back for uninitialized value for arbitrary 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // memregions 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) C.emitReport(R); 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, 22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CheckerContext &C) const{ 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Expr *Callee = CE->getCallee()->IgnoreParens(); 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProgramStateRef State = C.getState(); 2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const LocationContext *LCtx = C.getLocationContext(); 2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SVal L = State->getSVal(Callee, LCtx); 2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (L.isUndef()) { 2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!BT_call_undef) 2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BT_call_undef.reset(new BuiltinBug("Called function pointer is an " 2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "uninitalized pointer value")); 2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch emitBadCall(BT_call_undef.get(), C, Callee); 2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProgramStateRef StNonNull, StNull; 2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch llvm::tie(StNonNull, StNull) = 2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch State->assume(L.castAs<DefinedOrUnknownSVal>()); 2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (StNull && !StNonNull) { 243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!BT_call_null) 244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BT_call_null.reset( 245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) new BuiltinBug("Called function pointer is null (null dereference)")); 24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) emitBadCall(BT_call_null.get(), C, Callee); 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) C.addTransition(StNonNull); 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::checkPreCall(const CallEvent &Call, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext &C) const { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef State = C.getState(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a call to a C++ method, check if the callee is null or 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // undefined. 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = CC->getCXXThisVal(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (V.isUndef()) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT_cxx_call_undef) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_cxx_call_undef.reset(new BuiltinBug("Called C++ object pointer is " 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uninitialized")); 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr()); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 266558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProgramStateRef StNonNull, StNull; 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) llvm::tie(StNonNull, StNull) = 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) State->assume(V.castAs<DefinedOrUnknownSVal>()); 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StNull && !StNonNull) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT_cxx_call_null) 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer " 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "is null")); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr()); 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) State = StNonNull; 2810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Don't check for uninitialized field values in arguments if the 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caller has a body that is available and we have the chance to inline it. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a hack, but is a reasonable compromise betweens sometimes warning 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and sometimes not depending on if we decide to inline a function. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Decl *D = Call.getDecl(); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool checkUninitFields = 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody())); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OwningPtr<BugType> *BT; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isa<ObjCMethodCall>(Call)) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT = &BT_msg_arg; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT = &BT_call_arg; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i), 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Call.getArgExpr(i), /*IsFirstArgument=*/i == 0, 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkUninitFields, Call, *BT)) 301c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return; 302c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 303c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // If we make it here, record our assumptions about the callee. 304c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch C.addTransition(State); 305c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 306c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg, 308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CheckerContext &C) const { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal recVal = msg.getReceiverSVal(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recVal.isUndef()) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink()) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugType *BT = 0; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (msg.getMessageKind()) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OCM_Message: 3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!BT_msg_undef) 3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu BT_msg_undef.reset(new BuiltinBug("Receiver in message expression " 3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "is an uninitialized value")); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT = BT_msg_undef.get(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OCM_PropertyAccess: 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT_objc_prop_undef) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_objc_prop_undef.reset(new BuiltinBug("Property access on an " 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uninitialized object " 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pointer")); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT = BT_objc_prop_undef.get(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case OCM_Subscript: 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT_objc_subscript_undef) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_objc_subscript_undef.reset(new BuiltinBug("Subscript access on an " 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uninitialized object " 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pointer")); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT = BT_objc_subscript_undef.get(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(BT && "Unknown message kind."); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReport *R = new BugReport(*BT, BT->getName(), N); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessageExpr *ME = msg.getOriginExpr(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R->addRange(ME->getReceiverRange()); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const Expr *ReceiverE = ME->getInstanceReceiver()) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bugreporter::trackNullOrUndefValue(N, ReceiverE, *R); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.emitReport(R); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bifurcate the state into nil and non-nil ones. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefinedOrUnknownSVal receiverVal = recVal.castAs<DefinedOrUnknownSVal>(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ProgramStateRef state = C.getState(); 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ProgramStateRef notNilState, nilState; 3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) llvm::tie(notNilState, nilState) = state->assume(receiverVal); 3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Handle receiver must be nil. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nilState && !notNilState) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleNilReceiver(C, state, msg); 3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMethodCall &msg, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *N) const { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT_msg_ret) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT_msg_ret.reset( 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BuiltinBug("Receiver in message expression is " 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'nil' and returns a garbage value")); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessageExpr *ME = msg.getOriginExpr(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SmallString<200> buf; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::raw_svector_ostream os(buf); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "The receiver of message '" << ME->getSelector().getAsString() 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' is nil and returns a value of type '"; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.getResultType().print(os, C.getLangOpts()); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "' that will be garbage"; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReport *report = new BugReport(*BT_msg_ret, os.str(), N); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report->addRange(ME->getReceiverRange()); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: This won't track "self" in messages to super. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const Expr *receiver = ME->getInstanceReceiver()) { 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bugreporter::trackNullOrUndefValue(N, receiver, *report); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.emitReport(report); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool supportsNilWithFloatRet(const llvm::Triple &triple) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (triple.getVendor() == llvm::Triple::Apple && 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (triple.getOS() == llvm::Triple::IOS || 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !triple.isMacOSXVersionLT(10,5))); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramStateRef state, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMethodCall &Msg) const { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASTContext &Ctx = C.getASTContext(); 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the return type of the message expression. A message to nil will 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return different values depending on the return type and the architecture. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType RetTy = Msg.getResultType(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CanQualType CanRetTy = Ctx.getCanonicalType(RetTy); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LocationContext *LCtx = C.getLocationContext(); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CanRetTy->isStructureOrClassType()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Structure returns are safe since the compiler zeroes them out. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = C.getSValBuilder().makeZeroVal(RetTy); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other cases: check if sizeof(return type) > sizeof(void*) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap() 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .isConsumedExpr(Msg.getOriginExpr())) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute: sizeof(void *) and sizeof(return type) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (voidPtrSize < returnTypeSize && 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) && 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (Ctx.FloatTy == CanRetTy || 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.DoubleTy == CanRetTy || 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.LongDoubleTy == CanRetTy || 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.LongLongTy == CanRetTy || 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ctx.UnsignedLongLongTy == CanRetTy))) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExplodedNode *N = C.generateSink(state)) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) emitNilReceiverBug(C, Msg, N); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Handle the safe cases where the return value is 0 if the 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // receiver is nil. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: For now take the conservative approach that we only 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return null values if we *know* that the receiver is nil. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is because we can have surprises like: 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... = [[NSScreens screens] objectAtIndex:0]; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // What can happen is that [... screens] could return nil, but 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it most likely isn't nil. We should assume the semantics 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of this case unless we have *a lot* more knowledge. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal V = C.getSValBuilder().makeZeroVal(RetTy); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V)); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.addTransition(state); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ento::registerCallAndMessageChecker(CheckerManager &mgr) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mgr.registerChecker<CallAndMessageChecker>(); 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)