//===- 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) {}
  void run(const MatchFinder::MatchResult &Result) override;
};
} // 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(traverse(TK_AsIs, 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 CheckerManager &mgr) {
  return true;
}
