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 "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.h" 15 #include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.h" 16 17 namespace spdy { 18 19 class HpackFuzzUtil { 20 public: 21 // A GeneratorContext holds ordered header names & values which are 22 // initially seeded and then expanded with dynamically generated data. 23 struct GeneratorContext { 24 GeneratorContext(); 25 ~GeneratorContext(); 26 std::vector<std::string> names; 27 std::vector<std::string> values; 28 }; 29 30 // Initializes a GeneratorContext with a random seed and name/value fixtures. 31 static void InitializeGeneratorContext(GeneratorContext* context); 32 33 // Generates a header set from the generator context. 34 static Http2HeaderBlock NextGeneratedHeaderSet(GeneratorContext* context); 35 36 // Samples a size from the exponential distribution with mean |mean|, 37 // upper-bounded by |sanity_bound|. 38 static size_t SampleExponential(size_t mean, size_t sanity_bound); 39 40 // Holds an input string, and manages an offset into that string. 41 struct Input { 42 Input(); // Initializes |offset| to zero. 43 ~Input(); 44 remainingInput45 size_t remaining() { return input.size() - offset; } ptrInput46 const char* ptr() { return input.data() + offset; } 47 48 std::string input; 49 size_t offset = 0; 50 }; 51 52 // Returns true if the next header block was set at |out|. Returns 53 // false if no input header blocks remain. 54 static bool NextHeaderBlock(Input* input, absl::string_view* out); 55 56 // Returns the serialized header block length prefix for a block of 57 // |block_size| bytes. 58 static std::string HeaderBlockPrefix(size_t block_size); 59 60 // A FuzzerContext holds fuzzer input, as well as each of the decoder and 61 // encoder stages which fuzzed header blocks are processed through. 62 struct FuzzerContext { 63 FuzzerContext(); 64 ~FuzzerContext(); 65 std::unique_ptr<HpackDecoderAdapter> first_stage; 66 std::unique_ptr<HpackEncoder> second_stage; 67 std::unique_ptr<HpackDecoderAdapter> third_stage; 68 }; 69 70 static void InitializeFuzzerContext(FuzzerContext* context); 71 72 // Runs |input_block| through |first_stage| and, iff that succeeds, 73 // |second_stage| and |third_stage| as well. Returns whether all stages 74 // processed the input without error. 75 static bool RunHeaderBlockThroughFuzzerStages(FuzzerContext* context, 76 absl::string_view input_block); 77 78 // Flips random bits within |buffer|. The total number of flips is 79 // |flip_per_thousand| bits for every 1,024 bytes of |buffer_length|, 80 // rounding up. 81 static void FlipBits(uint8_t* buffer, 82 size_t buffer_length, 83 size_t flip_per_thousand); 84 }; 85 86 } // namespace spdy 87 88 #endif // NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_ 89