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