// Copyright (c) 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/fuzz/fuzzer_pass_obfuscate_constants.h"

#include <cmath>

#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/opt/ir_context.h"

namespace spvtools {
namespace fuzz {

FuzzerPassObfuscateConstants::FuzzerPassObfuscateConstants(
    opt::IRContext* ir_context, FactManager* fact_manager,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}

FuzzerPassObfuscateConstants::~FuzzerPassObfuscateConstants() = default;

void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
    uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
    const std::vector<SpvOp>& greater_than_opcodes,
    const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1,
    uint32_t constant_id_2, bool first_constant_is_larger) {
  auto bool_constant_opcode = GetIRContext()
                                  ->get_def_use_mgr()
                                  ->GetDef(bool_constant_use.id_of_interest())
                                  ->opcode();
  assert((bool_constant_opcode == SpvOpConstantFalse ||
          bool_constant_opcode == SpvOpConstantTrue) &&
         "Precondition: this must be a usage of a boolean constant.");

  // Pick an opcode at random.  First randomly decide whether to generate
  // a 'greater than' or 'less than' kind of opcode, and then select a
  // random opcode from the resulting subset.
  SpvOp comparison_opcode;
  if (GetFuzzerContext()->GetRandomGenerator()->RandomBool()) {
    comparison_opcode = greater_than_opcodes
        [GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
            static_cast<uint32_t>(greater_than_opcodes.size()))];
  } else {
    comparison_opcode = less_than_opcodes
        [GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
            static_cast<uint32_t>(less_than_opcodes.size()))];
  }

  // We now need to decide how to order constant_id_1 and constant_id_2 such
  // that 'constant_id_1 comparison_opcode constant_id_2' evaluates to the
  // boolean constant.
  const bool is_greater_than_opcode =
      std::find(greater_than_opcodes.begin(), greater_than_opcodes.end(),
                comparison_opcode) != greater_than_opcodes.end();
  uint32_t lhs_id;
  uint32_t rhs_id;
  if ((bool_constant_opcode == SpvOpConstantTrue &&
       first_constant_is_larger == is_greater_than_opcode) ||
      (bool_constant_opcode == SpvOpConstantFalse &&
       first_constant_is_larger != is_greater_than_opcode)) {
    lhs_id = constant_id_1;
    rhs_id = constant_id_2;
  } else {
    lhs_id = constant_id_2;
    rhs_id = constant_id_1;
  }

  // We can now make a transformation that will replace |bool_constant_use|
  // with an expression of the form (written using infix notation):
  // |lhs_id| |comparison_opcode| |rhs_id|
  auto transformation = TransformationReplaceBooleanConstantWithConstantBinary(
      bool_constant_use, lhs_id, rhs_id, comparison_opcode,
      GetFuzzerContext()->GetFreshId());
  // The transformation should be applicable by construction.
  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));

  // Applying this transformation yields a pointer to the new instruction that
  // computes the result of the binary expression.
  auto binary_operator_instruction =
      transformation.ApplyWithResult(GetIRContext(), GetFactManager());

  // Add this transformation to the sequence of transformations that have been
  // applied.
  *GetTransformations()->add_transformation() = transformation.ToMessage();

  // Having made a binary expression, there may now be opportunities to further
  // obfuscate the constants used as the LHS and RHS of the expression (e.g. by
  // replacing them with loads from known uniforms).
  //
  // We thus consider operands 0 and 1 (LHS and RHS in turn).
  for (uint32_t index : {0u, 1u}) {
    // We randomly decide, based on the current depth of obfuscation, whether
    // to further obfuscate this operand.
    if (GetFuzzerContext()->GoDeeperInConstantObfuscation()(
            depth, GetFuzzerContext()->GetRandomGenerator())) {
      auto in_operand_use = transformation::MakeIdUseDescriptor(
          binary_operator_instruction->GetSingleWordInOperand(index),
          binary_operator_instruction->opcode(), index,
          binary_operator_instruction->result_id(), 0);
      ObfuscateConstant(depth + 1, in_operand_use);
    }
  }
}

void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaFloatConstantPair(
    uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
    uint32_t float_constant_id_1, uint32_t float_constant_id_2) {
  auto float_constant_1 = GetIRContext()
                              ->get_constant_mgr()
                              ->FindDeclaredConstant(float_constant_id_1)
                              ->AsFloatConstant();
  auto float_constant_2 = GetIRContext()
                              ->get_constant_mgr()
                              ->FindDeclaredConstant(float_constant_id_2)
                              ->AsFloatConstant();
  assert(float_constant_1->words() != float_constant_2->words() &&
         "The constants should not be identical.");
  assert(std::isfinite(float_constant_1->GetValueAsDouble()) &&
         "The constants must be finite numbers.");
  assert(std::isfinite(float_constant_2->GetValueAsDouble()) &&
         "The constants must be finite numbers.");
  bool first_constant_is_larger;
  assert(float_constant_1->type()->AsFloat()->width() ==
             float_constant_2->type()->AsFloat()->width() &&
         "First and second floating-point constants must have the same width.");
  if (float_constant_1->type()->AsFloat()->width() == 32) {
    first_constant_is_larger =
        float_constant_1->GetFloat() > float_constant_2->GetFloat();
  } else {
    assert(float_constant_1->type()->AsFloat()->width() == 64 &&
           "Supported floating-point widths are 32 and 64.");
    first_constant_is_larger =
        float_constant_1->GetDouble() > float_constant_2->GetDouble();
  }
  std::vector<SpvOp> greater_than_opcodes{
      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
      SpvOpFUnordGreaterThanEqual};
  std::vector<SpvOp> less_than_opcodes{
      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
      SpvOpFUnordGreaterThanEqual};

  ObfuscateBoolConstantViaConstantPair(
      depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
      float_constant_id_1, float_constant_id_2, first_constant_is_larger);
}

void FuzzerPassObfuscateConstants::
    ObfuscateBoolConstantViaSignedIntConstantPair(
        uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
        uint32_t signed_int_constant_id_1, uint32_t signed_int_constant_id_2) {
  auto signed_int_constant_1 =
      GetIRContext()
          ->get_constant_mgr()
          ->FindDeclaredConstant(signed_int_constant_id_1)
          ->AsIntConstant();
  auto signed_int_constant_2 =
      GetIRContext()
          ->get_constant_mgr()
          ->FindDeclaredConstant(signed_int_constant_id_2)
          ->AsIntConstant();
  assert(signed_int_constant_1->words() != signed_int_constant_2->words() &&
         "The constants should not be identical.");
  bool first_constant_is_larger;
  assert(signed_int_constant_1->type()->AsInteger()->width() ==
             signed_int_constant_2->type()->AsInteger()->width() &&
         "First and second floating-point constants must have the same width.");
  assert(signed_int_constant_1->type()->AsInteger()->IsSigned());
  assert(signed_int_constant_2->type()->AsInteger()->IsSigned());
  if (signed_int_constant_1->type()->AsFloat()->width() == 32) {
    first_constant_is_larger =
        signed_int_constant_1->GetS32() > signed_int_constant_2->GetS32();
  } else {
    assert(signed_int_constant_1->type()->AsFloat()->width() == 64 &&
           "Supported integer widths are 32 and 64.");
    first_constant_is_larger =
        signed_int_constant_1->GetS64() > signed_int_constant_2->GetS64();
  }
  std::vector<SpvOp> greater_than_opcodes{SpvOpSGreaterThan,
                                          SpvOpSGreaterThanEqual};
  std::vector<SpvOp> less_than_opcodes{SpvOpSLessThan, SpvOpSLessThanEqual};

  ObfuscateBoolConstantViaConstantPair(
      depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
      signed_int_constant_id_1, signed_int_constant_id_2,
      first_constant_is_larger);
}

void FuzzerPassObfuscateConstants::
    ObfuscateBoolConstantViaUnsignedIntConstantPair(
        uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
        uint32_t unsigned_int_constant_id_1,
        uint32_t unsigned_int_constant_id_2) {
  auto unsigned_int_constant_1 =
      GetIRContext()
          ->get_constant_mgr()
          ->FindDeclaredConstant(unsigned_int_constant_id_1)
          ->AsIntConstant();
  auto unsigned_int_constant_2 =
      GetIRContext()
          ->get_constant_mgr()
          ->FindDeclaredConstant(unsigned_int_constant_id_2)
          ->AsIntConstant();
  assert(unsigned_int_constant_1->words() != unsigned_int_constant_2->words() &&
         "The constants should not be identical.");
  bool first_constant_is_larger;
  assert(unsigned_int_constant_1->type()->AsInteger()->width() ==
             unsigned_int_constant_2->type()->AsInteger()->width() &&
         "First and second floating-point constants must have the same width.");
  assert(!unsigned_int_constant_1->type()->AsInteger()->IsSigned());
  assert(!unsigned_int_constant_2->type()->AsInteger()->IsSigned());
  if (unsigned_int_constant_1->type()->AsFloat()->width() == 32) {
    first_constant_is_larger =
        unsigned_int_constant_1->GetU32() > unsigned_int_constant_2->GetU32();
  } else {
    assert(unsigned_int_constant_1->type()->AsFloat()->width() == 64 &&
           "Supported integer widths are 32 and 64.");
    first_constant_is_larger =
        unsigned_int_constant_1->GetU64() > unsigned_int_constant_2->GetU64();
  }
  std::vector<SpvOp> greater_than_opcodes{SpvOpUGreaterThan,
                                          SpvOpUGreaterThanEqual};
  std::vector<SpvOp> less_than_opcodes{SpvOpULessThan, SpvOpULessThanEqual};

  ObfuscateBoolConstantViaConstantPair(
      depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
      unsigned_int_constant_id_1, unsigned_int_constant_id_2,
      first_constant_is_larger);
}

void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
    uint32_t depth, const protobufs::IdUseDescriptor& constant_use) {
  // We want to replace the boolean constant use with a binary expression over
  // scalar constants, but only if we can then potentially replace the constants
  // with uniforms of the same value.

  auto available_types_with_uniforms =
      GetFactManager()->GetTypesForWhichUniformValuesAreKnown();
  if (available_types_with_uniforms.empty()) {
    // Do not try to obfuscate if we do not have access to any uniform
    // elements with known values.
    return;
  }
  auto chosen_type_id = available_types_with_uniforms
      [GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
          static_cast<uint32_t>(available_types_with_uniforms.size()))];
  auto available_constants =
      GetFactManager()->GetConstantsAvailableFromUniformsForType(
          GetIRContext(), chosen_type_id);
  if (available_constants.size() == 1) {
    // TODO(afd): for now we only obfuscate a boolean if there are at least
    //  two constants available from uniforms, so that we can do a
    //  comparison between them. It would be good to be able to do the
    //  obfuscation even if there is only one such constant, if there is
    //  also another regular constant available.
    return;
  }

  // We know we have at least two known-to-be-constant uniforms of the chosen
  // type.  Pick one of them at random.
  auto constant_index_1 =
      GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
          static_cast<uint32_t>(available_constants.size()));
  uint32_t constant_index_2;

  // Now choose another one distinct from the first one.
  do {
    constant_index_2 = GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
        static_cast<uint32_t>(available_constants.size()));
  } while (constant_index_1 == constant_index_2);

  auto constant_id_1 = available_constants[constant_index_1];
  auto constant_id_2 = available_constants[constant_index_2];

  assert(constant_id_1 != 0 && constant_id_2 != 0 &&
         "We should not find an available constant with an id of 0.");

  // Now perform the obfuscation, according to whether the type of the constants
  // is float, signed int, or unsigned int.
  auto chosen_type = GetIRContext()->get_type_mgr()->GetType(chosen_type_id);
  if (chosen_type->AsFloat()) {
    ObfuscateBoolConstantViaFloatConstantPair(depth, constant_use,
                                              constant_id_1, constant_id_2);
  } else {
    assert(chosen_type->AsInteger() &&
           "We should only have uniform facts about ints and floats.");
    if (chosen_type->AsInteger()->IsSigned()) {
      ObfuscateBoolConstantViaSignedIntConstantPair(
          depth, constant_use, constant_id_1, constant_id_2);
    } else {
      ObfuscateBoolConstantViaUnsignedIntConstantPair(
          depth, constant_use, constant_id_1, constant_id_2);
    }
  }
}

void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
    uint32_t /*depth*/, const protobufs::IdUseDescriptor& constant_use) {
  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2670): consider
  //  additional ways to obfuscate scalar constants.

  // Check whether we know that any uniforms are guaranteed to be equal to the
  // scalar constant associated with |constant_use|.
  auto uniform_descriptors = GetFactManager()->GetUniformDescriptorsForConstant(
      GetIRContext(), constant_use.id_of_interest());
  if (uniform_descriptors.empty()) {
    // No relevant uniforms, so do not obfuscate.
    return;
  }

  // Choose a random available uniform known to be equal to the constant.
  protobufs::UniformBufferElementDescriptor uniform_descriptor =
      uniform_descriptors
          [GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
              static_cast<uint32_t>(uniform_descriptors.size()))];
  // Create, apply and record a transformation to replace the constant use with
  // the result of a load from the chosen uniform.
  auto transformation = TransformationReplaceConstantWithUniform(
      constant_use, uniform_descriptor, GetFuzzerContext()->GetFreshId(),
      GetFuzzerContext()->GetFreshId());
  // Transformation should be applicable by construction.
  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));
  transformation.Apply(GetIRContext(), GetFactManager());
  *GetTransformations()->add_transformation() = transformation.ToMessage();
}

void FuzzerPassObfuscateConstants::ObfuscateConstant(
    uint32_t depth, const protobufs::IdUseDescriptor& constant_use) {
  switch (GetIRContext()
              ->get_def_use_mgr()
              ->GetDef(constant_use.id_of_interest())
              ->opcode()) {
    case SpvOpConstantTrue:
    case SpvOpConstantFalse:
      ObfuscateBoolConstant(depth, constant_use);
      break;
    case SpvOpConstant:
      ObfuscateScalarConstant(depth, constant_use);
      break;
    default:
      assert(false && "The opcode should be one of the above.");
      break;
  }
}

void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
    const opt::Instruction& inst, uint32_t in_operand_index,
    uint32_t base_instruction_result_id,
    const std::map<SpvOp, uint32_t>& skipped_opcode_count,
    std::vector<protobufs::IdUseDescriptor>* constant_uses) {
  if (inst.GetInOperand(in_operand_index).type != SPV_OPERAND_TYPE_ID) {
    // The operand is not an id, so it cannot be a constant id.
    return;
  }
  auto operand_id = inst.GetSingleWordInOperand(in_operand_index);
  auto operand_definition =
      GetIRContext()->get_def_use_mgr()->GetDef(operand_id);
  switch (operand_definition->opcode()) {
    case SpvOpConstantFalse:
    case SpvOpConstantTrue:
    case SpvOpConstant: {
      // The operand is a constant id, so make an id use descriptor and record
      // it.
      protobufs::IdUseDescriptor id_use_descriptor;
      id_use_descriptor.set_id_of_interest(operand_id);
      id_use_descriptor.set_target_instruction_opcode(inst.opcode());
      id_use_descriptor.set_in_operand_index(in_operand_index);
      id_use_descriptor.set_base_instruction_result_id(
          base_instruction_result_id);
      id_use_descriptor.set_num_opcodes_to_ignore(
          skipped_opcode_count.find(inst.opcode()) == skipped_opcode_count.end()
              ? 0
              : skipped_opcode_count.at(inst.opcode()));
      constant_uses->push_back(id_use_descriptor);
    } break;
    default:
      break;
  }
}

void FuzzerPassObfuscateConstants::Apply() {
  // First, gather up all the constant uses available in the module, by going
  // through each block in each function.
  std::vector<protobufs::IdUseDescriptor> constant_uses;
  for (auto& function : *GetIRContext()->module()) {
    for (auto& block : function) {
      // For each constant use we encounter we are going to make an id use
      // descriptor. An id use is described with respect to a base instruction;
      // if there are instructions at the start of the block without result ids,
      // the base instruction will have to be the block's label.
      uint32_t base_instruction_result_id = block.id();

      // An id use descriptor also records how many instructions of a particular
      // opcode need to be skipped in order to find the instruction of interest
      // from the base instruction. We maintain a mapping that records a skip
      // count for each relevant opcode.
      std::map<SpvOp, uint32_t> skipped_opcode_count;

      // Go through each instruction in the block.
      for (auto& inst : block) {
        if (inst.HasResultId()) {
          // The instruction has a result id, so can be used as the base
          // instruction from now on, until another instruction with a result id
          // is encountered.
          base_instruction_result_id = inst.result_id();
          // Opcode skip counts were with respect to the previous base
          // instruction and are now irrelevant.
          skipped_opcode_count.clear();
        }

        // Consider each operand of the instruction, and add a constant id use
        // for the operand if relevant.
        for (uint32_t in_operand_index = 0;
             in_operand_index < inst.NumInOperands(); in_operand_index++) {
          MaybeAddConstantIdUse(inst, in_operand_index,
                                base_instruction_result_id,
                                skipped_opcode_count, &constant_uses);
        }

        if (!inst.HasResultId()) {
          // The instruction has no result id, so in order to identify future id
          // uses for instructions with this opcode from the existing base
          // instruction, we need to increase the skip count for this opcode.
          skipped_opcode_count[inst.opcode()] =
              skipped_opcode_count.find(inst.opcode()) ==
                      skipped_opcode_count.end()
                  ? 1
                  : skipped_opcode_count[inst.opcode()] + 1;
        }
      }
    }
  }

  // Go through the constant uses in a random order by repeatedly pulling out a
  // constant use at a random index.
  while (!constant_uses.empty()) {
    auto index = GetFuzzerContext()->GetRandomGenerator()->RandomUint32(
        static_cast<uint32_t>(constant_uses.size()));
    auto constant_use = std::move(constant_uses[index]);
    constant_uses.erase(constant_uses.begin() + index);
    // Decide probabilistically whether to skip or obfuscate this constant use.
    if (GetFuzzerContext()->GetRandomGenerator()->RandomPercentage() >
        GetFuzzerContext()->GetChanceOfObfuscatingConstant()) {
      continue;
    }
    ObfuscateConstant(0, constant_use);
  }
}

}  // namespace fuzz
}  // namespace spvtools
