OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/fuzzing/hpack_fuzz_util.h" | 5 #include "net/spdy/fuzzing/hpack_fuzz_util.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 const size_t kNameLengthMean = 5; | 26 const size_t kNameLengthMean = 5; |
27 const size_t kNameLengthMax = 30; | 27 const size_t kNameLengthMax = 30; |
28 // Approximate distribution of header value lengths. | 28 // Approximate distribution of header value lengths. |
29 const size_t kValueLengthMean = 15; | 29 const size_t kValueLengthMean = 15; |
30 const size_t kValueLengthMax = 75; | 30 const size_t kValueLengthMax = 75; |
31 | 31 |
32 } // namespace | 32 } // namespace |
33 | 33 |
34 using base::RandBytesAsString; | 34 using base::RandBytesAsString; |
35 using std::map; | 35 using std::map; |
36 using std::string; | |
37 | 36 |
38 HpackFuzzUtil::GeneratorContext::GeneratorContext() {} | 37 HpackFuzzUtil::GeneratorContext::GeneratorContext() {} |
39 HpackFuzzUtil::GeneratorContext::~GeneratorContext() {} | 38 HpackFuzzUtil::GeneratorContext::~GeneratorContext() {} |
40 | 39 |
41 HpackFuzzUtil::Input::Input() : offset(0) {} | 40 HpackFuzzUtil::Input::Input() : offset(0) {} |
42 HpackFuzzUtil::Input::~Input() {} | 41 HpackFuzzUtil::Input::~Input() {} |
43 | 42 |
44 HpackFuzzUtil::FuzzerContext::FuzzerContext() {} | 43 HpackFuzzUtil::FuzzerContext::FuzzerContext() {} |
45 HpackFuzzUtil::FuzzerContext::~FuzzerContext() {} | 44 HpackFuzzUtil::FuzzerContext::~FuzzerContext() {} |
46 | 45 |
(...skipping 28 matching lines...) Expand all Loading... |
75 GeneratorContext* context) { | 74 GeneratorContext* context) { |
76 SpdyHeaderBlock headers; | 75 SpdyHeaderBlock headers; |
77 | 76 |
78 size_t header_count = 1 + SampleExponential(kHeaderCountMean, | 77 size_t header_count = 1 + SampleExponential(kHeaderCountMean, |
79 kHeaderCountMax); | 78 kHeaderCountMax); |
80 for (size_t j = 0; j != header_count; ++j) { | 79 for (size_t j = 0; j != header_count; ++j) { |
81 size_t name_index = SampleExponential(kHeaderIndexMean, | 80 size_t name_index = SampleExponential(kHeaderIndexMean, |
82 kHeaderIndexMax); | 81 kHeaderIndexMax); |
83 size_t value_index = SampleExponential(kHeaderIndexMean, | 82 size_t value_index = SampleExponential(kHeaderIndexMean, |
84 kHeaderIndexMax); | 83 kHeaderIndexMax); |
85 string name, value; | 84 SpdyString name, value; |
86 if (name_index >= context->names.size()) { | 85 if (name_index >= context->names.size()) { |
87 context->names.push_back( | 86 context->names.push_back( |
88 RandBytesAsString(1 + SampleExponential(kNameLengthMean, | 87 RandBytesAsString(1 + SampleExponential(kNameLengthMean, |
89 kNameLengthMax))); | 88 kNameLengthMax))); |
90 name = context->names.back(); | 89 name = context->names.back(); |
91 } else { | 90 } else { |
92 name = context->names[name_index]; | 91 name = context->names[name_index]; |
93 } | 92 } |
94 if (value_index >= context->values.size()) { | 93 if (value_index >= context->values.size()) { |
95 context->values.push_back( | 94 context->values.push_back( |
(...skipping 29 matching lines...) Expand all Loading... |
125 | 124 |
126 if (input->remaining() < length) { | 125 if (input->remaining() < length) { |
127 return false; | 126 return false; |
128 } | 127 } |
129 *out = SpdyStringPiece(input->ptr(), length); | 128 *out = SpdyStringPiece(input->ptr(), length); |
130 input->offset += length; | 129 input->offset += length; |
131 return true; | 130 return true; |
132 } | 131 } |
133 | 132 |
134 // static | 133 // static |
135 string HpackFuzzUtil::HeaderBlockPrefix(size_t block_size) { | 134 SpdyString HpackFuzzUtil::HeaderBlockPrefix(size_t block_size) { |
136 uint32_t length = base::HostToNet32(static_cast<uint32_t>(block_size)); | 135 uint32_t length = base::HostToNet32(static_cast<uint32_t>(block_size)); |
137 return string(reinterpret_cast<char*>(&length), sizeof(uint32_t)); | 136 return SpdyString(reinterpret_cast<char*>(&length), sizeof(uint32_t)); |
138 } | 137 } |
139 | 138 |
140 // static | 139 // static |
141 void HpackFuzzUtil::InitializeFuzzerContext(FuzzerContext* context) { | 140 void HpackFuzzUtil::InitializeFuzzerContext(FuzzerContext* context) { |
142 context->first_stage.reset(new HpackDecoder()); | 141 context->first_stage.reset(new HpackDecoder()); |
143 context->second_stage.reset(new HpackEncoder(ObtainHpackHuffmanTable())); | 142 context->second_stage.reset(new HpackEncoder(ObtainHpackHuffmanTable())); |
144 context->third_stage.reset(new HpackDecoder()); | 143 context->third_stage.reset(new HpackDecoder()); |
145 } | 144 } |
146 | 145 |
147 // static | 146 // static |
148 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages( | 147 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages( |
149 FuzzerContext* context, | 148 FuzzerContext* context, |
150 SpdyStringPiece input_block) { | 149 SpdyStringPiece input_block) { |
151 // First stage: Decode the input header block. This may fail on invalid input. | 150 // First stage: Decode the input header block. This may fail on invalid input. |
152 if (!context->first_stage->HandleControlFrameHeadersData( | 151 if (!context->first_stage->HandleControlFrameHeadersData( |
153 input_block.data(), input_block.size())) { | 152 input_block.data(), input_block.size())) { |
154 return false; | 153 return false; |
155 } | 154 } |
156 if (!context->first_stage->HandleControlFrameHeadersComplete(nullptr)) { | 155 if (!context->first_stage->HandleControlFrameHeadersComplete(nullptr)) { |
157 return false; | 156 return false; |
158 } | 157 } |
159 // Second stage: Re-encode the decoded header block. This must succeed. | 158 // Second stage: Re-encode the decoded header block. This must succeed. |
160 string second_stage_out; | 159 SpdyString second_stage_out; |
161 CHECK(context->second_stage->EncodeHeaderSet( | 160 CHECK(context->second_stage->EncodeHeaderSet( |
162 context->first_stage->decoded_block(), &second_stage_out)); | 161 context->first_stage->decoded_block(), &second_stage_out)); |
163 | 162 |
164 // Third stage: Expect a decoding of the re-encoded block to succeed, but | 163 // Third stage: Expect a decoding of the re-encoded block to succeed, but |
165 // don't require it. It's possible for the stage-two encoder to produce an | 164 // don't require it. It's possible for the stage-two encoder to produce an |
166 // output which violates decoder size tolerances. | 165 // output which violates decoder size tolerances. |
167 if (!context->third_stage->HandleControlFrameHeadersData( | 166 if (!context->third_stage->HandleControlFrameHeadersData( |
168 second_stage_out.data(), second_stage_out.length())) { | 167 second_stage_out.data(), second_stage_out.length())) { |
169 return false; | 168 return false; |
170 } | 169 } |
(...skipping 11 matching lines...) Expand all Loading... |
182 uint64_t bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024); | 181 uint64_t bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024); |
183 | 182 |
184 // Iteratively identify & flip offsets in the buffer bit-sequence. | 183 // Iteratively identify & flip offsets in the buffer bit-sequence. |
185 for (uint64_t i = 0; i != bits_to_flip; ++i) { | 184 for (uint64_t i = 0; i != bits_to_flip; ++i) { |
186 uint64_t bit_offset = base::RandUint64() % buffer_bit_length; | 185 uint64_t bit_offset = base::RandUint64() % buffer_bit_length; |
187 buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u)); | 186 buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u)); |
188 } | 187 } |
189 } | 188 } |
190 | 189 |
191 } // namespace net | 190 } // namespace net |
OLD | NEW |