// Copyright 2016 The Chromium 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 <fuzzer/FuzzedDataProvider.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>

#include "absl/strings/string_view.h"
#include "quic/core/http/quic_header_list.h"
#include "quic/core/qpack/qpack_decoded_headers_accumulator.h"
#include "quic/core/qpack/qpack_decoder.h"
#include "quic/core/qpack/qpack_encoder.h"
#include "quic/core/qpack/qpack_stream_sender_delegate.h"
#include "quic/core/qpack/value_splitting_header_list.h"
#include "quic/core/quic_error_codes.h"
#include "quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
#include "common/quiche_circular_deque.h"
#include "spdy/core/spdy_header_block.h"

namespace quic {
namespace test {
namespace {

// Find the first occurrence of invalid characters NUL, LF, CR in |*value| and
// remove that and the remaining of the string.
void TruncateValueOnInvalidChars(std::string* value) {
  for (auto it = value->begin(); it != value->end(); ++it) {
    if (*it == '\0' || *it == '\n' || *it == '\r') {
      value->erase(it, value->end());
      return;
    }
  }
}

}  // anonymous namespace

// Class to hold QpackEncoder and its DecoderStreamErrorDelegate.
class EncodingEndpoint {
 public:
  EncodingEndpoint(uint64_t maximum_dynamic_table_capacity,
                   uint64_t maximum_blocked_streams)
      : encoder_(&decoder_stream_error_delegate) {
    encoder_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity);
    encoder_.SetMaximumBlockedStreams(maximum_blocked_streams);
  }

  ~EncodingEndpoint() {
    // Every reference should be acknowledged.
    QUICHE_CHECK_EQ(std::numeric_limits<uint64_t>::max(),
                    QpackEncoderPeer::smallest_blocking_index(&encoder_));
  }

  void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
    encoder_.set_qpack_stream_sender_delegate(delegate);
  }

  void SetDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity) {
    encoder_.SetDynamicTableCapacity(maximum_dynamic_table_capacity);
  }

  QpackStreamReceiver* decoder_stream_receiver() {
    return encoder_.decoder_stream_receiver();
  }

  std::string EncodeHeaderList(QuicStreamId stream_id,
                               const spdy::Http2HeaderBlock& header_list) {
    return encoder_.EncodeHeaderList(stream_id, header_list, nullptr);
  }

 private:
  // DecoderStreamErrorDelegate implementation that crashes on error.
  class CrashingDecoderStreamErrorDelegate
      : public QpackEncoder::DecoderStreamErrorDelegate {
   public:
    ~CrashingDecoderStreamErrorDelegate() override = default;

    void OnDecoderStreamError(QuicErrorCode error_code,
                              absl::string_view error_message) override {
      QUICHE_CHECK(false) << QuicErrorCodeToString(error_code) << " "
                          << error_message;
    }
  };

  CrashingDecoderStreamErrorDelegate decoder_stream_error_delegate;
  QpackEncoder encoder_;
};

// Class that receives all header blocks from the encoding endpoint and passes
// them to the decoding endpoint, with delay determined by fuzzer data,
// preserving order within each stream but not among streams.
class DelayedHeaderBlockTransmitter {
 public:
  class Visitor {
   public:
    virtual ~Visitor() = default;

    // If decoding of the previous header block is still in progress, then
    // DelayedHeaderBlockTransmitter will not start transmitting the next header
    // block.
    virtual bool IsDecodingInProgressOnStream(QuicStreamId stream_id) = 0;

    // Called when a header block starts.
    virtual void OnHeaderBlockStart(QuicStreamId stream_id) = 0;
    // Called when part or all of a header block is transmitted.
    virtual void OnHeaderBlockFragment(QuicStreamId stream_id,
                                       absl::string_view data) = 0;
    // Called when transmission of a header block is complete.
    virtual void OnHeaderBlockEnd(QuicStreamId stream_id) = 0;
  };

  DelayedHeaderBlockTransmitter(Visitor* visitor, FuzzedDataProvider* provider)
      : visitor_(visitor), provider_(provider) {}

  ~DelayedHeaderBlockTransmitter() { QUICHE_CHECK(header_blocks_.empty()); }

  // Enqueues |encoded_header_block| for delayed transmission.
  void SendEncodedHeaderBlock(QuicStreamId stream_id,
                              std::string encoded_header_block) {
    auto it = header_blocks_.lower_bound(stream_id);
    if (it == header_blocks_.end() || it->first != stream_id) {
      it = header_blocks_.insert(it, {stream_id, {}});
    }
    QUICHE_CHECK_EQ(stream_id, it->first);
    it->second.push(HeaderBlock(std::move(encoded_header_block)));
  }

  // Release some (possibly none) header block data.
  void MaybeTransmitSomeData() {
    if (header_blocks_.empty()) {
      return;
    }

    auto index =
        provider_->ConsumeIntegralInRange<size_t>(0, header_blocks_.size() - 1);
    auto it = header_blocks_.begin();
    std::advance(it, index);
    const QuicStreamId stream_id = it->first;

    // Do not start new header block if processing of previous header block is
    // blocked.
    if (visitor_->IsDecodingInProgressOnStream(stream_id)) {
      return;
    }

    auto& header_block_queue = it->second;
    HeaderBlock& header_block = header_block_queue.front();

    if (header_block.ConsumedLength() == 0) {
      visitor_->OnHeaderBlockStart(stream_id);
    }

    QUICHE_DCHECK_NE(0u, header_block.RemainingLength());

    size_t length = provider_->ConsumeIntegralInRange<size_t>(
        1, header_block.RemainingLength());
    visitor_->OnHeaderBlockFragment(stream_id, header_block.Consume(length));

    QUICHE_DCHECK_NE(0u, header_block.ConsumedLength());

    if (header_block.RemainingLength() == 0) {
      visitor_->OnHeaderBlockEnd(stream_id);

      header_block_queue.pop();
      if (header_block_queue.empty()) {
        header_blocks_.erase(it);
      }
    }
  }

  // Release all header block data.  Must be called before destruction.  All
  // encoder stream data must have been released before calling Flush() so that
  // all header blocks can be decoded synchronously.
  void Flush() {
    while (!header_blocks_.empty()) {
      auto it = header_blocks_.begin();
      const QuicStreamId stream_id = it->first;

      auto& header_block_queue = it->second;
      HeaderBlock& header_block = header_block_queue.front();

      if (header_block.ConsumedLength() == 0) {
        QUICHE_CHECK(!visitor_->IsDecodingInProgressOnStream(stream_id));
        visitor_->OnHeaderBlockStart(stream_id);
      }

      QUICHE_DCHECK_NE(0u, header_block.RemainingLength());

      visitor_->OnHeaderBlockFragment(stream_id,
                                      header_block.ConsumeRemaining());

      QUICHE_DCHECK_NE(0u, header_block.ConsumedLength());
      QUICHE_DCHECK_EQ(0u, header_block.RemainingLength());

      visitor_->OnHeaderBlockEnd(stream_id);
      QUICHE_CHECK(!visitor_->IsDecodingInProgressOnStream(stream_id));

      header_block_queue.pop();
      if (header_block_queue.empty()) {
        header_blocks_.erase(it);
      }
    }
  }

 private:
  // Helper class that allows the header block to be consumed in parts.
  class HeaderBlock {
   public:
    explicit HeaderBlock(std::string data)
        : data_(std::move(data)), offset_(0) {
      // Valid QPACK header block cannot be empty.
      QUICHE_DCHECK(!data_.empty());
    }

    size_t ConsumedLength() const { return offset_; }

    size_t RemainingLength() const { return data_.length() - offset_; }

    absl::string_view Consume(size_t length) {
      QUICHE_DCHECK_NE(0u, length);
      QUICHE_DCHECK_LE(length, RemainingLength());

      absl::string_view consumed = absl::string_view(&data_[offset_], length);
      offset_ += length;
      return consumed;
    }

    absl::string_view ConsumeRemaining() { return Consume(RemainingLength()); }

   private:
    // Complete header block.
    const std::string data_;

    // Offset of the part not consumed yet.  Same as number of consumed bytes.
    size_t offset_;
  };

  Visitor* const visitor_;
  FuzzedDataProvider* const provider_;

  std::map<QuicStreamId, std::queue<HeaderBlock>> header_blocks_;
};

// Class to decode and verify a header block, and in case of blocked decoding,
// keep necessary decoding context while waiting for decoding to complete.
class VerifyingDecoder : public QpackDecodedHeadersAccumulator::Visitor {
 public:
  class Visitor {
   public:
    virtual ~Visitor() = default;

    // Called when header block is decoded, either synchronously or
    // asynchronously.  Might destroy VerifyingDecoder.
    virtual void OnHeaderBlockDecoded(QuicStreamId stream_id) = 0;
  };

  VerifyingDecoder(QuicStreamId stream_id,
                   Visitor* visitor,
                   QpackDecoder* qpack_decoder,
                   QuicHeaderList expected_header_list)
      : stream_id_(stream_id),
        visitor_(visitor),
        accumulator_(
            stream_id,
            qpack_decoder,
            this,
            /* max_header_list_size = */ std::numeric_limits<size_t>::max()),
        expected_header_list_(std::move(expected_header_list)) {}

  VerifyingDecoder(const VerifyingDecoder&) = delete;
  VerifyingDecoder& operator=(const VerifyingDecoder&) = delete;
  // VerifyingDecoder must not be moved because it passes |this| to
  // |accumulator_| upon construction.
  VerifyingDecoder(VerifyingDecoder&&) = delete;
  VerifyingDecoder& operator=(VerifyingDecoder&&) = delete;

  virtual ~VerifyingDecoder() = default;

  // QpackDecodedHeadersAccumulator::Visitor implementation.
  void OnHeadersDecoded(QuicHeaderList headers,
                        bool header_list_size_limit_exceeded) override {
    // Verify headers.
    QUICHE_CHECK(!header_list_size_limit_exceeded);
    QUICHE_CHECK(expected_header_list_ == headers);

    // Might destroy |this|.
    visitor_->OnHeaderBlockDecoded(stream_id_);
  }

  void OnHeaderDecodingError(QuicErrorCode error_code,
                             absl::string_view error_message) override {
    QUICHE_CHECK(false) << QuicErrorCodeToString(error_code) << " "
                        << error_message;
  }

  void Decode(absl::string_view data) { accumulator_.Decode(data); }

  void EndHeaderBlock() { accumulator_.EndHeaderBlock(); }

 private:
  QuicStreamId stream_id_;
  Visitor* const visitor_;
  QpackDecodedHeadersAccumulator accumulator_;
  QuicHeaderList expected_header_list_;
};

// Class that holds QpackDecoder and its EncoderStreamErrorDelegate, and creates
// and keeps VerifyingDecoders for each received header block until decoding is
// complete.
class DecodingEndpoint : public DelayedHeaderBlockTransmitter::Visitor,
                         public VerifyingDecoder::Visitor {
 public:
  DecodingEndpoint(uint64_t maximum_dynamic_table_capacity,
                   uint64_t maximum_blocked_streams)
      : decoder_(maximum_dynamic_table_capacity,
                 maximum_blocked_streams,
                 &encoder_stream_error_delegate_) {}

  ~DecodingEndpoint() override {
    // All decoding must have been completed.
    QUICHE_CHECK(expected_header_lists_.empty());
    QUICHE_CHECK(verifying_decoders_.empty());
  }

  void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
    decoder_.set_qpack_stream_sender_delegate(delegate);
  }

  QpackStreamReceiver* encoder_stream_receiver() {
    return decoder_.encoder_stream_receiver();
  }

  void AddExpectedHeaderList(QuicStreamId stream_id,
                             QuicHeaderList expected_header_list) {
    auto it = expected_header_lists_.lower_bound(stream_id);
    if (it == expected_header_lists_.end() || it->first != stream_id) {
      it = expected_header_lists_.insert(it, {stream_id, {}});
    }
    QUICHE_CHECK_EQ(stream_id, it->first);
    it->second.push(std::move(expected_header_list));
  }

  // VerifyingDecoder::Visitor implementation.
  void OnHeaderBlockDecoded(QuicStreamId stream_id) override {
    auto result = verifying_decoders_.erase(stream_id);
    QUICHE_CHECK_EQ(1u, result);
  }

  // DelayedHeaderBlockTransmitter::Visitor implementation.
  bool IsDecodingInProgressOnStream(QuicStreamId stream_id) override {
    return verifying_decoders_.find(stream_id) != verifying_decoders_.end();
  }

  void OnHeaderBlockStart(QuicStreamId stream_id) override {
    QUICHE_CHECK(!IsDecodingInProgressOnStream(stream_id));
    auto it = expected_header_lists_.find(stream_id);
    QUICHE_CHECK(it != expected_header_lists_.end());

    auto& header_list_queue = it->second;
    QuicHeaderList expected_header_list = std::move(header_list_queue.front());

    header_list_queue.pop();
    if (header_list_queue.empty()) {
      expected_header_lists_.erase(it);
    }

    auto verifying_decoder = std::make_unique<VerifyingDecoder>(
        stream_id, this, &decoder_, std::move(expected_header_list));
    auto result =
        verifying_decoders_.insert({stream_id, std::move(verifying_decoder)});
    QUICHE_CHECK(result.second);
  }

  void OnHeaderBlockFragment(QuicStreamId stream_id,
                             absl::string_view data) override {
    auto it = verifying_decoders_.find(stream_id);
    QUICHE_CHECK(it != verifying_decoders_.end());
    it->second->Decode(data);
  }

  void OnHeaderBlockEnd(QuicStreamId stream_id) override {
    auto it = verifying_decoders_.find(stream_id);
    QUICHE_CHECK(it != verifying_decoders_.end());
    it->second->EndHeaderBlock();
  }

 private:
  // EncoderStreamErrorDelegate implementation that crashes on error.
  class CrashingEncoderStreamErrorDelegate
      : public QpackDecoder::EncoderStreamErrorDelegate {
   public:
    ~CrashingEncoderStreamErrorDelegate() override = default;

    void OnEncoderStreamError(QuicErrorCode error_code,
                              absl::string_view error_message) override {
      QUICHE_CHECK(false) << QuicErrorCodeToString(error_code) << " "
                          << error_message;
    }
  };

  CrashingEncoderStreamErrorDelegate encoder_stream_error_delegate_;
  QpackDecoder decoder_;

  // Expected header lists in order for each stream.
  std::map<QuicStreamId, std::queue<QuicHeaderList>> expected_header_lists_;

  // A VerifyingDecoder object keeps context necessary for asynchronously
  // decoding blocked header blocks.  It is destroyed as soon as it signals that
  // decoding is completed, which might happen synchronously within an
  // EndHeaderBlock() call.
  std::map<QuicStreamId, std::unique_ptr<VerifyingDecoder>> verifying_decoders_;
};

// Class that receives encoder stream data from the encoder and passes it to the
// decoder, or receives decoder stream data from the decoder and passes it to
// the encoder, with delay determined by fuzzer data.
class DelayedStreamDataTransmitter : public QpackStreamSenderDelegate {
 public:
  DelayedStreamDataTransmitter(QpackStreamReceiver* receiver,
                               FuzzedDataProvider* provider)
      : receiver_(receiver), provider_(provider) {}

  ~DelayedStreamDataTransmitter() { QUICHE_CHECK(stream_data.empty()); }

  // QpackStreamSenderDelegate implementation.
  void WriteStreamData(absl::string_view data) override {
    stream_data.push_back(std::string(data.data(), data.size()));
  }
  uint64_t NumBytesBuffered() const override { return 0; }

  // Release some (possibly none) delayed stream data.
  void MaybeTransmitSomeData() {
    auto count = provider_->ConsumeIntegral<uint8_t>();
    while (!stream_data.empty() && count > 0) {
      receiver_->Decode(stream_data.front());
      stream_data.pop_front();
      --count;
    }
  }

  // Release all delayed stream data.  Must be called before destruction.
  void Flush() {
    while (!stream_data.empty()) {
      receiver_->Decode(stream_data.front());
      stream_data.pop_front();
    }
  }

 private:
  QpackStreamReceiver* const receiver_;
  FuzzedDataProvider* const provider_;
  quiche::QuicheCircularDeque<std::string> stream_data;
};

// Generate header list using fuzzer data.
spdy::Http2HeaderBlock GenerateHeaderList(FuzzedDataProvider* provider) {
  spdy::Http2HeaderBlock header_list;
  uint8_t header_count = provider->ConsumeIntegral<uint8_t>();
  for (uint8_t header_index = 0; header_index < header_count; ++header_index) {
    if (provider->remaining_bytes() == 0) {
      // Do not add more headers if there is no more fuzzer data.
      break;
    }

    std::string name;
    std::string value;
    switch (provider->ConsumeIntegral<uint8_t>()) {
      case 0:
        // Static table entry with no header value.
        name = ":authority";
        break;
      case 1:
        // Static table entry with no header value, using non-empty header
        // value.
        name = ":authority";
        value = "www.example.org";
        break;
      case 2:
        // Static table entry with header value, using that header value.
        name = ":accept-encoding";
        value = "gzip, deflate";
        break;
      case 3:
        // Static table entry with header value, using empty header value.
        name = ":accept-encoding";
        break;
      case 4:
        // Static table entry with header value, using different, non-empty
        // header value.
        name = ":accept-encoding";
        value = "brotli";
        break;
      case 5:
        // Header name that has multiple entries in the static table,
        // using header value from one of them.
        name = ":method";
        value = "GET";
        break;
      case 6:
        // Header name that has multiple entries in the static table,
        // using empty header value.
        name = ":method";
        break;
      case 7:
        // Header name that has multiple entries in the static table,
        // using different, non-empty header value.
        name = ":method";
        value = "CONNECT";
        break;
      case 8:
        // Header name not in the static table, empty header value.
        name = "foo";
        value = "";
        break;
      case 9:
        // Header name not in the static table, non-empty fixed header value.
        name = "foo";
        value = "bar";
        break;
      case 10:
        // Header name not in the static table, fuzzed header value.
        name = "foo";
        value = provider->ConsumeRandomLengthString(128);
        TruncateValueOnInvalidChars(&value);
        break;
      case 11:
        // Another header name not in the static table, empty header value.
        name = "bar";
        value = "";
        break;
      case 12:
        // Another header name not in the static table, non-empty fixed header
        // value.
        name = "bar";
        value = "baz";
        break;
      case 13:
        // Another header name not in the static table, fuzzed header value.
        name = "bar";
        value = provider->ConsumeRandomLengthString(128);
        TruncateValueOnInvalidChars(&value);
        break;
      default:
        // Fuzzed header name and header value.
        name = provider->ConsumeRandomLengthString(128);
        value = provider->ConsumeRandomLengthString(128);
        TruncateValueOnInvalidChars(&value);
    }

    header_list.AppendValueOrAddHeader(name, value);
  }

  return header_list;
}

// Splits |*header_list| header values along '\0' or ';' separators.
QuicHeaderList SplitHeaderList(const spdy::Http2HeaderBlock& header_list) {
  QuicHeaderList split_header_list;
  split_header_list.OnHeaderBlockStart();

  size_t total_size = 0;
  ValueSplittingHeaderList splitting_header_list(&header_list);
  for (const auto& header : splitting_header_list) {
    split_header_list.OnHeader(header.first, header.second);
    total_size += header.first.size() + header.second.size();
  }

  split_header_list.OnHeaderBlockEnd(total_size, total_size);

  return split_header_list;
}

// This fuzzer exercises QpackEncoder and QpackDecoder.  It should be able to
// cover all possible code paths of QpackEncoder.  However, since the resulting
// header block is always valid and is encoded in a particular way, this fuzzer
// is not expected to cover all code paths of QpackDecoder.  On the other hand,
// encoding then decoding is expected to result in the original header list, and
// this fuzzer checks for that.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  FuzzedDataProvider provider(data, size);

  // Maximum 256 byte dynamic table.  Such a small size helps test draining
  // entries and eviction.
  const uint64_t maximum_dynamic_table_capacity =
      provider.ConsumeIntegral<uint8_t>();
  // Maximum 256 blocked streams.
  const uint64_t maximum_blocked_streams = provider.ConsumeIntegral<uint8_t>();

  // Set up encoder.
  EncodingEndpoint encoder(maximum_dynamic_table_capacity,
                           maximum_blocked_streams);

  // Set up decoder.
  DecodingEndpoint decoder(maximum_dynamic_table_capacity,
                           maximum_blocked_streams);

  // Transmit encoder stream data from encoder to decoder.
  DelayedStreamDataTransmitter encoder_stream_transmitter(
      decoder.encoder_stream_receiver(), &provider);
  encoder.set_qpack_stream_sender_delegate(&encoder_stream_transmitter);

  // Use a dynamic table as large as the peer allows.  This sends data on the
  // encoder stream, so it can only be done after delegate is set.
  encoder.SetDynamicTableCapacity(maximum_dynamic_table_capacity);

  // Transmit decoder stream data from encoder to decoder.
  DelayedStreamDataTransmitter decoder_stream_transmitter(
      encoder.decoder_stream_receiver(), &provider);
  decoder.set_qpack_stream_sender_delegate(&decoder_stream_transmitter);

  // Transmit header blocks from encoder to decoder.
  DelayedHeaderBlockTransmitter header_block_transmitter(&decoder, &provider);

  // Maximum 256 header lists to limit runtime and memory usage.
  auto header_list_count = provider.ConsumeIntegral<uint8_t>();
  while (header_list_count > 0 && provider.remaining_bytes() > 0) {
    const QuicStreamId stream_id = provider.ConsumeIntegral<uint8_t>();

    // Generate header list.
    spdy::Http2HeaderBlock header_list = GenerateHeaderList(&provider);

    // Encode header list.
    std::string encoded_header_block =
        encoder.EncodeHeaderList(stream_id, header_list);

    // TODO(bnc): Randomly cancel the stream.

    // Encoder splits |header_list| header values along '\0' or ';' separators.
    // Do the same here so that we get matching results.
    QuicHeaderList expected_header_list = SplitHeaderList(header_list);
    decoder.AddExpectedHeaderList(stream_id, std::move(expected_header_list));

    header_block_transmitter.SendEncodedHeaderBlock(
        stream_id, std::move(encoded_header_block));

    // Transmit some encoder stream data, decoder stream data, or header blocks
    // on the request stream, repeating a few times.
    for (auto transmit_data_count = provider.ConsumeIntegralInRange(1, 5);
         transmit_data_count > 0; --transmit_data_count) {
      encoder_stream_transmitter.MaybeTransmitSomeData();
      decoder_stream_transmitter.MaybeTransmitSomeData();
      header_block_transmitter.MaybeTransmitSomeData();
    }

    --header_list_count;
  }

  // Release all delayed encoder stream data so that remaining header blocks can
  // be decoded synchronously.
  encoder_stream_transmitter.Flush();
  // Release all delayed header blocks.
  header_block_transmitter.Flush();
  // Release all delayed decoder stream data.
  decoder_stream_transmitter.Flush();

  return 0;
}

}  // namespace test
}  // namespace quic
