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 
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/qpack/qpack_encoder_stream_receiver.h"
12 #include "quiche/quic/platform/api/quic_logging.h"
13 
14 namespace quic {
15 namespace test {
16 namespace {
17 
18 // A QpackEncoderStreamReceiver::Delegate implementation that ignores all
19 // decoded instructions but keeps track of whether an error has been detected.
20 class NoOpDelegate : public QpackEncoderStreamReceiver::Delegate {
21  public:
NoOpDelegate()22   NoOpDelegate() : error_detected_(false) {}
23   ~NoOpDelegate() override = default;
24 
OnInsertWithNameReference(bool,uint64_t,absl::string_view)25   void OnInsertWithNameReference(bool /*is_static*/, uint64_t /*name_index*/,
26                                  absl::string_view /*value*/) override {}
OnInsertWithoutNameReference(absl::string_view,absl::string_view)27   void OnInsertWithoutNameReference(absl::string_view /*name*/,
28                                     absl::string_view /*value*/) override {}
OnDuplicate(uint64_t)29   void OnDuplicate(uint64_t /*index*/) override {}
OnSetDynamicTableCapacity(uint64_t)30   void OnSetDynamicTableCapacity(uint64_t /*capacity*/) override {}
OnErrorDetected(QuicErrorCode,absl::string_view)31   void OnErrorDetected(QuicErrorCode /*error_code*/,
32                        absl::string_view /*error_message*/) override {
33     error_detected_ = true;
34   }
35 
error_detected() const36   bool error_detected() const { return error_detected_; }
37 
38  private:
39   bool error_detected_;
40 };
41 
42 }  // namespace
43 
44 // This fuzzer exercises QpackEncoderStreamReceiver.
45 // Note that since string literals may be encoded with or without Huffman
46 // encoding, one could not expect identical encoded data if the decoded
47 // instructions were fed into QpackEncoderStreamSender.  Therefore there is no
48 // point in extending this fuzzer into a round-trip test.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)49 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
50   NoOpDelegate delegate;
51   QpackEncoderStreamReceiver receiver(&delegate);
52 
53   FuzzedDataProvider provider(data, size);
54 
55   while (!delegate.error_detected() && provider.remaining_bytes() != 0) {
56     // Process up to 64 kB fragments at a time.  Too small upper bound might not
57     // provide enough coverage, too large might make fuzzing too inefficient.
58     size_t fragment_size = provider.ConsumeIntegralInRange<uint16_t>(
59         0, std::numeric_limits<uint16_t>::max());
60     receiver.Decode(provider.ConsumeRandomLengthString(fragment_size));
61   }
62 
63   return 0;
64 }
65 
66 }  // namespace test
67 }  // namespace quic
68