// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cstdint>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_boolean.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_hint_tables.h"
#include "core/fpdfapi/parser/cpdf_linearized_header.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fxcrt/cfx_bitstream.h"
#include "core/fxcrt/span.h"

int32_t GetData(const int32_t** data32, const uint8_t** data, size_t* size) {
  const int32_t* ret = *data32;
  ++(*data32);
  *data += 4;
  *size -= 4;
  return *ret;
}

class HintTableForFuzzing final : public CPDF_HintTables {
 public:
  HintTableForFuzzing(CPDF_LinearizedHeader* pLinearized,
                      int shared_hint_table_offset)
      : CPDF_HintTables(nullptr, pLinearized),
        shared_hint_table_offset_(shared_hint_table_offset) {}
  ~HintTableForFuzzing() override = default;

  void Fuzz(const uint8_t* data, size_t size) {
    if (shared_hint_table_offset_ <= 0) {
      return;
    }

    if (size < static_cast<size_t>(shared_hint_table_offset_)) {
      return;
    }

    CFX_BitStream bs(pdfium::span(data, size));
    if (!ReadPageHintTable(&bs)) {
      return;
    }
    ReadSharedObjHintTable(&bs, shared_hint_table_offset_);
  }

 private:
  int shared_hint_table_offset_;
};

class FakeLinearized final : public CPDF_LinearizedHeader {
 public:
  explicit FakeLinearized(CPDF_Dictionary* linearized_dict)
      : CPDF_LinearizedHeader(linearized_dict, 0) {}
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  // Need 28 bytes for |linearized_dict|.
  // The header section of page offset hint table is 36 bytes.
  // The header section of shared object hint table is 24 bytes.
  if (size < 28 + 36 + 24) {
    return 0;
  }

  const int32_t* data32 = reinterpret_cast<const int32_t*>(data);

  auto linearized_dict = pdfium::MakeRetain<CPDF_Dictionary>();
  // Set initial value.
  linearized_dict->SetNewFor<CPDF_Boolean>("Linearized", true);
  // Set first page end offset
  linearized_dict->SetNewFor<CPDF_Number>("E", GetData(&data32, &data, &size));
  // Set page count
  linearized_dict->SetNewFor<CPDF_Number>("N", GetData(&data32, &data, &size));
  // Set first page obj num
  linearized_dict->SetNewFor<CPDF_Number>("O", GetData(&data32, &data, &size));
  // Set first page no
  linearized_dict->SetNewFor<CPDF_Number>("P", GetData(&data32, &data, &size));

  auto hint_info = pdfium::MakeRetain<CPDF_Array>();
  // Add primary hint stream offset
  hint_info->AppendNew<CPDF_Number>(GetData(&data32, &data, &size));
  // Add primary hint stream size
  hint_info->AppendNew<CPDF_Number>(GetData(&data32, &data, &size));
  // Set hint stream info.
  linearized_dict->SetFor("H", std::move(hint_info));

  const int shared_hint_table_offset = GetData(&data32, &data, &size);

  {
    FakeLinearized linearized(linearized_dict.Get());
    HintTableForFuzzing hint_table(&linearized, shared_hint_table_offset);
    hint_table.Fuzz(data, size);
  }
  return 0;
}
