// Copyright 2021 The Fuchsia 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <iomanip>
#include <iostream>
#include <limits>
#include <utility>
#include <vector>

#include <fuzzer/FuzzedDataProvider.h>
#include <test/conformance/cpp/libfuzzer_decode_encode.h>

namespace {

// Caller must ensure that `*size >= sizeof(T)`. Using `out` parameter ensures match with implicit
// template specialization.
template <typename T>
void FirstAs(const uint8_t** data, size_t* size, T* out) {
  assert(*size >= sizeof(T));

  // Use byte-by-byte copy strategy to avoid "load of misaligned address".
  uint8_t* out_bytes = (uint8_t*)(out);
  memcpy(out_bytes, *data, sizeof(T));

  *data += sizeof(T);
  *size -= sizeof(T);
}

// Caller must ensure that `*size >= sizeof(T)`. Using `out` parameter ensures match with implicit
// template specialization.
template <typename T>
void LastAs(const uint8_t** data, size_t* size, T* out) {
  assert(*size >= sizeof(T));

  // Use byte-by-byte copy strategy to avoid "load of misaligned address".
  uint8_t* out_bytes = (uint8_t*)(out);
  memcpy(out_bytes, *data + *size - sizeof(T), sizeof(T));

  *size -= sizeof(T);
}

constexpr uint64_t kMaxHandles = 2 * ZX_CHANNEL_MAX_MSG_HANDLES;

using DecoderEncoderForType = ::fidl::fuzzing::DecoderEncoderForType;
using DecoderEncoderProgress = ::fidl::fuzzing::DecoderEncoderProgress;
using DecoderEncoderStatus = ::fidl::fuzzing::DecoderEncoderStatus;

class DecoderEncoderInput {
 public:
  DecoderEncoderInput(const uint8_t* const bytes, const size_t size) : bytes_(bytes), size_(size) {}
  const uint8_t* data() const { return bytes_; }
  size_t size() const { return size_; }
  DecoderEncoderInput skip(size_t num_bytes) const {
    ZX_ASSERT(num_bytes < size_);
    return DecoderEncoderInput(bytes_ + num_bytes, size_ - num_bytes);
  }

 private:
  const uint8_t* const bytes_;
  const size_t size_;
};

std::string_view DecoderEncoderProgressString(DecoderEncoderProgress progress) {
  switch (progress) {
    case DecoderEncoderProgress::NoProgress:
      return "NoProgress";
    case DecoderEncoderProgress::InitializedForDecoding:
      return "InitializedForDecoding";
    case DecoderEncoderProgress::FirstDecodeSuccess:
      return "FirstDecodeSuccess";
    case DecoderEncoderProgress::FirstEncodeSuccess:
      return "FirstEncodeSuccess";
    case DecoderEncoderProgress::FirstEncodeVerified:
      return "FirstEncodeVerified";
    case DecoderEncoderProgress::SecondDecodeSuccess:
      return "SecondDecodeSuccess";
    case DecoderEncoderProgress::SecondEncodeSuccess:
      return "SecondEncodeSuccess";
  }
  __builtin_unreachable();
}

// Prints the contents of `first` to `stderr`, highlighting the bytes that differ from `second`.
template <typename T1, typename T2>
void ReportFirstByteArray(const T1& first, const char* const first_label, const T2& second,
                          const char* const second_label) {
  std::cerr << std::endl << first_label << " (diff'd against " << second_label << "):" << std::endl;
  if (first.size() == 0) {
    std::cerr << "<empty byte array>";
  } else {
    for (size_t i = 0; i < first.size(); i++) {
      if (i != 0 && i % 8 == 0)
        std::cerr << std::endl;

      const uint8_t* const first_data = first.data();
      const uint8_t* const second_data = second.data();
      const uint32_t uint_value = first_data[i];
      const bool is_diff = i >= second.size() || first_data[i] != second_data[i];

      std::cerr << (is_diff ? "[" : " ");
      std::cerr << "0x" << std::hex << std::setfill('0') << std::setw(2) << uint_value;
      std::cerr << (is_diff ? "]" : " ");
    }
  }

  std::cerr << std::endl;
}

#define REPORT_BYTE_ARRAY_DIFF(first, second)             \
  {                                                       \
    ReportFirstByteArray(first, #first, second, #second); \
    ReportFirstByteArray(second, #second, first, #first); \
  }

void ReportTestCase(const DecoderEncoderInput& input,
                    const DecoderEncoderForType& decoder_encoder_for_type,
                    const DecoderEncoderStatus& status) {
  std::cerr << std::endl
            << "FIDL wire type:" << std::endl
            << decoder_encoder_for_type.fidl_type_name << std::endl
            << "flexible envelope? " << std::boolalpha
            << decoder_encoder_for_type.has_flexible_envelope << std::endl;
  std::cerr << std::endl
            << "Decode/encode progress:" << std::endl
            << DecoderEncoderProgressString(status.progress) << std::endl;
  std::cerr << std::endl << "Decode/encode status:" << std::endl << status.status << std::endl;

  const std::vector<uint8_t>& first_encoded_bytes = status.first_encoded_bytes;
  REPORT_BYTE_ARRAY_DIFF(input, first_encoded_bytes);
  const std::vector<uint8_t>& second_encoded_bytes = status.second_encoded_bytes;
  REPORT_BYTE_ARRAY_DIFF(first_encoded_bytes, second_encoded_bytes);

  // TODO(fxbug.dev/72895): Report second handle data.
}

#define ASSERT_TEST_CASE(cond, input, decoder_encoder_for_type, status)  \
  {                                                                      \
    if (!(cond)) {                                                       \
      std::cerr << "TEST CASE ASSERTION FAILED: " << #cond << std::endl; \
      ReportTestCase(input, decoder_encoder_for_type, status);           \
    }                                                                    \
    assert(cond);                                                        \
  }

// If decoder/encoder progressed to a second round-trip, then check that it completed the round-trip
// successfully, and the re-encoded data from both round-trips match.
void CheckDecoderEncoderDoubleRoundTrip(const DecoderEncoderInput& input,
                                        const DecoderEncoderForType& decoder_encoder_for_type,
                                        const DecoderEncoderStatus& status) {
  // No symmetry verification unless first decode/encode round-trip succeeded and verified. This is
  // because unexpected data in a flexible envelope may be accepted on decode, but invalid to
  // re-encode.
  if (status.progress < DecoderEncoderProgress::FirstEncodeVerified)
    return;

    // If no early return above, then second decode-encode round-trip should have succeeded and data
    // should match.
#define ASSERT_LOCAL(cond) ASSERT_TEST_CASE(cond, input, decoder_encoder_for_type, status)
  ASSERT_LOCAL(status.progress >= DecoderEncoderProgress::SecondEncodeSuccess);
  ASSERT_LOCAL(status.first_encoded_bytes.size() == status.second_encoded_bytes.size());
  ASSERT_LOCAL(memcmp(status.first_encoded_bytes.data(), status.second_encoded_bytes.data(),
                      status.first_encoded_bytes.size()) == 0);
#undef ASSERT_LOCAL

  // TODO(fxbug.dev/72895): Check handle koids.
}

// If initial decoding succeeded, then check that a decode/encode round-trip succeeded, and
// re-encoded the same data.
void CheckDecoderEncoderRoundTrip(const DecoderEncoderInput& raw_input,
                                  const DecoderEncoderForType& decoder_encoder_for_type,
                                  const DecoderEncoderStatus& status) {
  // No symmetry verification unless initial decode succeeded.
  if (status.progress < DecoderEncoderProgress::FirstDecodeSuccess)
    return;

  // If the decoder encoder interpreted the bytes as a transactional message,
  // only the body will be decoded/encoded. The header part is used to modulate
  // the decoder wire format setting.
  const DecoderEncoderInput input = decoder_encoder_for_type.treat_bytes_as_transactional_message
                                        ? raw_input.skip(sizeof(fidl_message_header_t))
                                        : raw_input;

  // If no early return above, then first decode-encode round-trip should have succeeded and
  // verified, and data should match.
#define ASSERT_LOCAL(cond) ASSERT_TEST_CASE(cond, input, decoder_encoder_for_type, status)
  ASSERT_LOCAL(status.progress >= DecoderEncoderProgress::FirstEncodeVerified);
  ASSERT_LOCAL(input.size() == status.first_encoded_bytes.size());
  ASSERT_LOCAL(memcmp(input.data(), status.first_encoded_bytes.data(), input.size()) == 0);
#undef ASSERT_LOCAL

  // TODO(fxbug.dev/72895): Check handle koids.
}

#undef ASSERT_TEST_CASE

void CheckDecoderEncoderResult(const DecoderEncoderInput& input,
                               const DecoderEncoderForType& decoder_encoder_for_type,
                               const DecoderEncoderStatus& status) {
  if (decoder_encoder_for_type.has_flexible_envelope) {
    // Data with flexible envelopes can only perform symmetry checks on a "double round-trip"
    // because unexpected data in a flexible envelope may be accepted on decode, but invalid to
    // re-encode. Only after the re-encode succeeds and is verified can a symmetry check on a second
    // round-trip be performed (i.e., ensure both re-encodings match).
    CheckDecoderEncoderDoubleRoundTrip(input, decoder_encoder_for_type, status);
  } else {
    // No flexible envelope: Just check check single round-trip: successful decode implies
    // successful re-encode of the same data.
    CheckDecoderEncoderRoundTrip(input, decoder_encoder_for_type, status);
  }
}

}  // namespace

// This assertion guards `static_cast<uint32_t>(handle_infos.size())` below, where
// `handle_infos.size() = num_handles` and `num_handles <= kMaxHandles`.
static_assert(kMaxHandles <= std::numeric_limits<uint32_t>::max());

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  const uint8_t* remaining_data = data;
  size_t remaining_size = size;

  // Follow libfuzzer best practice: Length encodings drawn from tail.
  uint64_t num_handles;
  if (remaining_size < sizeof(num_handles))
    return 0;
  LastAs(&remaining_data, &remaining_size, &num_handles);
  // Test oversized, but not ludicrously sized, collection of handles.
  num_handles %= kMaxHandles + 1;

  // Size check: Handles.
  // 1. Handle type.
  //
  // TODO(markdittmer): Use interesting handle rights and values. This may require a change in
  // corpus data format.
  if (remaining_size < num_handles * sizeof(zx_obj_type_t))
    return 0;

  std::vector<zx_handle_t> handles;
  std::vector<fidl_channel_handle_metadata_t> handle_metadata;
  for (uint64_t i = 0; i < num_handles; i++) {
    zx_obj_type_t obj_type;

    // Consume data: Handles.
    // Note: Data (non-length-encodings) drawn from head.
    // 1. Handle type.
    FirstAs(&remaining_data, &remaining_size, &obj_type);
    // TODO(markdittmer): Use interesting handle rights and values. This may require a change in
    // corpus data format.
    handles.push_back(ZX_HANDLE_INVALID);
    handle_metadata.push_back(fidl_channel_handle_metadata_t{
        .obj_type = obj_type,
        .rights = 0,
    });
  }

  // Remaining data goes into `message`, and `message.size()` later cast as `uint32_t`.
  if (remaining_size > std::numeric_limits<uint32_t>::max())
    return 0;

  const DecoderEncoderInput decoder_encoder_input(remaining_data, remaining_size);

  for (auto decoder_encoder_for_type : fuzzing::test_conformance_decoder_encoders) {
    // Decode/encode require non-const data pointer: Copy remaining data into (non-const) vector.
    std::vector<uint8_t> message(decoder_encoder_input.data(),
                                 decoder_encoder_input.data() + decoder_encoder_input.size());

    // Result is unused on builds with assertions disabled.
    [[maybe_unused]] auto decode_encode_status = decoder_encoder_for_type.decoder_encoder(
        message.data(), static_cast<uint32_t>(message.size()), handles.data(),
        handle_metadata.data(), static_cast<uint32_t>(handles.size()));

    CheckDecoderEncoderResult(decoder_encoder_input, decoder_encoder_for_type,
                              decode_encode_status);
  }

  return 0;
}
