1 // Copyright 2014 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_ 6 #define NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <vector> 13 14 #include "base/containers/span.h" 15 #include "net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.h" 16 #include "net/third_party/quiche/src/quiche/http2/hpack/hpack_decoder_adapter.h" 17 #include "net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.h" 18 19 namespace quiche { 20 class HttpHeaderBlock; 21 } 22 23 namespace spdy { 24 25 class HpackFuzzUtil { 26 public: 27 // A GeneratorContext holds ordered header names & values which are 28 // initially seeded and then expanded with dynamically generated data. 29 struct GeneratorContext { 30 GeneratorContext(); 31 ~GeneratorContext(); 32 std::vector<std::string> names; 33 std::vector<std::string> values; 34 }; 35 36 // Initializes a GeneratorContext with a random seed and name/value fixtures. 37 static void InitializeGeneratorContext(GeneratorContext* context); 38 39 // Generates a header set from the generator context. 40 static quiche::HttpHeaderBlock NextGeneratedHeaderSet( 41 GeneratorContext* context); 42 43 // Samples a size from the exponential distribution with mean |mean|, 44 // upper-bounded by |sanity_bound|. 45 static size_t SampleExponential(size_t mean, size_t sanity_bound); 46 47 // Holds an input string, and manages an offset into that string. 48 struct Input { 49 Input(); // Initializes |offset| to zero. 50 ~Input(); 51 52 // Returns a span over the next `bytes` many characters in the buffer, and 53 // advances the buffer offset past them. ReadSpanInput54 base::span<const uint8_t> ReadSpan(size_t bytes) { 55 auto out = RemainingBytes().first(bytes); 56 offset += bytes; 57 return out; 58 } 59 // Returns a span over the next `bytes` many characters in the buffer, and 60 // advances the buffer offset past them. 61 // 62 // This version takes a compile-time size and returns a fixed-size span. 63 template <size_t bytes> ReadSpanInput64 base::span<const uint8_t, bytes> ReadSpan() { 65 auto out = RemainingBytes().first<bytes>(); 66 offset += bytes; 67 return out; 68 } 69 70 // Returns a span over all remaining bytes in the input buffer. RemainingBytesInput71 base::span<const uint8_t> RemainingBytes() { 72 return base::as_byte_span(input).subspan(offset); 73 } 74 75 std::string input; 76 size_t offset = 0; 77 }; 78 79 // Returns true if the next header block was set at |out|. Returns 80 // false if no input header blocks remain. 81 static bool NextHeaderBlock(Input* input, std::string_view* out); 82 83 // Returns the serialized header block length prefix for a block of 84 // |block_size| bytes. 85 static std::string HeaderBlockPrefix(size_t block_size); 86 87 // A FuzzerContext holds fuzzer input, as well as each of the decoder and 88 // encoder stages which fuzzed header blocks are processed through. 89 struct FuzzerContext { 90 FuzzerContext(); 91 ~FuzzerContext(); 92 std::unique_ptr<HpackDecoderAdapter> first_stage; 93 std::unique_ptr<RecordingHeadersHandler> first_stage_handler; 94 std::unique_ptr<HpackEncoder> second_stage; 95 std::unique_ptr<HpackDecoderAdapter> third_stage; 96 std::unique_ptr<RecordingHeadersHandler> third_stage_handler; 97 }; 98 99 static void InitializeFuzzerContext(FuzzerContext* context); 100 101 // Runs |input_block| through |first_stage| and, iff that succeeds, 102 // |second_stage| and |third_stage| as well. Returns whether all stages 103 // processed the input without error. 104 static bool RunHeaderBlockThroughFuzzerStages(FuzzerContext* context, 105 std::string_view input_block); 106 107 // Flips random bits within |buffer|. The total number of flips is 108 // |flip_per_thousand| bits for every 1,024 bytes of |buffer_length|, 109 // rounding up. 110 static void FlipBits(uint8_t* buffer, 111 size_t buffer_length, 112 size_t flip_per_thousand); 113 }; 114 115 } // namespace spdy 116 117 #endif // NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_ 118