Home | History | Annotate | Line # | Download | only in Checkers
      1 //===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This defines CallAndMessageChecker, a builtin checker that checks for various
     10 // errors of call and objc message expressions.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/AST/ExprCXX.h"
     15 #include "clang/AST/ParentMap.h"
     16 #include "clang/Basic/TargetInfo.h"
     17 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
     18 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
     19 #include "clang/StaticAnalyzer/Core/Checker.h"
     20 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
     21 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
     22 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
     23 #include "llvm/ADT/SmallString.h"
     24 #include "llvm/ADT/StringExtras.h"
     25 #include "llvm/Support/Casting.h"
     26 #include "llvm/Support/raw_ostream.h"
     27 
     28 using namespace clang;
     29 using namespace ento;
     30 
     31 namespace {
     32 
     33 class CallAndMessageChecker
     34     : public Checker<check::PreObjCMessage, check::ObjCMessageNil,
     35                      check::PreCall> {
     36   mutable std::unique_ptr<BugType> BT_call_null;
     37   mutable std::unique_ptr<BugType> BT_call_undef;
     38   mutable std::unique_ptr<BugType> BT_cxx_call_null;
     39   mutable std::unique_ptr<BugType> BT_cxx_call_undef;
     40   mutable std::unique_ptr<BugType> BT_call_arg;
     41   mutable std::unique_ptr<BugType> BT_cxx_delete_undef;
     42   mutable std::unique_ptr<BugType> BT_msg_undef;
     43   mutable std::unique_ptr<BugType> BT_objc_prop_undef;
     44   mutable std::unique_ptr<BugType> BT_objc_subscript_undef;
     45   mutable std::unique_ptr<BugType> BT_msg_arg;
     46   mutable std::unique_ptr<BugType> BT_msg_ret;
     47   mutable std::unique_ptr<BugType> BT_call_few_args;
     48 
     49 public:
     50   // These correspond with the checker options. Looking at other checkers such
     51   // as MallocChecker and CStringChecker, this is similar as to how they pull
     52   // off having a modeling class, but emitting diagnostics under a smaller
     53   // checker's name that can be safely disabled without disturbing the
     54   // underlaying modeling engine.
     55   // The reason behind having *checker options* rather then actual *checkers*
     56   // here is that CallAndMessage is among the oldest checkers out there, and can
     57   // be responsible for the majority of the reports on any given project. This
     58   // is obviously not ideal, but changing checker name has the consequence of
     59   // changing the issue hashes associated with the reports, and databases
     60   // relying on this (CodeChecker, for instance) would suffer greatly.
     61   // If we ever end up making changes to the issue hash generation algorithm, or
     62   // the warning messages here, we should totally jump on the opportunity to
     63   // convert these to actual checkers.
     64   enum CheckKind {
     65     CK_FunctionPointer,
     66     CK_ParameterCount,
     67     CK_CXXThisMethodCall,
     68     CK_CXXDeallocationArg,
     69     CK_ArgInitializedness,
     70     CK_ArgPointeeInitializedness,
     71     CK_NilReceiver,
     72     CK_UndefReceiver,
     73     CK_NumCheckKinds
     74   };
     75 
     76   DefaultBool ChecksEnabled[CK_NumCheckKinds];
     77   // The original core.CallAndMessage checker name. This should rather be an
     78   // array, as seen in MallocChecker and CStringChecker.
     79   CheckerNameRef OriginalName;
     80 
     81   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
     82 
     83   /// Fill in the return value that results from messaging nil based on the
     84   /// return type and architecture and diagnose if the return value will be
     85   /// garbage.
     86   void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const;
     87 
     88   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
     89 
     90   ProgramStateRef checkFunctionPointerCall(const CallExpr *CE,
     91                                            CheckerContext &C,
     92                                            ProgramStateRef State) const;
     93 
     94   ProgramStateRef checkCXXMethodCall(const CXXInstanceCall *CC,
     95                                      CheckerContext &C,
     96                                      ProgramStateRef State) const;
     97 
     98   ProgramStateRef checkParameterCount(const CallEvent &Call, CheckerContext &C,
     99                                       ProgramStateRef State) const;
    100 
    101   ProgramStateRef checkCXXDeallocation(const CXXDeallocatorCall *DC,
    102                                        CheckerContext &C,
    103                                        ProgramStateRef State) const;
    104 
    105   ProgramStateRef checkArgInitializedness(const CallEvent &Call,
    106                                           CheckerContext &C,
    107                                           ProgramStateRef State) const;
    108 
    109 private:
    110   bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange,
    111                           const Expr *ArgEx, int ArgumentNumber,
    112                           bool CheckUninitFields, const CallEvent &Call,
    113                           std::unique_ptr<BugType> &BT,
    114                           const ParmVarDecl *ParamDecl) const;
    115 
    116   static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE);
    117   void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
    118                           ExplodedNode *N) const;
    119 
    120   void HandleNilReceiver(CheckerContext &C,
    121                          ProgramStateRef state,
    122                          const ObjCMethodCall &msg) const;
    123 
    124   void LazyInit_BT(const char *desc, std::unique_ptr<BugType> &BT) const {
    125     if (!BT)
    126       BT.reset(new BuiltinBug(OriginalName, desc));
    127   }
    128   bool uninitRefOrPointer(CheckerContext &C, const SVal &V,
    129                           SourceRange ArgRange, const Expr *ArgEx,
    130                           std::unique_ptr<BugType> &BT,
    131                           const ParmVarDecl *ParamDecl, const char *BD,
    132                           int ArgumentNumber) const;
    133 };
    134 } // end anonymous namespace
    135 
    136 void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
    137                                         const Expr *BadE) {
    138   ExplodedNode *N = C.generateErrorNode();
    139   if (!N)
    140     return;
    141 
    142   auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
    143   if (BadE) {
    144     R->addRange(BadE->getSourceRange());
    145     if (BadE->isGLValue())
    146       BadE = bugreporter::getDerefExpr(BadE);
    147     bugreporter::trackExpressionValue(N, BadE, *R);
    148   }
    149   C.emitReport(std::move(R));
    150 }
    151 
    152 static void describeUninitializedArgumentInCall(const CallEvent &Call,
    153                                                 int ArgumentNumber,
    154                                                 llvm::raw_svector_ostream &Os) {
    155   switch (Call.getKind()) {
    156   case CE_ObjCMessage: {
    157     const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
    158     switch (Msg.getMessageKind()) {
    159     case OCM_Message:
    160       Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
    161          << " argument in message expression is an uninitialized value";
    162       return;
    163     case OCM_PropertyAccess:
    164       assert(Msg.isSetter() && "Getters have no args");
    165       Os << "Argument for property setter is an uninitialized value";
    166       return;
    167     case OCM_Subscript:
    168       if (Msg.isSetter() && (ArgumentNumber == 0))
    169         Os << "Argument for subscript setter is an uninitialized value";
    170       else
    171         Os << "Subscript index is an uninitialized value";
    172       return;
    173     }
    174     llvm_unreachable("Unknown message kind.");
    175   }
    176   case CE_Block:
    177     Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
    178        << " block call argument is an uninitialized value";
    179     return;
    180   default:
    181     Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
    182        << " function call argument is an uninitialized value";
    183     return;
    184   }
    185 }
    186 
    187 bool CallAndMessageChecker::uninitRefOrPointer(
    188     CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx,
    189     std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD,
    190     int ArgumentNumber) const {
    191 
    192   // The pointee being uninitialized is a sign of code smell, not a bug, no need
    193   // to sink here.
    194   if (!ChecksEnabled[CK_ArgPointeeInitializedness])
    195     return false;
    196 
    197   // No parameter declaration available, i.e. variadic function argument.
    198   if(!ParamDecl)
    199     return false;
    200 
    201   // If parameter is declared as pointer to const in function declaration,
    202   // then check if corresponding argument in function call is
    203   // pointing to undefined symbol value (uninitialized memory).
    204   SmallString<200> Buf;
    205   llvm::raw_svector_ostream Os(Buf);
    206 
    207   if (ParamDecl->getType()->isPointerType()) {
    208     Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
    209        << " function call argument is a pointer to uninitialized value";
    210   } else if (ParamDecl->getType()->isReferenceType()) {
    211     Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
    212        << " function call argument is an uninitialized value";
    213   } else
    214     return false;
    215 
    216   if(!ParamDecl->getType()->getPointeeType().isConstQualified())
    217     return false;
    218 
    219   if (const MemRegion *SValMemRegion = V.getAsRegion()) {
    220     const ProgramStateRef State = C.getState();
    221     const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
    222     if (PSV.isUndef()) {
    223       if (ExplodedNode *N = C.generateErrorNode()) {
    224         LazyInit_BT(BD, BT);
    225         auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);
    226         R->addRange(ArgRange);
    227         if (ArgEx)
    228           bugreporter::trackExpressionValue(N, ArgEx, *R);
    229 
    230         C.emitReport(std::move(R));
    231       }
    232       return true;
    233     }
    234   }
    235   return false;
    236 }
    237 
    238 namespace {
    239 class FindUninitializedField {
    240 public:
    241   SmallVector<const FieldDecl *, 10> FieldChain;
    242 
    243 private:
    244   StoreManager &StoreMgr;
    245   MemRegionManager &MrMgr;
    246   Store store;
    247 
    248 public:
    249   FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
    250                          Store s)
    251       : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
    252 
    253   bool Find(const TypedValueRegion *R) {
    254     QualType T = R->getValueType();
    255     if (const RecordType *RT = T->getAsStructureType()) {
    256       const RecordDecl *RD = RT->getDecl()->getDefinition();
    257       assert(RD && "Referred record has no definition");
    258       for (const auto *I : RD->fields()) {
    259         const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
    260         FieldChain.push_back(I);
    261         T = I->getType();
    262         if (T->getAsStructureType()) {
    263           if (Find(FR))
    264             return true;
    265         } else {
    266           const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
    267           if (V.isUndef())
    268             return true;
    269         }
    270         FieldChain.pop_back();
    271       }
    272     }
    273 
    274     return false;
    275   }
    276 };
    277 } // namespace
    278 
    279 bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
    280                                                SVal V,
    281                                                SourceRange ArgRange,
    282                                                const Expr *ArgEx,
    283                                                int ArgumentNumber,
    284                                                bool CheckUninitFields,
    285                                                const CallEvent &Call,
    286                                                std::unique_ptr<BugType> &BT,
    287                                                const ParmVarDecl *ParamDecl
    288                                                ) const {
    289   const char *BD = "Uninitialized argument value";
    290 
    291   if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD,
    292                          ArgumentNumber))
    293     return true;
    294 
    295   if (V.isUndef()) {
    296     if (!ChecksEnabled[CK_ArgInitializedness]) {
    297       C.addSink();
    298       return true;
    299     }
    300     if (ExplodedNode *N = C.generateErrorNode()) {
    301       LazyInit_BT(BD, BT);
    302       // Generate a report for this bug.
    303       SmallString<200> Buf;
    304       llvm::raw_svector_ostream Os(Buf);
    305       describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
    306       auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);
    307 
    308       R->addRange(ArgRange);
    309       if (ArgEx)
    310         bugreporter::trackExpressionValue(N, ArgEx, *R);
    311       C.emitReport(std::move(R));
    312     }
    313     return true;
    314   }
    315 
    316   if (!CheckUninitFields)
    317     return false;
    318 
    319   if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
    320     const LazyCompoundValData *D = LV->getCVData();
    321     FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
    322                              C.getSValBuilder().getRegionManager(),
    323                              D->getStore());
    324 
    325     if (F.Find(D->getRegion())) {
    326       if (!ChecksEnabled[CK_ArgInitializedness]) {
    327         C.addSink();
    328         return true;
    329       }
    330       if (ExplodedNode *N = C.generateErrorNode()) {
    331         LazyInit_BT(BD, BT);
    332         SmallString<512> Str;
    333         llvm::raw_svector_ostream os(Str);
    334         os << "Passed-by-value struct argument contains uninitialized data";
    335 
    336         if (F.FieldChain.size() == 1)
    337           os << " (e.g., field: '" << *F.FieldChain[0] << "')";
    338         else {
    339           os << " (e.g., via the field chain: '";
    340           bool first = true;
    341           for (SmallVectorImpl<const FieldDecl *>::iterator
    342                DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
    343             if (first)
    344               first = false;
    345             else
    346               os << '.';
    347             os << **DI;
    348           }
    349           os << "')";
    350         }
    351 
    352         // Generate a report for this bug.
    353         auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
    354         R->addRange(ArgRange);
    355 
    356         if (ArgEx)
    357           bugreporter::trackExpressionValue(N, ArgEx, *R);
    358         // FIXME: enhance track back for uninitialized value for arbitrary
    359         // memregions
    360         C.emitReport(std::move(R));
    361       }
    362       return true;
    363     }
    364   }
    365 
    366   return false;
    367 }
    368 
    369 ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
    370     const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const {
    371 
    372   const Expr *Callee = CE->getCallee()->IgnoreParens();
    373   const LocationContext *LCtx = C.getLocationContext();
    374   SVal L = State->getSVal(Callee, LCtx);
    375 
    376   if (L.isUndef()) {
    377     if (!ChecksEnabled[CK_FunctionPointer]) {
    378       C.addSink(State);
    379       return nullptr;
    380     }
    381     if (!BT_call_undef)
    382       BT_call_undef.reset(new BuiltinBug(
    383           OriginalName,
    384           "Called function pointer is an uninitialized pointer value"));
    385     emitBadCall(BT_call_undef.get(), C, Callee);
    386     return nullptr;
    387   }
    388 
    389   ProgramStateRef StNonNull, StNull;
    390   std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());
    391 
    392   if (StNull && !StNonNull) {
    393     if (!ChecksEnabled[CK_FunctionPointer]) {
    394       C.addSink(StNull);
    395       return nullptr;
    396     }
    397     if (!BT_call_null)
    398       BT_call_null.reset(new BuiltinBug(
    399           OriginalName, "Called function pointer is null (null dereference)"));
    400     emitBadCall(BT_call_null.get(), C, Callee);
    401     return nullptr;
    402   }
    403 
    404   return StNonNull;
    405 }
    406 
    407 ProgramStateRef CallAndMessageChecker::checkParameterCount(
    408     const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
    409 
    410   // If we have a function or block declaration, we can make sure we pass
    411   // enough parameters.
    412   unsigned Params = Call.parameters().size();
    413   if (Call.getNumArgs() >= Params)
    414     return State;
    415 
    416   if (!ChecksEnabled[CK_ParameterCount]) {
    417     C.addSink(State);
    418     return nullptr;
    419   }
    420 
    421   ExplodedNode *N = C.generateErrorNode();
    422   if (!N)
    423     return nullptr;
    424 
    425   LazyInit_BT("Function call with too few arguments", BT_call_few_args);
    426 
    427   SmallString<512> Str;
    428   llvm::raw_svector_ostream os(Str);
    429   if (isa<AnyFunctionCall>(Call)) {
    430     os << "Function ";
    431   } else {
    432     assert(isa<BlockCall>(Call));
    433     os << "Block ";
    434   }
    435   os << "taking " << Params << " argument" << (Params == 1 ? "" : "s")
    436      << " is called with fewer (" << Call.getNumArgs() << ")";
    437 
    438   C.emitReport(
    439       std::make_unique<PathSensitiveBugReport>(*BT_call_few_args, os.str(), N));
    440   return nullptr;
    441 }
    442 
    443 ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
    444     const CXXInstanceCall *CC, CheckerContext &C, ProgramStateRef State) const {
    445 
    446   SVal V = CC->getCXXThisVal();
    447   if (V.isUndef()) {
    448     if (!ChecksEnabled[CK_CXXThisMethodCall]) {
    449       C.addSink(State);
    450       return nullptr;
    451     }
    452     if (!BT_cxx_call_undef)
    453       BT_cxx_call_undef.reset(new BuiltinBug(
    454           OriginalName, "Called C++ object pointer is uninitialized"));
    455     emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
    456     return nullptr;
    457   }
    458 
    459   ProgramStateRef StNonNull, StNull;
    460   std::tie(StNonNull, StNull) = State->assume(V.castAs<DefinedOrUnknownSVal>());
    461 
    462   if (StNull && !StNonNull) {
    463     if (!ChecksEnabled[CK_CXXThisMethodCall]) {
    464       C.addSink(StNull);
    465       return nullptr;
    466     }
    467     if (!BT_cxx_call_null)
    468       BT_cxx_call_null.reset(
    469           new BuiltinBug(OriginalName, "Called C++ object pointer is null"));
    470     emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
    471     return nullptr;
    472   }
    473 
    474   return StNonNull;
    475 }
    476 
    477 ProgramStateRef
    478 CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC,
    479                                             CheckerContext &C,
    480                                             ProgramStateRef State) const {
    481   const CXXDeleteExpr *DE = DC->getOriginExpr();
    482   assert(DE);
    483   SVal Arg = C.getSVal(DE->getArgument());
    484   if (!Arg.isUndef())
    485     return State;
    486 
    487   if (!ChecksEnabled[CK_CXXDeallocationArg]) {
    488     C.addSink(State);
    489     return nullptr;
    490   }
    491 
    492   StringRef Desc;
    493   ExplodedNode *N = C.generateErrorNode();
    494   if (!N)
    495     return nullptr;
    496   if (!BT_cxx_delete_undef)
    497     BT_cxx_delete_undef.reset(
    498         new BuiltinBug(OriginalName, "Uninitialized argument value"));
    499   if (DE->isArrayFormAsWritten())
    500     Desc = "Argument to 'delete[]' is uninitialized";
    501   else
    502     Desc = "Argument to 'delete' is uninitialized";
    503   BugType *BT = BT_cxx_delete_undef.get();
    504   auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
    505   bugreporter::trackExpressionValue(N, DE, *R);
    506   C.emitReport(std::move(R));
    507   return nullptr;
    508 }
    509 
    510 ProgramStateRef CallAndMessageChecker::checkArgInitializedness(
    511     const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
    512 
    513   const Decl *D = Call.getDecl();
    514 
    515   // Don't check for uninitialized field values in arguments if the
    516   // caller has a body that is available and we have the chance to inline it.
    517   // This is a hack, but is a reasonable compromise betweens sometimes warning
    518   // and sometimes not depending on if we decide to inline a function.
    519   const bool checkUninitFields =
    520       !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
    521 
    522   std::unique_ptr<BugType> *BT;
    523   if (isa<ObjCMethodCall>(Call))
    524     BT = &BT_msg_arg;
    525   else
    526     BT = &BT_call_arg;
    527 
    528   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
    529   for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
    530     const ParmVarDecl *ParamDecl = nullptr;
    531     if (FD && i < FD->getNumParams())
    532       ParamDecl = FD->getParamDecl(i);
    533     if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
    534                            Call.getArgExpr(i), i, checkUninitFields, Call, *BT,
    535                            ParamDecl))
    536       return nullptr;
    537   }
    538   return State;
    539 }
    540 
    541 void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
    542                                          CheckerContext &C) const {
    543   ProgramStateRef State = C.getState();
    544 
    545   if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()))
    546     State = checkFunctionPointerCall(CE, C, State);
    547 
    548   if (!State)
    549     return;
    550 
    551   if (Call.getDecl())
    552     State = checkParameterCount(Call, C, State);
    553 
    554   if (!State)
    555     return;
    556 
    557   if (const auto *CC = dyn_cast<CXXInstanceCall>(&Call))
    558     State = checkCXXMethodCall(CC, C, State);
    559 
    560   if (!State)
    561     return;
    562 
    563   if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call))
    564     State = checkCXXDeallocation(DC, C, State);
    565 
    566   if (!State)
    567     return;
    568 
    569   State = checkArgInitializedness(Call, C, State);
    570 
    571   // If we make it here, record our assumptions about the callee.
    572   C.addTransition(State);
    573 }
    574 
    575 void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
    576                                                 CheckerContext &C) const {
    577   SVal recVal = msg.getReceiverSVal();
    578   if (recVal.isUndef()) {
    579     if (!ChecksEnabled[CK_UndefReceiver]) {
    580       C.addSink();
    581       return;
    582     }
    583     if (ExplodedNode *N = C.generateErrorNode()) {
    584       BugType *BT = nullptr;
    585       switch (msg.getMessageKind()) {
    586       case OCM_Message:
    587         if (!BT_msg_undef)
    588           BT_msg_undef.reset(new BuiltinBug(OriginalName,
    589                                             "Receiver in message expression "
    590                                             "is an uninitialized value"));
    591         BT = BT_msg_undef.get();
    592         break;
    593       case OCM_PropertyAccess:
    594         if (!BT_objc_prop_undef)
    595           BT_objc_prop_undef.reset(new BuiltinBug(
    596               OriginalName,
    597               "Property access on an uninitialized object pointer"));
    598         BT = BT_objc_prop_undef.get();
    599         break;
    600       case OCM_Subscript:
    601         if (!BT_objc_subscript_undef)
    602           BT_objc_subscript_undef.reset(new BuiltinBug(
    603               OriginalName,
    604               "Subscript access on an uninitialized object pointer"));
    605         BT = BT_objc_subscript_undef.get();
    606         break;
    607       }
    608       assert(BT && "Unknown message kind.");
    609 
    610       auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
    611       const ObjCMessageExpr *ME = msg.getOriginExpr();
    612       R->addRange(ME->getReceiverRange());
    613 
    614       // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
    615       if (const Expr *ReceiverE = ME->getInstanceReceiver())
    616         bugreporter::trackExpressionValue(N, ReceiverE, *R);
    617       C.emitReport(std::move(R));
    618     }
    619     return;
    620   }
    621 }
    622 
    623 void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
    624                                                 CheckerContext &C) const {
    625   HandleNilReceiver(C, C.getState(), msg);
    626 }
    627 
    628 void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
    629                                                const ObjCMethodCall &msg,
    630                                                ExplodedNode *N) const {
    631   if (!ChecksEnabled[CK_NilReceiver]) {
    632     C.addSink();
    633     return;
    634   }
    635 
    636   if (!BT_msg_ret)
    637     BT_msg_ret.reset(new BuiltinBug(OriginalName,
    638                                     "Receiver in message expression is 'nil'"));
    639 
    640   const ObjCMessageExpr *ME = msg.getOriginExpr();
    641 
    642   QualType ResTy = msg.getResultType();
    643 
    644   SmallString<200> buf;
    645   llvm::raw_svector_ostream os(buf);
    646   os << "The receiver of message '";
    647   ME->getSelector().print(os);
    648   os << "' is nil";
    649   if (ResTy->isReferenceType()) {
    650     os << ", which results in forming a null reference";
    651   } else {
    652     os << " and returns a value of type '";
    653     msg.getResultType().print(os, C.getLangOpts());
    654     os << "' that will be garbage";
    655   }
    656 
    657   auto report =
    658       std::make_unique<PathSensitiveBugReport>(*BT_msg_ret, os.str(), N);
    659   report->addRange(ME->getReceiverRange());
    660   // FIXME: This won't track "self" in messages to super.
    661   if (const Expr *receiver = ME->getInstanceReceiver()) {
    662     bugreporter::trackExpressionValue(N, receiver, *report);
    663   }
    664   C.emitReport(std::move(report));
    665 }
    666 
    667 static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
    668   return (triple.getVendor() == llvm::Triple::Apple &&
    669           (triple.isiOS() || triple.isWatchOS() ||
    670            !triple.isMacOSXVersionLT(10,5)));
    671 }
    672 
    673 void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
    674                                               ProgramStateRef state,
    675                                               const ObjCMethodCall &Msg) const {
    676   ASTContext &Ctx = C.getASTContext();
    677   static CheckerProgramPointTag Tag(this, "NilReceiver");
    678 
    679   // Check the return type of the message expression.  A message to nil will
    680   // return different values depending on the return type and the architecture.
    681   QualType RetTy = Msg.getResultType();
    682   CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
    683   const LocationContext *LCtx = C.getLocationContext();
    684 
    685   if (CanRetTy->isStructureOrClassType()) {
    686     // Structure returns are safe since the compiler zeroes them out.
    687     SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    688     C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
    689     return;
    690   }
    691 
    692   // Other cases: check if sizeof(return type) > sizeof(void*)
    693   if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
    694                                   .isConsumedExpr(Msg.getOriginExpr())) {
    695     // Compute: sizeof(void *) and sizeof(return type)
    696     const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
    697     const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
    698 
    699     if (CanRetTy.getTypePtr()->isReferenceType()||
    700         (voidPtrSize < returnTypeSize &&
    701          !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
    702            (Ctx.FloatTy == CanRetTy ||
    703             Ctx.DoubleTy == CanRetTy ||
    704             Ctx.LongDoubleTy == CanRetTy ||
    705             Ctx.LongLongTy == CanRetTy ||
    706             Ctx.UnsignedLongLongTy == CanRetTy)))) {
    707       if (ExplodedNode *N = C.generateErrorNode(state, &Tag))
    708         emitNilReceiverBug(C, Msg, N);
    709       return;
    710     }
    711 
    712     // Handle the safe cases where the return value is 0 if the
    713     // receiver is nil.
    714     //
    715     // FIXME: For now take the conservative approach that we only
    716     // return null values if we *know* that the receiver is nil.
    717     // This is because we can have surprises like:
    718     //
    719     //   ... = [[NSScreens screens] objectAtIndex:0];
    720     //
    721     // What can happen is that [... screens] could return nil, but
    722     // it most likely isn't nil.  We should assume the semantics
    723     // of this case unless we have *a lot* more knowledge.
    724     //
    725     SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    726     C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
    727     return;
    728   }
    729 
    730   C.addTransition(state);
    731 }
    732 
    733 void ento::registerCallAndMessageModeling(CheckerManager &mgr) {
    734   mgr.registerChecker<CallAndMessageChecker>();
    735 }
    736 
    737 bool ento::shouldRegisterCallAndMessageModeling(const CheckerManager &mgr) {
    738   return true;
    739 }
    740 
    741 void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
    742   CallAndMessageChecker *checker = mgr.getChecker<CallAndMessageChecker>();
    743 
    744   checker->OriginalName = mgr.getCurrentCheckerName();
    745 
    746 #define QUERY_CHECKER_OPTION(OPTION)                                           \
    747   checker->ChecksEnabled[CallAndMessageChecker::CK_##OPTION] =                 \
    748       mgr.getAnalyzerOptions().getCheckerBooleanOption(                        \
    749           mgr.getCurrentCheckerName(), #OPTION);
    750 
    751   QUERY_CHECKER_OPTION(FunctionPointer)
    752   QUERY_CHECKER_OPTION(ParameterCount)
    753   QUERY_CHECKER_OPTION(CXXThisMethodCall)
    754   QUERY_CHECKER_OPTION(CXXDeallocationArg)
    755   QUERY_CHECKER_OPTION(ArgInitializedness)
    756   QUERY_CHECKER_OPTION(ArgPointeeInitializedness)
    757   QUERY_CHECKER_OPTION(NilReceiver)
    758   QUERY_CHECKER_OPTION(UndefReceiver)
    759 }
    760 
    761 bool ento::shouldRegisterCallAndMessageChecker(const CheckerManager &mgr) {
    762   return true;
    763 }
    764