//===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This defines CallAndMessageChecker, a builtin checker that checks for various
// errors of call and objc message expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

namespace {

class CallAndMessageChecker
  : public Checker< check::PreStmt<CallExpr>,
                    check::PreStmt<CXXDeleteExpr>,
                    check::PreObjCMessage,
                    check::ObjCMessageNil,
                    check::PreCall > {
  mutable std::unique_ptr<BugType> BT_call_null;
  mutable std::unique_ptr<BugType> BT_call_undef;
  mutable std::unique_ptr<BugType> BT_cxx_call_null;
  mutable std::unique_ptr<BugType> BT_cxx_call_undef;
  mutable std::unique_ptr<BugType> BT_call_arg;
  mutable std::unique_ptr<BugType> BT_cxx_delete_undef;
  mutable std::unique_ptr<BugType> BT_msg_undef;
  mutable std::unique_ptr<BugType> BT_objc_prop_undef;
  mutable std::unique_ptr<BugType> BT_objc_subscript_undef;
  mutable std::unique_ptr<BugType> BT_msg_arg;
  mutable std::unique_ptr<BugType> BT_msg_ret;
  mutable std::unique_ptr<BugType> BT_call_few_args;

public:
  DefaultBool Check_CallAndMessageUnInitRefArg;
  CheckerNameRef CheckName_CallAndMessageUnInitRefArg;

  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;

  /// Fill in the return value that results from messaging nil based on the
  /// return type and architecture and diagnose if the return value will be
  /// garbage.
  void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const;

  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;

private:
  bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange,
                          const Expr *ArgEx, int ArgumentNumber,
                          bool CheckUninitFields, const CallEvent &Call,
                          std::unique_ptr<BugType> &BT,
                          const ParmVarDecl *ParamDecl) const;

  static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE);
  void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
                          ExplodedNode *N) const;

  void HandleNilReceiver(CheckerContext &C,
                         ProgramStateRef state,
                         const ObjCMethodCall &msg) const;

  void LazyInit_BT(const char *desc, std::unique_ptr<BugType> &BT) const {
    if (!BT)
      BT.reset(new BuiltinBug(this, desc));
  }
  bool uninitRefOrPointer(CheckerContext &C, const SVal &V,
                          SourceRange ArgRange, const Expr *ArgEx,
                          std::unique_ptr<BugType> &BT,
                          const ParmVarDecl *ParamDecl, const char *BD,
                          int ArgumentNumber) const;
};
} // end anonymous namespace

void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
                                        const Expr *BadE) {
  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return;

  auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
  if (BadE) {
    R->addRange(BadE->getSourceRange());
    if (BadE->isGLValue())
      BadE = bugreporter::getDerefExpr(BadE);
    bugreporter::trackExpressionValue(N, BadE, *R);
  }
  C.emitReport(std::move(R));
}

static void describeUninitializedArgumentInCall(const CallEvent &Call,
                                                int ArgumentNumber,
                                                llvm::raw_svector_ostream &Os) {
  switch (Call.getKind()) {
  case CE_ObjCMessage: {
    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
    switch (Msg.getMessageKind()) {
    case OCM_Message:
      Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
         << " argument in message expression is an uninitialized value";
      return;
    case OCM_PropertyAccess:
      assert(Msg.isSetter() && "Getters have no args");
      Os << "Argument for property setter is an uninitialized value";
      return;
    case OCM_Subscript:
      if (Msg.isSetter() && (ArgumentNumber == 0))
        Os << "Argument for subscript setter is an uninitialized value";
      else
        Os << "Subscript index is an uninitialized value";
      return;
    }
    llvm_unreachable("Unknown message kind.");
  }
  case CE_Block:
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " block call argument is an uninitialized value";
    return;
  default:
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " function call argument is an uninitialized value";
    return;
  }
}

bool CallAndMessageChecker::uninitRefOrPointer(
    CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx,
    std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD,
    int ArgumentNumber) const {
  if (!Check_CallAndMessageUnInitRefArg)
    return false;

  // No parameter declaration available, i.e. variadic function argument.
  if(!ParamDecl)
    return false;

  // If parameter is declared as pointer to const in function declaration,
  // then check if corresponding argument in function call is
  // pointing to undefined symbol value (uninitialized memory).
  SmallString<200> Buf;
  llvm::raw_svector_ostream Os(Buf);

  if (ParamDecl->getType()->isPointerType()) {
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " function call argument is a pointer to uninitialized value";
  } else if (ParamDecl->getType()->isReferenceType()) {
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " function call argument is an uninitialized value";
  } else
    return false;

  if(!ParamDecl->getType()->getPointeeType().isConstQualified())
    return false;

  if (const MemRegion *SValMemRegion = V.getAsRegion()) {
    const ProgramStateRef State = C.getState();
    const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
    if (PSV.isUndef()) {
      if (ExplodedNode *N = C.generateErrorNode()) {
        LazyInit_BT(BD, BT);
        auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);
        R->addRange(ArgRange);
        if (ArgEx)
          bugreporter::trackExpressionValue(N, ArgEx, *R);

        C.emitReport(std::move(R));
      }
      return true;
    }
  }
  return false;
}

namespace {
class FindUninitializedField {
public:
  SmallVector<const FieldDecl *, 10> FieldChain;

private:
  StoreManager &StoreMgr;
  MemRegionManager &MrMgr;
  Store store;

public:
  FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
                         Store s)
      : StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}

  bool Find(const TypedValueRegion *R) {
    QualType T = R->getValueType();
    if (const RecordType *RT = T->getAsStructureType()) {
      const RecordDecl *RD = RT->getDecl()->getDefinition();
      assert(RD && "Referred record has no definition");
      for (const auto *I : RD->fields()) {
        const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
        FieldChain.push_back(I);
        T = I->getType();
        if (T->getAsStructureType()) {
          if (Find(FR))
            return true;
        } else {
          const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
          if (V.isUndef())
            return true;
        }
        FieldChain.pop_back();
      }
    }

    return false;
  }
};
} // namespace

bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
                                               SVal V,
                                               SourceRange ArgRange,
                                               const Expr *ArgEx,
                                               int ArgumentNumber,
                                               bool CheckUninitFields,
                                               const CallEvent &Call,
                                               std::unique_ptr<BugType> &BT,
                                               const ParmVarDecl *ParamDecl
                                               ) const {
  const char *BD = "Uninitialized argument value";

  if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD,
                         ArgumentNumber))
    return true;

  if (V.isUndef()) {
    if (ExplodedNode *N = C.generateErrorNode()) {
      LazyInit_BT(BD, BT);
      // Generate a report for this bug.
      SmallString<200> Buf;
      llvm::raw_svector_ostream Os(Buf);
      describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
      auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);

      R->addRange(ArgRange);
      if (ArgEx)
        bugreporter::trackExpressionValue(N, ArgEx, *R);
      C.emitReport(std::move(R));
    }
    return true;
  }

  if (!CheckUninitFields)
    return false;

  if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
    const LazyCompoundValData *D = LV->getCVData();
    FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
                             C.getSValBuilder().getRegionManager(),
                             D->getStore());

    if (F.Find(D->getRegion())) {
      if (ExplodedNode *N = C.generateErrorNode()) {
        LazyInit_BT(BD, BT);
        SmallString<512> Str;
        llvm::raw_svector_ostream os(Str);
        os << "Passed-by-value struct argument contains uninitialized data";

        if (F.FieldChain.size() == 1)
          os << " (e.g., field: '" << *F.FieldChain[0] << "')";
        else {
          os << " (e.g., via the field chain: '";
          bool first = true;
          for (SmallVectorImpl<const FieldDecl *>::iterator
               DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
            if (first)
              first = false;
            else
              os << '.';
            os << **DI;
          }
          os << "')";
        }

        // Generate a report for this bug.
        auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
        R->addRange(ArgRange);

        if (ArgEx)
          bugreporter::trackExpressionValue(N, ArgEx, *R);
        // FIXME: enhance track back for uninitialized value for arbitrary
        // memregions
        C.emitReport(std::move(R));
      }
      return true;
    }
  }

  return false;
}

void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
                                         CheckerContext &C) const{

  const Expr *Callee = CE->getCallee()->IgnoreParens();
  ProgramStateRef State = C.getState();
  const LocationContext *LCtx = C.getLocationContext();
  SVal L = State->getSVal(Callee, LCtx);

  if (L.isUndef()) {
    if (!BT_call_undef)
      BT_call_undef.reset(new BuiltinBug(
          this, "Called function pointer is an uninitialized pointer value"));
    emitBadCall(BT_call_undef.get(), C, Callee);
    return;
  }

  ProgramStateRef StNonNull, StNull;
  std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());

  if (StNull && !StNonNull) {
    if (!BT_call_null)
      BT_call_null.reset(new BuiltinBug(
          this, "Called function pointer is null (null dereference)"));
    emitBadCall(BT_call_null.get(), C, Callee);
    return;
  }

  C.addTransition(StNonNull);
}

void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
                                         CheckerContext &C) const {

  SVal Arg = C.getSVal(DE->getArgument());
  if (Arg.isUndef()) {
    StringRef Desc;
    ExplodedNode *N = C.generateErrorNode();
    if (!N)
      return;
    if (!BT_cxx_delete_undef)
      BT_cxx_delete_undef.reset(
          new BuiltinBug(this, "Uninitialized argument value"));
    if (DE->isArrayFormAsWritten())
      Desc = "Argument to 'delete[]' is uninitialized";
    else
      Desc = "Argument to 'delete' is uninitialized";
    BugType *BT = BT_cxx_delete_undef.get();
    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
    bugreporter::trackExpressionValue(N, DE, *R);
    C.emitReport(std::move(R));
    return;
  }
}

void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
                                         CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  // If this is a call to a C++ method, check if the callee is null or
  // undefined.
  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
    SVal V = CC->getCXXThisVal();
    if (V.isUndef()) {
      if (!BT_cxx_call_undef)
        BT_cxx_call_undef.reset(
            new BuiltinBug(this, "Called C++ object pointer is uninitialized"));
      emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
      return;
    }

    ProgramStateRef StNonNull, StNull;
    std::tie(StNonNull, StNull) =
        State->assume(V.castAs<DefinedOrUnknownSVal>());

    if (StNull && !StNonNull) {
      if (!BT_cxx_call_null)
        BT_cxx_call_null.reset(
            new BuiltinBug(this, "Called C++ object pointer is null"));
      emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
      return;
    }

    State = StNonNull;
  }

  const Decl *D = Call.getDecl();
  if (D && (isa<FunctionDecl>(D) || isa<BlockDecl>(D))) {
    // If we have a function or block declaration, we can make sure we pass
    // enough parameters.
    unsigned Params = Call.parameters().size();
    if (Call.getNumArgs() < Params) {
      ExplodedNode *N = C.generateErrorNode();
      if (!N)
        return;

      LazyInit_BT("Function call with too few arguments", BT_call_few_args);

      SmallString<512> Str;
      llvm::raw_svector_ostream os(Str);
      if (isa<FunctionDecl>(D)) {
        os << "Function ";
      } else {
        assert(isa<BlockDecl>(D));
        os << "Block ";
      }
      os << "taking " << Params << " argument"
         << (Params == 1 ? "" : "s") << " is called with fewer ("
         << Call.getNumArgs() << ")";

      C.emitReport(std::make_unique<PathSensitiveBugReport>(*BT_call_few_args,
                                                            os.str(), N));
    }
  }

  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const bool checkUninitFields =
    !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));

  std::unique_ptr<BugType> *BT;
  if (isa<ObjCMethodCall>(Call))
    BT = &BT_msg_arg;
  else
    BT = &BT_call_arg;

  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
    const ParmVarDecl *ParamDecl = nullptr;
    if(FD && i < FD->getNumParams())
      ParamDecl = FD->getParamDecl(i);
    if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
                           Call.getArgExpr(i), i,
                           checkUninitFields, Call, *BT, ParamDecl))
      return;
  }

  // If we make it here, record our assumptions about the callee.
  C.addTransition(State);
}

void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
                                                CheckerContext &C) const {
  SVal recVal = msg.getReceiverSVal();
  if (recVal.isUndef()) {
    if (ExplodedNode *N = C.generateErrorNode()) {
      BugType *BT = nullptr;
      switch (msg.getMessageKind()) {
      case OCM_Message:
        if (!BT_msg_undef)
          BT_msg_undef.reset(new BuiltinBug(this,
                                            "Receiver in message expression "
                                            "is an uninitialized value"));
        BT = BT_msg_undef.get();
        break;
      case OCM_PropertyAccess:
        if (!BT_objc_prop_undef)
          BT_objc_prop_undef.reset(new BuiltinBug(
              this, "Property access on an uninitialized object pointer"));
        BT = BT_objc_prop_undef.get();
        break;
      case OCM_Subscript:
        if (!BT_objc_subscript_undef)
          BT_objc_subscript_undef.reset(new BuiltinBug(
              this, "Subscript access on an uninitialized object pointer"));
        BT = BT_objc_subscript_undef.get();
        break;
      }
      assert(BT && "Unknown message kind.");

      auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
      const ObjCMessageExpr *ME = msg.getOriginExpr();
      R->addRange(ME->getReceiverRange());

      // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
      if (const Expr *ReceiverE = ME->getInstanceReceiver())
        bugreporter::trackExpressionValue(N, ReceiverE, *R);
      C.emitReport(std::move(R));
    }
    return;
  }
}

void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
                                                CheckerContext &C) const {
  HandleNilReceiver(C, C.getState(), msg);
}

void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
                                               const ObjCMethodCall &msg,
                                               ExplodedNode *N) const {

  if (!BT_msg_ret)
    BT_msg_ret.reset(
        new BuiltinBug(this, "Receiver in message expression is 'nil'"));

  const ObjCMessageExpr *ME = msg.getOriginExpr();

  QualType ResTy = msg.getResultType();

  SmallString<200> buf;
  llvm::raw_svector_ostream os(buf);
  os << "The receiver of message '";
  ME->getSelector().print(os);
  os << "' is nil";
  if (ResTy->isReferenceType()) {
    os << ", which results in forming a null reference";
  } else {
    os << " and returns a value of type '";
    msg.getResultType().print(os, C.getLangOpts());
    os << "' that will be garbage";
  }

  auto report =
      std::make_unique<PathSensitiveBugReport>(*BT_msg_ret, os.str(), N);
  report->addRange(ME->getReceiverRange());
  // FIXME: This won't track "self" in messages to super.
  if (const Expr *receiver = ME->getInstanceReceiver()) {
    bugreporter::trackExpressionValue(N, receiver, *report);
  }
  C.emitReport(std::move(report));
}

static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
  return (triple.getVendor() == llvm::Triple::Apple &&
          (triple.isiOS() || triple.isWatchOS() ||
           !triple.isMacOSXVersionLT(10,5)));
}

void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
                                              ProgramStateRef state,
                                              const ObjCMethodCall &Msg) const {
  ASTContext &Ctx = C.getASTContext();
  static CheckerProgramPointTag Tag(this, "NilReceiver");

  // Check the return type of the message expression.  A message to nil will
  // return different values depending on the return type and the architecture.
  QualType RetTy = Msg.getResultType();
  CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
  const LocationContext *LCtx = C.getLocationContext();

  if (CanRetTy->isStructureOrClassType()) {
    // Structure returns are safe since the compiler zeroes them out.
    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
    return;
  }

  // Other cases: check if sizeof(return type) > sizeof(void*)
  if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
                                  .isConsumedExpr(Msg.getOriginExpr())) {
    // Compute: sizeof(void *) and sizeof(return type)
    const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
    const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);

    if (CanRetTy.getTypePtr()->isReferenceType()||
        (voidPtrSize < returnTypeSize &&
         !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
           (Ctx.FloatTy == CanRetTy ||
            Ctx.DoubleTy == CanRetTy ||
            Ctx.LongDoubleTy == CanRetTy ||
            Ctx.LongLongTy == CanRetTy ||
            Ctx.UnsignedLongLongTy == CanRetTy)))) {
      if (ExplodedNode *N = C.generateErrorNode(state, &Tag))
        emitNilReceiverBug(C, Msg, N);
      return;
    }

    // Handle the safe cases where the return value is 0 if the
    // receiver is nil.
    //
    // FIXME: For now take the conservative approach that we only
    // return null values if we *know* that the receiver is nil.
    // This is because we can have surprises like:
    //
    //   ... = [[NSScreens screens] objectAtIndex:0];
    //
    // What can happen is that [... screens] could return nil, but
    // it most likely isn't nil.  We should assume the semantics
    // of this case unless we have *a lot* more knowledge.
    //
    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag);
    return;
  }

  C.addTransition(state);
}

void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
  mgr.registerChecker<CallAndMessageChecker>();
}

bool ento::shouldRegisterCallAndMessageChecker(const LangOptions &LO) {
  return true;
}

void ento::registerCallAndMessageUnInitRefArg(CheckerManager &mgr) {
  CallAndMessageChecker *Checker = mgr.getChecker<CallAndMessageChecker>();
  Checker->Check_CallAndMessageUnInitRefArg = true;
  Checker->CheckName_CallAndMessageUnInitRefArg = mgr.getCurrentCheckerName();
}

bool ento::shouldRegisterCallAndMessageUnInitRefArg(const LangOptions &LO) {
  return true;
}
