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 18 matching lines...) Expand all Loading... |
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::StringPiece; | 34 using base::StringPiece; |
35 using base::RandBytesAsString; | 35 using base::RandBytesAsString; |
36 using std::map; | 36 using std::map; |
37 using std::string; | 37 using std::string; |
38 | 38 |
39 HpackFuzzUtil::GeneratorContext::GeneratorContext() {} | 39 HpackFuzzUtil::GeneratorContext::GeneratorContext() { |
40 HpackFuzzUtil::GeneratorContext::~GeneratorContext() {} | 40 } |
| 41 HpackFuzzUtil::GeneratorContext::~GeneratorContext() { |
| 42 } |
41 | 43 |
42 HpackFuzzUtil::Input::Input() : offset(0) {} | 44 HpackFuzzUtil::Input::Input() : offset(0) { |
43 HpackFuzzUtil::Input::~Input() {} | 45 } |
| 46 HpackFuzzUtil::Input::~Input() { |
| 47 } |
44 | 48 |
45 HpackFuzzUtil::FuzzerContext::FuzzerContext() {} | 49 HpackFuzzUtil::FuzzerContext::FuzzerContext() { |
46 HpackFuzzUtil::FuzzerContext::~FuzzerContext() {} | 50 } |
| 51 HpackFuzzUtil::FuzzerContext::~FuzzerContext() { |
| 52 } |
47 | 53 |
48 // static | 54 // static |
49 void HpackFuzzUtil::InitializeGeneratorContext(GeneratorContext* context) { | 55 void HpackFuzzUtil::InitializeGeneratorContext(GeneratorContext* context) { |
50 // Seed the generator with common header fixtures. | 56 // Seed the generator with common header fixtures. |
51 context->names.push_back(":authority"); | 57 context->names.push_back(":authority"); |
52 context->names.push_back(":path"); | 58 context->names.push_back(":path"); |
53 context->names.push_back(":status"); | 59 context->names.push_back(":status"); |
54 context->names.push_back("cookie"); | 60 context->names.push_back("cookie"); |
55 context->names.push_back("content-type"); | 61 context->names.push_back("content-type"); |
56 context->names.push_back("cache-control"); | 62 context->names.push_back("cache-control"); |
(...skipping 12 matching lines...) Expand all Loading... |
69 context->values.push_back("had=a;very_shiny=nose"); | 75 context->values.push_back("had=a;very_shiny=nose"); |
70 context->values.push_back("and\0if\0you\0ever\1saw\0it;"); | 76 context->values.push_back("and\0if\0you\0ever\1saw\0it;"); |
71 context->values.push_back("u; would=even;say-it\xffglows"); | 77 context->values.push_back("u; would=even;say-it\xffglows"); |
72 } | 78 } |
73 | 79 |
74 // static | 80 // static |
75 map<string, string> HpackFuzzUtil::NextGeneratedHeaderSet( | 81 map<string, string> HpackFuzzUtil::NextGeneratedHeaderSet( |
76 GeneratorContext* context) { | 82 GeneratorContext* context) { |
77 map<string, string> headers; | 83 map<string, string> headers; |
78 | 84 |
79 size_t header_count = 1 + SampleExponential(kHeaderCountMean, | 85 size_t header_count = |
80 kHeaderCountMax); | 86 1 + SampleExponential(kHeaderCountMean, kHeaderCountMax); |
81 for (size_t j = 0; j != header_count; ++j) { | 87 for (size_t j = 0; j != header_count; ++j) { |
82 size_t name_index = SampleExponential(kHeaderIndexMean, | 88 size_t name_index = SampleExponential(kHeaderIndexMean, kHeaderIndexMax); |
83 kHeaderIndexMax); | 89 size_t value_index = SampleExponential(kHeaderIndexMean, kHeaderIndexMax); |
84 size_t value_index = SampleExponential(kHeaderIndexMean, | |
85 kHeaderIndexMax); | |
86 string name, value; | 90 string name, value; |
87 if (name_index >= context->names.size()) { | 91 if (name_index >= context->names.size()) { |
88 context->names.push_back( | 92 context->names.push_back(RandBytesAsString( |
89 RandBytesAsString(1 + SampleExponential(kNameLengthMean, | 93 1 + SampleExponential(kNameLengthMean, kNameLengthMax))); |
90 kNameLengthMax))); | |
91 name = context->names.back(); | 94 name = context->names.back(); |
92 } else { | 95 } else { |
93 name = context->names[name_index]; | 96 name = context->names[name_index]; |
94 } | 97 } |
95 if (value_index >= context->values.size()) { | 98 if (value_index >= context->values.size()) { |
96 context->values.push_back( | 99 context->values.push_back(RandBytesAsString( |
97 RandBytesAsString(1 + SampleExponential(kValueLengthMean, | 100 1 + SampleExponential(kValueLengthMean, kValueLengthMax))); |
98 kValueLengthMax))); | |
99 value = context->values.back(); | 101 value = context->values.back(); |
100 } else { | 102 } else { |
101 value = context->values[value_index]; | 103 value = context->values[value_index]; |
102 } | 104 } |
103 headers[name] = value; | 105 headers[name] = value; |
104 } | 106 } |
105 return headers; | 107 return headers; |
106 } | 108 } |
107 | 109 |
108 // static | 110 // static |
109 size_t HpackFuzzUtil::SampleExponential(size_t mean, size_t sanity_bound) { | 111 size_t HpackFuzzUtil::SampleExponential(size_t mean, size_t sanity_bound) { |
110 return std::min<size_t>(-std::log(base::RandDouble()) * mean, sanity_bound); | 112 return std::min<size_t>(-std::log(base::RandDouble()) * mean, sanity_bound); |
111 } | 113 } |
112 | 114 |
113 // static | 115 // static |
114 bool HpackFuzzUtil::NextHeaderBlock(Input* input, | 116 bool HpackFuzzUtil::NextHeaderBlock(Input* input, StringPiece* out) { |
115 StringPiece* out) { | |
116 CHECK_LE(input->offset, input->input.size()); | 117 CHECK_LE(input->offset, input->input.size()); |
117 if (input->remaining() == 0) { | 118 if (input->remaining() == 0) { |
118 return false; | 119 return false; |
119 } | 120 } |
120 CHECK_LE(sizeof(uint32), input->remaining()); | 121 CHECK_LE(sizeof(uint32), input->remaining()); |
121 | 122 |
122 size_t length = ntohl(*reinterpret_cast<const uint32*>(input->ptr())); | 123 size_t length = ntohl(*reinterpret_cast<const uint32*>(input->ptr())); |
123 input->offset += sizeof(uint32); | 124 input->offset += sizeof(uint32); |
124 | 125 |
125 CHECK_LE(length, input->remaining()); | 126 CHECK_LE(length, input->remaining()); |
(...skipping 13 matching lines...) Expand all Loading... |
139 context->first_stage.reset(new HpackDecoder(ObtainHpackHuffmanTable())); | 140 context->first_stage.reset(new HpackDecoder(ObtainHpackHuffmanTable())); |
140 context->second_stage.reset(new HpackEncoder(ObtainHpackHuffmanTable())); | 141 context->second_stage.reset(new HpackEncoder(ObtainHpackHuffmanTable())); |
141 context->third_stage.reset(new HpackDecoder(ObtainHpackHuffmanTable())); | 142 context->third_stage.reset(new HpackDecoder(ObtainHpackHuffmanTable())); |
142 } | 143 } |
143 | 144 |
144 // static | 145 // static |
145 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(FuzzerContext* context, | 146 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(FuzzerContext* context, |
146 StringPiece input_block) { | 147 StringPiece input_block) { |
147 // First stage: Decode the input header block. This may fail on invalid input. | 148 // First stage: Decode the input header block. This may fail on invalid input. |
148 if (!context->first_stage->HandleControlFrameHeadersData( | 149 if (!context->first_stage->HandleControlFrameHeadersData( |
149 1, input_block.data(), input_block.size())) { | 150 1, input_block.data(), input_block.size())) { |
150 return false; | 151 return false; |
151 } | 152 } |
152 if (!context->first_stage->HandleControlFrameHeadersComplete(1)) { | 153 if (!context->first_stage->HandleControlFrameHeadersComplete(1)) { |
153 return false; | 154 return false; |
154 } | 155 } |
155 // Second stage: Re-encode the decoded header block. This must succeed. | 156 // Second stage: Re-encode the decoded header block. This must succeed. |
156 string second_stage_out; | 157 string second_stage_out; |
157 CHECK(context->second_stage->EncodeHeaderSet( | 158 CHECK(context->second_stage->EncodeHeaderSet( |
158 context->first_stage->decoded_block(), &second_stage_out)); | 159 context->first_stage->decoded_block(), &second_stage_out)); |
159 | 160 |
160 // Third stage: Expect a decoding of the re-encoded block to succeed. | 161 // Third stage: Expect a decoding of the re-encoded block to succeed. |
161 CHECK(context->third_stage->HandleControlFrameHeadersData( | 162 CHECK(context->third_stage->HandleControlFrameHeadersData( |
162 1, second_stage_out.data(), second_stage_out.length())); | 163 1, second_stage_out.data(), second_stage_out.length())); |
163 CHECK(context->third_stage->HandleControlFrameHeadersComplete(1)); | 164 CHECK(context->third_stage->HandleControlFrameHeadersComplete(1)); |
164 return true; | 165 return true; |
165 } | 166 } |
166 | 167 |
167 // static | 168 // static |
168 void HpackFuzzUtil::FlipBits(uint8* buffer, size_t buffer_length, | 169 void HpackFuzzUtil::FlipBits(uint8* buffer, |
| 170 size_t buffer_length, |
169 size_t flip_per_thousand) { | 171 size_t flip_per_thousand) { |
170 uint64 buffer_bit_length = buffer_length * 8u; | 172 uint64 buffer_bit_length = buffer_length * 8u; |
171 uint64 bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024); | 173 uint64 bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024); |
172 | 174 |
173 // Iteratively identify & flip offsets in the buffer bit-sequence. | 175 // Iteratively identify & flip offsets in the buffer bit-sequence. |
174 for (uint64 i = 0; i != bits_to_flip; ++i) { | 176 for (uint64 i = 0; i != bits_to_flip; ++i) { |
175 uint64 bit_offset = base::RandUint64() % buffer_bit_length; | 177 uint64 bit_offset = base::RandUint64() % buffer_bit_length; |
176 buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u)); | 178 buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u)); |
177 } | 179 } |
178 } | 180 } |
179 | 181 |
180 } // namespace net | 182 } // namespace net |
OLD | NEW |