Add QpackDecoderStreamReceiver fuzzer.

Also change QpackEncoderStreamReceiver fuzzer to allow feeding empty strings to
Decoder().

PiperOrigin-RevId: 404601632
diff --git a/quic/core/qpack/fuzzer/qpack_decoder_stream_receiver_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_decoder_stream_receiver_fuzzer.cc
new file mode 100644
index 0000000..8c2d650
--- /dev/null
+++ b/quic/core/qpack/fuzzer/qpack_decoder_stream_receiver_fuzzer.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 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 <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "absl/strings/string_view.h"
+#include "quic/core/qpack/qpack_decoder_stream_receiver.h"
+#include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_stream.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+// A QpackDecoderStreamReceiver::Delegate implementation that ignores all
+// decoded instructions but keeps track of whether an error has been detected.
+class NoOpDelegate : public QpackDecoderStreamReceiver::Delegate {
+ public:
+  NoOpDelegate() : error_detected_(false) {}
+  ~NoOpDelegate() override = default;
+
+  void OnInsertCountIncrement(uint64_t /*increment*/) override {}
+  void OnHeaderAcknowledgement(QuicStreamId /*stream_id*/) override {}
+  void OnStreamCancellation(QuicStreamId /*stream_id*/) override {}
+  void OnErrorDetected(QuicErrorCode /*error_code*/,
+                       absl::string_view /*error_message*/) override {
+    error_detected_ = true;
+  }
+
+  bool error_detected() const { return error_detected_; }
+
+ private:
+  bool error_detected_;
+};
+
+}  // namespace
+
+// This fuzzer exercises QpackDecoderStreamReceiver.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  NoOpDelegate delegate;
+  QpackDecoderStreamReceiver receiver(&delegate);
+
+  FuzzedDataProvider provider(data, size);
+
+  while (!delegate.error_detected() && provider.remaining_bytes() != 0) {
+    // Process up to 64 kB fragments at a time.  Too small upper bound might not
+    // provide enough coverage, too large might make fuzzing too inefficient.
+    size_t fragment_size = provider.ConsumeIntegralInRange<uint16_t>(
+        0, std::numeric_limits<uint16_t>::max());
+    receiver.Decode(provider.ConsumeRandomLengthString(fragment_size));
+  }
+
+  return 0;
+}
+
+}  // namespace test
+}  // namespace quic
diff --git a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
index 5167536..ac7fac9 100644
--- a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
+++ b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
@@ -57,7 +57,7 @@
     // Process up to 64 kB fragments at a time.  Too small upper bound might not
     // provide enough coverage, too large might make fuzzing too inefficient.
     size_t fragment_size = provider.ConsumeIntegralInRange<uint16_t>(
-        1, std::numeric_limits<uint16_t>::max());
+        0, std::numeric_limits<uint16_t>::max());
     receiver.Decode(provider.ConsumeRandomLengthString(fragment_size));
   }