Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1601)

Side by Side Diff: net/spdy/fuzzing/hpack_fuzz_util.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/fuzzing/hpack_fuzz_util.h ('k') | net/spdy/fuzzing/hpack_fuzz_util_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include "net/spdy/fuzzing/hpack_fuzz_util.h"
6
7 #include <algorithm>
8 #include <cmath>
9
10 #include "base/rand_util.h"
11 #include "base/sys_byteorder.h"
12 #include "net/spdy/hpack/hpack_constants.h"
13
14 namespace net {
15
16 namespace {
17
18 // Sampled exponential distribution parameters:
19 // Number of headers in each header set.
20 const size_t kHeaderCountMean = 7;
21 const size_t kHeaderCountMax = 50;
22 // Selected index within list of headers.
23 const size_t kHeaderIndexMean = 20;
24 const size_t kHeaderIndexMax = 200;
25 // Approximate distribution of header name lengths.
26 const size_t kNameLengthMean = 5;
27 const size_t kNameLengthMax = 30;
28 // Approximate distribution of header value lengths.
29 const size_t kValueLengthMean = 15;
30 const size_t kValueLengthMax = 75;
31
32 } // namespace
33
34 using base::RandBytesAsString;
35 using std::map;
36
37 HpackFuzzUtil::GeneratorContext::GeneratorContext() {}
38 HpackFuzzUtil::GeneratorContext::~GeneratorContext() {}
39
40 HpackFuzzUtil::Input::Input() : offset(0) {}
41 HpackFuzzUtil::Input::~Input() {}
42
43 HpackFuzzUtil::FuzzerContext::FuzzerContext() {}
44 HpackFuzzUtil::FuzzerContext::~FuzzerContext() {}
45
46 // static
47 void HpackFuzzUtil::InitializeGeneratorContext(GeneratorContext* context) {
48 // Seed the generator with common header fixtures.
49 context->names.push_back(":authority");
50 context->names.push_back(":path");
51 context->names.push_back(":status");
52 context->names.push_back("cookie");
53 context->names.push_back("content-type");
54 context->names.push_back("cache-control");
55 context->names.push_back("date");
56 context->names.push_back("user-agent");
57 context->names.push_back("via");
58
59 context->values.push_back("/");
60 context->values.push_back("/index.html");
61 context->values.push_back("200");
62 context->values.push_back("404");
63 context->values.push_back("");
64 context->values.push_back("baz=bing; foo=bar; garbage");
65 context->values.push_back("baz=bing; fizzle=fazzle; garbage");
66 context->values.push_back("rudolph=the-red-nosed-reindeer");
67 context->values.push_back("had=a;very_shiny=nose");
68 context->values.push_back("and\0if\0you\0ever\1saw\0it;");
69 context->values.push_back("u; would=even;say-it\xffglows");
70 }
71
72 // static
73 SpdyHeaderBlock HpackFuzzUtil::NextGeneratedHeaderSet(
74 GeneratorContext* context) {
75 SpdyHeaderBlock headers;
76
77 size_t header_count = 1 + SampleExponential(kHeaderCountMean,
78 kHeaderCountMax);
79 for (size_t j = 0; j != header_count; ++j) {
80 size_t name_index = SampleExponential(kHeaderIndexMean,
81 kHeaderIndexMax);
82 size_t value_index = SampleExponential(kHeaderIndexMean,
83 kHeaderIndexMax);
84 SpdyString name, value;
85 if (name_index >= context->names.size()) {
86 context->names.push_back(
87 RandBytesAsString(1 + SampleExponential(kNameLengthMean,
88 kNameLengthMax)));
89 name = context->names.back();
90 } else {
91 name = context->names[name_index];
92 }
93 if (value_index >= context->values.size()) {
94 context->values.push_back(
95 RandBytesAsString(1 + SampleExponential(kValueLengthMean,
96 kValueLengthMax)));
97 value = context->values.back();
98 } else {
99 value = context->values[value_index];
100 }
101 headers[name] = value;
102 }
103 return headers;
104 }
105
106 // static
107 size_t HpackFuzzUtil::SampleExponential(size_t mean, size_t sanity_bound) {
108 return std::min(static_cast<size_t>(-std::log(base::RandDouble()) * mean),
109 sanity_bound);
110 }
111
112 // static
113 bool HpackFuzzUtil::NextHeaderBlock(Input* input, SpdyStringPiece* out) {
114 // ClusterFuzz may truncate input files if the fuzzer ran out of allocated
115 // disk space. Be tolerant of these.
116 CHECK_LE(input->offset, input->input.size());
117 if (input->remaining() < sizeof(uint32_t)) {
118 return false;
119 }
120
121 size_t length =
122 base::NetToHost32(*reinterpret_cast<const uint32_t*>(input->ptr()));
123 input->offset += sizeof(uint32_t);
124
125 if (input->remaining() < length) {
126 return false;
127 }
128 *out = SpdyStringPiece(input->ptr(), length);
129 input->offset += length;
130 return true;
131 }
132
133 // static
134 SpdyString HpackFuzzUtil::HeaderBlockPrefix(size_t block_size) {
135 uint32_t length = base::HostToNet32(static_cast<uint32_t>(block_size));
136 return SpdyString(reinterpret_cast<char*>(&length), sizeof(uint32_t));
137 }
138
139 // static
140 void HpackFuzzUtil::InitializeFuzzerContext(FuzzerContext* context) {
141 context->first_stage.reset(new HpackDecoder());
142 context->second_stage.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
143 context->third_stage.reset(new HpackDecoder());
144 }
145
146 // static
147 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(
148 FuzzerContext* context,
149 SpdyStringPiece input_block) {
150 // First stage: Decode the input header block. This may fail on invalid input.
151 if (!context->first_stage->HandleControlFrameHeadersData(
152 input_block.data(), input_block.size())) {
153 return false;
154 }
155 if (!context->first_stage->HandleControlFrameHeadersComplete(nullptr)) {
156 return false;
157 }
158 // Second stage: Re-encode the decoded header block. This must succeed.
159 SpdyString second_stage_out;
160 CHECK(context->second_stage->EncodeHeaderSet(
161 context->first_stage->decoded_block(), &second_stage_out));
162
163 // Third stage: Expect a decoding of the re-encoded block to succeed, but
164 // don't require it. It's possible for the stage-two encoder to produce an
165 // output which violates decoder size tolerances.
166 if (!context->third_stage->HandleControlFrameHeadersData(
167 second_stage_out.data(), second_stage_out.length())) {
168 return false;
169 }
170 if (!context->third_stage->HandleControlFrameHeadersComplete(nullptr)) {
171 return false;
172 }
173 return true;
174 }
175
176 // static
177 void HpackFuzzUtil::FlipBits(uint8_t* buffer,
178 size_t buffer_length,
179 size_t flip_per_thousand) {
180 uint64_t buffer_bit_length = buffer_length * 8u;
181 uint64_t bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024);
182
183 // Iteratively identify & flip offsets in the buffer bit-sequence.
184 for (uint64_t i = 0; i != bits_to_flip; ++i) {
185 uint64_t bit_offset = base::RandUint64() % buffer_bit_length;
186 buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u));
187 }
188 }
189
190 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/fuzzing/hpack_fuzz_util.h ('k') | net/spdy/fuzzing/hpack_fuzz_util_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698