//===- NumberObjectConversionChecker.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 file defines NumberObjectConversionChecker, which checks for a
// particular common mistake when dealing with numbers represented as objects
// passed around by pointers. Namely, the language allows to reinterpret the
// pointer as a number directly, often without throwing any warnings,
// but in most cases the result of such conversion is clearly unexpected,
// as pointer value, rather than number value represented by the pointee object,
// becomes the result of such operation.
//
// Currently the checker supports the Objective-C NSNumber class,
// and the OSBoolean class found in macOS low-level code; the latter
// can only hold boolean values.
//
// This checker has an option "Pedantic" (boolean), which enables detection of
// more conversion patterns (which are most likely more harmless, and therefore
// are more likely to produce false positives) - disabled by default,
// enabled with `-analyzer-config osx.NumberObjectConversion:Pedantic=true'.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/APSInt.h"

using namespace clang;
using namespace ento;
using namespace ast_matchers;

namespace {

class NumberObjectConversionChecker : public Checker<check::ASTCodeBody> {
public:
  bool Pedantic;

  void checkASTCodeBody(const Decl *D, AnalysisManager &AM,
                        BugReporter &BR) const;
};

class Callback : public MatchFinder::MatchCallback {
  const NumberObjectConversionChecker *C;
  BugReporter &BR;
  AnalysisDeclContext *ADC;

public:
  Callback(const NumberObjectConversionChecker *C,
           BugReporter &BR, AnalysisDeclContext *ADC)
      : C(C), BR(BR), ADC(ADC) {}
  virtual void run(const MatchFinder::MatchResult &Result);
};
} // end of anonymous namespace

void Callback::run(const MatchFinder::MatchResult &Result) {
  bool IsPedanticMatch =
      (Result.Nodes.getNodeAs<Stmt>("pedantic") != nullptr);
  if (IsPedanticMatch && !C->Pedantic)
    return;

  ASTContext &ACtx = ADC->getASTContext();

  if (const Expr *CheckIfNull =
          Result.Nodes.getNodeAs<Expr>("check_if_null")) {
    // Unless the macro indicates that the intended type is clearly not
    // a pointer type, we should avoid warning on comparing pointers
    // to zero literals in non-pedantic mode.
    // FIXME: Introduce an AST matcher to implement the macro-related logic?
    bool MacroIndicatesWeShouldSkipTheCheck = false;
    SourceLocation Loc = CheckIfNull->getBeginLoc();
    if (Loc.isMacroID()) {
      StringRef MacroName = Lexer::getImmediateMacroName(
          Loc, ACtx.getSourceManager(), ACtx.getLangOpts());
      if (MacroName == "NULL" || MacroName == "nil")
        return;
      if (MacroName == "YES" || MacroName == "NO")
        MacroIndicatesWeShouldSkipTheCheck = true;
    }
    if (!MacroIndicatesWeShouldSkipTheCheck) {
      Expr::EvalResult EVResult;
      if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt(
              EVResult, ACtx, Expr::SE_AllowSideEffects)) {
        llvm::APSInt Result = EVResult.Val.getInt();
        if (Result == 0) {
          if (!C->Pedantic)
            return;
          IsPedanticMatch = true;
        }
      }
    }
  }

  const Stmt *Conv = Result.Nodes.getNodeAs<Stmt>("conv");
  assert(Conv);

  const Expr *ConvertedCObject = Result.Nodes.getNodeAs<Expr>("c_object");
  const Expr *ConvertedCppObject = Result.Nodes.getNodeAs<Expr>("cpp_object");
  const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs<Expr>("objc_object");
  bool IsCpp = (ConvertedCppObject != nullptr);
  bool IsObjC = (ConvertedObjCObject != nullptr);
  const Expr *Obj = IsObjC ? ConvertedObjCObject
                  : IsCpp ? ConvertedCppObject
                  : ConvertedCObject;
  assert(Obj);

  bool IsComparison =
      (Result.Nodes.getNodeAs<Stmt>("comparison") != nullptr);

  bool IsOSNumber =
      (Result.Nodes.getNodeAs<Decl>("osnumber") != nullptr);

  bool IsInteger =
      (Result.Nodes.getNodeAs<QualType>("int_type") != nullptr);
  bool IsObjCBool =
      (Result.Nodes.getNodeAs<QualType>("objc_bool_type") != nullptr);
  bool IsCppBool =
      (Result.Nodes.getNodeAs<QualType>("cpp_bool_type") != nullptr);

  llvm::SmallString<64> Msg;
  llvm::raw_svector_ostream OS(Msg);

  // Remove ObjC ARC qualifiers.
  QualType ObjT = Obj->getType().getUnqualifiedType();

  // Remove consts from pointers.
  if (IsCpp) {
    assert(ObjT.getCanonicalType()->isPointerType());
    ObjT = ACtx.getPointerType(
        ObjT->getPointeeType().getCanonicalType().getUnqualifiedType());
  }

  if (IsComparison)
    OS << "Comparing ";
  else
    OS << "Converting ";

  OS << "a pointer value of type '" << ObjT.getAsString() << "' to a ";

  std::string EuphemismForPlain = "primitive";
  std::string SuggestedApi = IsObjC ? (IsInteger ? "" : "-boolValue")
                           : IsCpp ? (IsOSNumber ? "" : "getValue()")
                           : "CFNumberGetValue()";
  if (SuggestedApi.empty()) {
    // A generic message if we're not sure what API should be called.
    // FIXME: Pattern-match the integer type to make a better guess?
    SuggestedApi =
        "a method on '" + ObjT.getAsString() + "' to get the scalar value";
    // "scalar" is not quite correct or common, but some documentation uses it
    // when describing object methods we suggest. For consistency, we use
    // "scalar" in the whole sentence when we need to use this word in at least
    // one place, otherwise we use "primitive".
    EuphemismForPlain = "scalar";
  }

  if (IsInteger)
    OS << EuphemismForPlain << " integer value";
  else if (IsObjCBool)
    OS << EuphemismForPlain << " BOOL value";
  else if (IsCppBool)
    OS << EuphemismForPlain << " bool value";
  else // Branch condition?
    OS << EuphemismForPlain << " boolean value";


  if (IsPedanticMatch)
    OS << "; instead, either compare the pointer to "
       << (IsObjC ? "nil" : IsCpp ? "nullptr" : "NULL") << " or ";
  else
    OS << "; did you mean to ";

  if (IsComparison)
    OS << "compare the result of calling " << SuggestedApi;
  else
    OS << "call " << SuggestedApi;

  if (!IsPedanticMatch)
    OS << "?";

  BR.EmitBasicReport(
      ADC->getDecl(), C, "Suspicious number object conversion", "Logic error",
      OS.str(),
      PathDiagnosticLocation::createBegin(Obj, BR.getSourceManager(), ADC),
      Conv->getSourceRange());
}

void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
                                                     AnalysisManager &AM,
                                                     BugReporter &BR) const {
  // Currently this matches CoreFoundation opaque pointer typedefs.
  auto CSuspiciousNumberObjectExprM =
      expr(ignoringParenImpCasts(
          expr(hasType(
              typedefType(hasDeclaration(anyOf(
                  typedefDecl(hasName("CFNumberRef")),
                  typedefDecl(hasName("CFBooleanRef")))))))
          .bind("c_object")));

  // Currently this matches XNU kernel number-object pointers.
  auto CppSuspiciousNumberObjectExprM =
      expr(ignoringParenImpCasts(
          expr(hasType(hasCanonicalType(
              pointerType(pointee(hasCanonicalType(
                  recordType(hasDeclaration(
                      anyOf(
                        cxxRecordDecl(hasName("OSBoolean")),
                        cxxRecordDecl(hasName("OSNumber"))
                            .bind("osnumber"))))))))))
          .bind("cpp_object")));

  // Currently this matches NeXTSTEP number objects.
  auto ObjCSuspiciousNumberObjectExprM =
      expr(ignoringParenImpCasts(
          expr(hasType(hasCanonicalType(
              objcObjectPointerType(pointee(
                  qualType(hasCanonicalType(
                      qualType(hasDeclaration(
                          objcInterfaceDecl(hasName("NSNumber")))))))))))
          .bind("objc_object")));

  auto SuspiciousNumberObjectExprM = anyOf(
      CSuspiciousNumberObjectExprM,
      CppSuspiciousNumberObjectExprM,
      ObjCSuspiciousNumberObjectExprM);

  // Useful for predicates like "Unless we've seen the same object elsewhere".
  auto AnotherSuspiciousNumberObjectExprM =
      expr(anyOf(
          equalsBoundNode("c_object"),
          equalsBoundNode("objc_object"),
          equalsBoundNode("cpp_object")));

  // The .bind here is in order to compose the error message more accurately.
  auto ObjCSuspiciousScalarBooleanTypeM =
      qualType(typedefType(hasDeclaration(
                   typedefDecl(hasName("BOOL"))))).bind("objc_bool_type");

  // The .bind here is in order to compose the error message more accurately.
  auto SuspiciousScalarBooleanTypeM =
      qualType(anyOf(qualType(booleanType()).bind("cpp_bool_type"),
                     ObjCSuspiciousScalarBooleanTypeM));

  // The .bind here is in order to compose the error message more accurately.
  // Also avoid intptr_t and uintptr_t because they were specifically created
  // for storing pointers.
  auto SuspiciousScalarNumberTypeM =
      qualType(hasCanonicalType(isInteger()),
               unless(typedefType(hasDeclaration(
                   typedefDecl(matchesName("^::u?intptr_t$"))))))
      .bind("int_type");

  auto SuspiciousScalarTypeM =
      qualType(anyOf(SuspiciousScalarBooleanTypeM,
                     SuspiciousScalarNumberTypeM));

  auto SuspiciousScalarExprM =
      expr(ignoringParenImpCasts(expr(hasType(SuspiciousScalarTypeM))));

  auto ConversionThroughAssignmentM =
      binaryOperator(allOf(hasOperatorName("="),
                           hasLHS(SuspiciousScalarExprM),
                           hasRHS(SuspiciousNumberObjectExprM)));

  auto ConversionThroughBranchingM =
      ifStmt(allOf(
          hasCondition(SuspiciousNumberObjectExprM),
          unless(hasConditionVariableStatement(declStmt())
      ))).bind("pedantic");

  auto ConversionThroughCallM =
      callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM),
                                    ignoringParenImpCasts(
                                        SuspiciousNumberObjectExprM))));

  // We bind "check_if_null" to modify the warning message
  // in case it was intended to compare a pointer to 0 with a relatively-ok
  // construct "x == 0" or "x != 0".
  auto ConversionThroughEquivalenceM =
      binaryOperator(allOf(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
                           hasEitherOperand(SuspiciousNumberObjectExprM),
                           hasEitherOperand(SuspiciousScalarExprM
                                            .bind("check_if_null"))))
      .bind("comparison");

  auto ConversionThroughComparisonM =
      binaryOperator(allOf(anyOf(hasOperatorName(">="), hasOperatorName(">"),
                                 hasOperatorName("<="), hasOperatorName("<")),
                           hasEitherOperand(SuspiciousNumberObjectExprM),
                           hasEitherOperand(SuspiciousScalarExprM)))
      .bind("comparison");

  auto ConversionThroughConditionalOperatorM =
      conditionalOperator(allOf(
          hasCondition(SuspiciousNumberObjectExprM),
          unless(hasTrueExpression(
              hasDescendant(AnotherSuspiciousNumberObjectExprM))),
          unless(hasFalseExpression(
              hasDescendant(AnotherSuspiciousNumberObjectExprM)))))
      .bind("pedantic");

  auto ConversionThroughExclamationMarkM =
      unaryOperator(allOf(hasOperatorName("!"),
                          has(expr(SuspiciousNumberObjectExprM))))
      .bind("pedantic");

  auto ConversionThroughExplicitBooleanCastM =
      explicitCastExpr(allOf(hasType(SuspiciousScalarBooleanTypeM),
                             has(expr(SuspiciousNumberObjectExprM))));

  auto ConversionThroughExplicitNumberCastM =
      explicitCastExpr(allOf(hasType(SuspiciousScalarNumberTypeM),
                             has(expr(SuspiciousNumberObjectExprM))));

  auto ConversionThroughInitializerM =
      declStmt(hasSingleDecl(
          varDecl(hasType(SuspiciousScalarTypeM),
                  hasInitializer(SuspiciousNumberObjectExprM))));

  auto FinalM = stmt(anyOf(ConversionThroughAssignmentM,
                           ConversionThroughBranchingM,
                           ConversionThroughCallM,
                           ConversionThroughComparisonM,
                           ConversionThroughConditionalOperatorM,
                           ConversionThroughEquivalenceM,
                           ConversionThroughExclamationMarkM,
                           ConversionThroughExplicitBooleanCastM,
                           ConversionThroughExplicitNumberCastM,
                           ConversionThroughInitializerM)).bind("conv");

  MatchFinder F;
  Callback CB(this, BR, AM.getAnalysisDeclContext(D));

  F.addMatcher(stmt(forEachDescendant(FinalM)), &CB);
  F.match(*D->getBody(), AM.getASTContext());
}

void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) {
  NumberObjectConversionChecker *Chk =
      Mgr.registerChecker<NumberObjectConversionChecker>();
  Chk->Pedantic =
      Mgr.getAnalyzerOptions().getCheckerBooleanOption(Chk, "Pedantic");
}

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