1// Copyright 2014 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#ifndef NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
6#define NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
7
8#include <string>
9#include <vector>
10
11#include "base/memory/scoped_ptr.h"
12#include "base/strings/string_piece.h"
13#include "net/base/net_export.h"
14#include "net/spdy/hpack_decoder.h"
15#include "net/spdy/hpack_encoder.h"
16
17namespace net {
18
19class NET_EXPORT_PRIVATE 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 NET_EXPORT_PRIVATE 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 std::map<std::string, std::string> NextGeneratedHeaderSet(
35      GeneratorContext* context);
36
37  // Samples a size from the exponential distribution with mean |mean|,
38  // upper-bounded by |sanity_bound|.
39  static size_t SampleExponential(size_t mean, size_t sanity_bound);
40
41  // Holds an input string, and manages an offset into that string.
42  struct NET_EXPORT_PRIVATE Input {
43    Input();  // Initializes |offset| to zero.
44    ~Input();
45
46    size_t remaining() {
47      return input.size() - offset;
48    }
49    const char* ptr() {
50      return input.data() + offset;
51    }
52
53    std::string input;
54    size_t offset;
55  };
56
57  // Returns true if the next header block was set at |out|. Returns
58  // false if no input header blocks remain.
59  static bool NextHeaderBlock(Input* input, base::StringPiece* out);
60
61  // Returns the serialized header block length prefix for a block of
62  // |block_size| bytes.
63  static std::string HeaderBlockPrefix(size_t block_size);
64
65  // A FuzzerContext holds fuzzer input, as well as each of the decoder and
66  // encoder stages which fuzzed header blocks are processed through.
67  struct NET_EXPORT_PRIVATE FuzzerContext {
68    FuzzerContext();
69    ~FuzzerContext();
70    scoped_ptr<HpackDecoder> first_stage;
71    scoped_ptr<HpackEncoder> second_stage;
72    scoped_ptr<HpackDecoder> third_stage;
73  };
74
75  static void InitializeFuzzerContext(FuzzerContext* context);
76
77  // Runs |input_block| through |first_stage| and, iff that succeeds,
78  // |second_stage| and |third_stage| as well. Returns whether all stages
79  // processed the input without error.
80  static bool RunHeaderBlockThroughFuzzerStages(FuzzerContext* context,
81                                                base::StringPiece input_block);
82
83  // Flips random bits within |buffer|. The total number of flips is
84  // |flip_per_thousand| bits for every 1,024 bytes of |buffer_length|,
85  // rounding up.
86  static void FlipBits(uint8* buffer,
87                       size_t buffer_length,
88                       size_t flip_per_thousand);
89};
90
91}  // namespace net
92
93#endif  // NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
94