//===- 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 << "' 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;
}
