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)