// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "CheckIPCVisitor.h"

using namespace clang;

namespace chrome_checker {

namespace {

const char kWriteParamBadType[] =
    "[chromium-ipc] IPC::WriteParam() is called on blacklisted type '%0'%1.";

const char kTupleBadType[] =
    "[chromium-ipc] IPC tuple references banned type '%0'%1.";

const char kWriteParamBadSignature[] =
    "[chromium-ipc] IPC::WriteParam() is expected to have two arguments.";

const char kNoteSeeHere[] =
    "see here";

}  // namespace

CheckIPCVisitor::CheckIPCVisitor(CompilerInstance& compiler)
  : compiler_(compiler), context_(nullptr) {
  auto& diagnostics = compiler_.getDiagnostics();
  error_write_param_bad_type_ = diagnostics.getCustomDiagID(
      DiagnosticsEngine::Error, kWriteParamBadType);
  error_tuple_bad_type_ = diagnostics.getCustomDiagID(
      DiagnosticsEngine::Error, kTupleBadType);
  error_write_param_bad_signature_ = diagnostics.getCustomDiagID(
      DiagnosticsEngine::Error, kWriteParamBadSignature);
  note_see_here_ = diagnostics.getCustomDiagID(
      DiagnosticsEngine::Note, kNoteSeeHere);

  blacklisted_typedefs_ = llvm::StringSet<>({
      "intmax_t",
      "uintmax_t",
      "intptr_t",
      "uintptr_t",
      "wint_t",
      "size_t",
      "rsize_t",
      "ssize_t",
      "ptrdiff_t",
      "dev_t",
      "off_t",
      "clock_t",
      "time_t",
      "suseconds_t"
  });
}

void CheckIPCVisitor::BeginDecl(Decl* decl) {
  decl_stack_.push_back(decl);
}

void CheckIPCVisitor::EndDecl() {
  decl_stack_.pop_back();
}

void CheckIPCVisitor::VisitTemplateSpecializationType(
    TemplateSpecializationType* spec) {
  ValidateCheckedTuple(spec);
}

void CheckIPCVisitor::VisitCallExpr(CallExpr* call_expr) {
  ValidateWriteParam(call_expr);
}

bool CheckIPCVisitor::ValidateWriteParam(const CallExpr* call_expr) {
  const FunctionDecl* callee_decl = call_expr->getDirectCallee();
  if (!callee_decl ||
      callee_decl->getQualifiedNameAsString() != "IPC::WriteParam") {
    return true;
  }

  return ValidateWriteParamSignature(call_expr) &&
      ValidateWriteParamArgument(call_expr->getArg(1));
}

// Checks that IPC::WriteParam() has expected signature.
bool CheckIPCVisitor::ValidateWriteParamSignature(
    const CallExpr* call_expr) {
  if (call_expr->getNumArgs() != 2) {
    compiler_.getDiagnostics().Report(
        call_expr->getExprLoc(), error_write_param_bad_signature_);
    return false;
  }
  return true;
}

// Checks that IPC::WriteParam() argument type is allowed.
// See CheckType() for specifics.
bool CheckIPCVisitor::ValidateWriteParamArgument(const Expr* arg_expr) {
  if (auto* parent_fn_decl = GetParentDecl<FunctionDecl>()) {
    auto template_kind = parent_fn_decl->getTemplatedKind();
    if (template_kind != FunctionDecl::TK_NonTemplate &&
        template_kind != FunctionDecl::TK_FunctionTemplate) {
      // Skip all specializations - we don't check WriteParam() on dependent
      // types (typedef info gets lost), and we checked all non-dependent uses
      // earlier (when we checked the template itself).
      return true;
    }
  }

  QualType arg_type;

  arg_expr = arg_expr->IgnoreImplicit();
  if (auto* cast_expr = dyn_cast<ExplicitCastExpr>(arg_expr)) {
    arg_type = cast_expr->getTypeAsWritten();
  } else {
    arg_type = arg_expr->getType();
  }

  CheckDetails details;
  if (CheckType(arg_type, &details)) {
    return true;
  }

  ReportCheckError(details,
                   arg_expr->getExprLoc(),
                   error_write_param_bad_type_);

  return false;
}

// Checks that IPC::CheckedTuple<> is specialized with allowed types.
// See CheckType() above for specifics.
bool CheckIPCVisitor::ValidateCheckedTuple(
    const TemplateSpecializationType* spec) {
  TemplateDecl* decl = spec->getTemplateName().getAsTemplateDecl();
  if (!decl || decl->getQualifiedNameAsString() != "IPC::CheckedTuple") {
    return true;
  }

  bool valid = true;
  for (unsigned i = 0; i != spec->getNumArgs(); ++i) {
    const TemplateArgument& arg = spec->getArg(i);
    CheckDetails details;
    if (CheckTemplateArgument(arg, &details)) {
      continue;
    }

    valid = false;

    auto* parent_decl = GetParentDecl<Decl>();
    ReportCheckError(
        details, parent_decl ? parent_decl->getBeginLoc() : SourceLocation(),
        error_tuple_bad_type_);
  }

  return valid;
}

template <typename T>
const T* CheckIPCVisitor::GetParentDecl() const {
  for (auto i = decl_stack_.rbegin(); i != decl_stack_.rend(); ++i) {
    if (auto* parent = dyn_cast_or_null<T>(*i)) {
      return parent;
    }
  }
  return nullptr;
}


bool CheckIPCVisitor::IsBlacklistedType(QualType type) const {
  return context_->hasSameUnqualifiedType(type, context_->LongTy) ||
      context_->hasSameUnqualifiedType(type, context_->UnsignedLongTy);
}

bool CheckIPCVisitor::IsBlacklistedTypedef(const TypedefNameDecl* tdef) const {
  return blacklisted_typedefs_.find(tdef->getName()) !=
      blacklisted_typedefs_.end();
}

// Checks that integer type is allowed (not blacklisted).
bool CheckIPCVisitor::CheckIntegerType(QualType type,
                                       CheckDetails* details) const {
  bool seen_typedef = false;
  while (true) {
    details->exit_type = type;

    if (auto* tdef = dyn_cast<TypedefType>(type)) {
      if (IsBlacklistedTypedef(tdef->getDecl())) {
        return false;
      }
      details->typedefs.push_back(tdef);
      seen_typedef = true;
    }

    QualType desugared_type =
        type->getLocallyUnqualifiedSingleStepDesugaredType();
    if (desugared_type == type) {
      break;
    }

    type = desugared_type;
  }

  return seen_typedef || !IsBlacklistedType(type);
}

// Checks that |type| is allowed (not blacklisted), recursively visiting
// template specializations.
bool CheckIPCVisitor::CheckType(QualType type, CheckDetails* details) const {
  if (type->isReferenceType()) {
    type = type->getPointeeType();
  }
  type = type.getLocalUnqualifiedType();

  if (details->entry_type.isNull()) {
    details->entry_type = type;
  }

  if (type->isIntegerType()) {
    return CheckIntegerType(type, details);
  }

  while (true) {
    if (auto* spec = dyn_cast<TemplateSpecializationType>(type)) {
      for (const TemplateArgument& arg: *spec) {
        if (!CheckTemplateArgument(arg, details)) {
          return false;
        }
      }
      return true;
    }

    if (auto* record = dyn_cast<RecordType>(type)) {
      if (auto* spec = dyn_cast<ClassTemplateSpecializationDecl>(
              record->getDecl())) {
        const TemplateArgumentList& args = spec->getTemplateArgs();
        for (unsigned i = 0; i != args.size(); ++i) {
          if (!CheckTemplateArgument(args[i], details)) {
            return false;
          }
        }
      }
      return true;
    }

    if (auto* tdef = dyn_cast<TypedefType>(type)) {
      details->typedefs.push_back(tdef);
    }

    QualType desugared_type =
        type->getLocallyUnqualifiedSingleStepDesugaredType();
    if (desugared_type == type) {
      break;
    }

    type = desugared_type;
  }

  return true;
}

bool CheckIPCVisitor::CheckTemplateArgument(const TemplateArgument& arg,
                                            CheckDetails* details) const {
  return arg.getKind() != TemplateArgument::Type ||
      CheckType(arg.getAsType(), details);
}

void CheckIPCVisitor::ReportCheckError(const CheckDetails& details,
                                       SourceLocation loc,
                                       unsigned error) {
  DiagnosticsEngine& diagnostics = compiler_.getDiagnostics();

  std::string entry_type = details.entry_type.getAsString();
  std::string exit_type = details.exit_type.getAsString();

  std::string via;
  if (entry_type != exit_type) {
    via = " via '" + entry_type + "'";
  }
  diagnostics.Report(loc, error) << exit_type << via;

  for (const TypedefType* tdef: details.typedefs) {
    diagnostics.Report(tdef->getDecl()->getLocation(), note_see_here_);
  }
}

}  // namespace chrome_checker
