// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause
// Compare non-incremental and incremental decode results of an arbitrary byte
// sequence.

#include <algorithm>
#include <cstdint>
#include <string>

#include "avif/avif.h"
#include "avif_fuzztest_helpers.h"
#include "avifincrtest_helpers.h"
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

using ::fuzztest::Arbitrary;

namespace avif {
namespace testutil {
namespace {

::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();

//------------------------------------------------------------------------------

struct DecoderInput {
  const uint8_t* available_bytes;
  size_t available_size;
  size_t read_size;
};

// A custom reader is necessary to get the number of bytes read by libavif.
// See avifIOReadFunc() documentation.
avifResult AvifIoRead(struct avifIO* io, uint32_t read_flags, uint64_t offset,
                      size_t size, avifROData* out) {
  DecoderInput* data = reinterpret_cast<DecoderInput*>(io->data);
  if (read_flags != 0 || !data || data->available_size < offset) {
    return AVIF_RESULT_IO_ERROR;
  }
  out->data = data->available_bytes + offset;
  out->size =
      std::min(size, data->available_size - static_cast<size_t>(offset));
  data->read_size =
      std::max(data->read_size, static_cast<size_t>(offset) + out->size);
  return AVIF_RESULT_OK;
}

//------------------------------------------------------------------------------

void DecodeIncr(const std::string& arbitrary_bytes, bool is_persistent,
                bool give_size_hint, bool use_nth_image_api) {
  ASSERT_FALSE(GetSeedDataDirs().empty());  // Make sure seeds are available.

  ImagePtr reference(avifImageCreateEmpty());
  ASSERT_NE(reference.get(), nullptr);

  DecoderInput data = {reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()),
                       arbitrary_bytes.size(), 0};
  avifIO io = {.destroy = nullptr,
               .read = AvifIoRead,
               .write = nullptr,
               .sizeHint = arbitrary_bytes.size(),
               .persistent = AVIF_TRUE,
               .data = &data};

  DecoderPtr decoder(avifDecoderCreate());
  ASSERT_NE(decoder.get(), nullptr);
  avifDecoderSetIO(decoder.get(), &io);
  // OSS-Fuzz limits the allocated memory to 2560 MB.
  constexpr uint32_t kMaxMem = 2560u * 1024 * 1024;
  // Consider at most four planes of 16-bit samples.
  constexpr uint32_t kMaxImageSize =
      kMaxMem / (AVIF_PLANE_COUNT_YUV + 1) / sizeof(uint16_t);
  // Reduce the limit further to include pixel buffer copies and other memory
  // allocations.
  constexpr uint32_t kImageSizeLimit = kMaxImageSize / 4;
  // avifDecoderParse returns AVIF_RESULT_NOT_IMPLEMENTED if kImageSizeLimit is
  // bigger than AVIF_DEFAULT_IMAGE_SIZE_LIMIT.
  static_assert(kImageSizeLimit <= AVIF_DEFAULT_IMAGE_SIZE_LIMIT,
                "Too big an image size limit");
  decoder->imageSizeLimit = kImageSizeLimit;

  if (avifDecoderRead(decoder.get(), reference.get()) == AVIF_RESULT_OK) {
    // Avoid timeouts by discarding big images decoded many times.
    // TODO(yguyon): Increase this arbitrary threshold but decode incrementally
    //               fewer times than as many bytes.
    if (reference->width * reference->height * data.read_size >
        8 * 1024 * 1024) {
      return;
    }
    // decodeIncrementally() will fail if there are leftover bytes.
    const avifRWData encoded_data = {const_cast<uint8_t*>(data.available_bytes),
                                     data.read_size};
    // No clue on whether encoded_data is tiled so use a lower bound of a single
    // tile for the whole image.
    // Note that an AVIF tile is at most as high as an AV1 frame
    // (aomediacodec.github.io/av1-spec says max_frame_height_minus_1 < 65536)
    // but libavif successfully decodes AVIF files with dimensions unrelated to
    // the underlying AV1 frame (for example a 1x1000000 AVIF for a 1x1 AV1).
    // Otherwise we could use the minimum of reference->height and 65536u below.
    const uint32_t max_cell_height = reference->height;
    const avifResult result = DecodeIncrementally(
        encoded_data, decoder.get(), is_persistent, give_size_hint,
        use_nth_image_api, *reference, max_cell_height);
    // The result does not matter, as long as we do not crash.
    (void)result;
  }
}

FUZZ_TEST(DecodeAvifFuzzTest, DecodeIncr)
    .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_AVIF}),
                 Arbitrary<bool>(), Arbitrary<bool>(), Arbitrary<bool>());

//------------------------------------------------------------------------------

}  // namespace
}  // namespace testutil
}  // namespace avif
