1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fuzzer/FuzzedDataProvider.h>
6 
7 #include <cstddef>
8 #include <cstdint>
9 #include <limits>
10 
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/qpack/qpack_decoder_stream_receiver.h"
13 #include "quiche/quic/core/quic_error_codes.h"
14 #include "quiche/quic/core/quic_stream.h"
15 
16 namespace quic {
17 namespace test {
18 namespace {
19 
20 // A QpackDecoderStreamReceiver::Delegate implementation that ignores all
21 // decoded instructions but keeps track of whether an error has been detected.
22 class NoOpDelegate : public QpackDecoderStreamReceiver::Delegate {
23  public:
NoOpDelegate()24   NoOpDelegate() : error_detected_(false) {}
25   ~NoOpDelegate() override = default;
26 
OnInsertCountIncrement(uint64_t)27   void OnInsertCountIncrement(uint64_t /*increment*/) override {}
OnHeaderAcknowledgement(QuicStreamId)28   void OnHeaderAcknowledgement(QuicStreamId /*stream_id*/) override {}
OnStreamCancellation(QuicStreamId)29   void OnStreamCancellation(QuicStreamId /*stream_id*/) override {}
OnErrorDetected(QuicErrorCode,absl::string_view)30   void OnErrorDetected(QuicErrorCode /*error_code*/,
31                        absl::string_view /*error_message*/) override {
32     error_detected_ = true;
33   }
34 
error_detected() const35   bool error_detected() const { return error_detected_; }
36 
37  private:
38   bool error_detected_;
39 };
40 
41 }  // namespace
42 
43 // This fuzzer exercises QpackDecoderStreamReceiver.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)44 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
45   NoOpDelegate delegate;
46   QpackDecoderStreamReceiver receiver(&delegate);
47 
48   FuzzedDataProvider provider(data, size);
49 
50   while (!delegate.error_detected() && provider.remaining_bytes() != 0) {
51     // Process up to 64 kB fragments at a time.  Too small upper bound might not
52     // provide enough coverage, too large might make fuzzing too inefficient.
53     size_t fragment_size = provider.ConsumeIntegralInRange<uint16_t>(
54         0, std::numeric_limits<uint16_t>::max());
55     receiver.Decode(provider.ConsumeRandomLengthString(fragment_size));
56   }
57 
58   return 0;
59 }
60 
61 }  // namespace test
62 }  // namespace quic
63