| 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 |