1 // Copyright 2016 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 "base/test/fuzzed_data_provider.h" 6 7 #include <algorithm> 8 #include <limits> 9 10 #include "base/logging.h" 11 12 namespace base { 13 14 FuzzedDataProvider::FuzzedDataProvider(const uint8_t* data, size_t size) 15 : remaining_data_(reinterpret_cast<const char*>(data), size) {} 16 17 FuzzedDataProvider::~FuzzedDataProvider() = default; 18 19 std::string FuzzedDataProvider::ConsumeBytes(size_t num_bytes) { 20 num_bytes = std::min(num_bytes, remaining_data_.length()); 21 StringPiece result(remaining_data_.data(), num_bytes); 22 remaining_data_ = remaining_data_.substr(num_bytes); 23 return result.as_string(); 24 } 25 26 std::string FuzzedDataProvider::ConsumeRemainingBytes() { 27 return ConsumeBytes(remaining_data_.length()); 28 } 29 30 uint32_t FuzzedDataProvider::ConsumeUint32InRange(uint32_t min, uint32_t max) { 31 CHECK_LE(min, max); 32 33 uint32_t range = max - min; 34 uint32_t offset = 0; 35 uint32_t result = 0; 36 37 while (offset < 32 && (range >> offset) > 0 && !remaining_data_.empty()) { 38 // Pull bytes off the end of the seed data. Experimentally, this seems to 39 // allow the fuzzer to more easily explore the input space. This makes 40 // sense, since it works by modifying inputs that caused new code to run, 41 // and this data is often used to encode length of data read by 42 // ConsumeBytes. Separating out read lengths makes it easier modify the 43 // contents of the data that is actually read. 44 uint8_t next_byte = remaining_data_.back(); 45 remaining_data_.remove_suffix(1); 46 result = (result << 8) | next_byte; 47 offset += 8; 48 } 49 50 // Avoid division by 0, in the case |range + 1| results in overflow. 51 if (range == std::numeric_limits<uint32_t>::max()) 52 return result; 53 54 return min + result % (range + 1); 55 } 56 57 std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) { 58 // Reads bytes from start of |remaining_data_|. Maps "\\" to "\", and maps "\" 59 // followed by anything else to the end of the string. As a result of this 60 // logic, a fuzzer can insert characters into the string, and the string will 61 // be lengthened to include those new characters, resulting in a more stable 62 // fuzzer than picking the length of a string independently from picking its 63 // contents. 64 std::string out; 65 for (size_t i = 0; i < max_length && !remaining_data_.empty(); ++i) { 66 char next = remaining_data_[0]; 67 remaining_data_.remove_prefix(1); 68 if (next == '\\' && !remaining_data_.empty()) { 69 next = remaining_data_[0]; 70 remaining_data_.remove_prefix(1); 71 if (next != '\\') 72 return out; 73 } 74 out += next; 75 } 76 return out; 77 } 78 79 int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) { 80 CHECK_LE(min, max); 81 82 uint32_t range = max - min; 83 return min + ConsumeUint32InRange(0, range); 84 } 85 86 bool FuzzedDataProvider::ConsumeBool() { 87 return (ConsumeUint8() & 0x01) == 0x01; 88 } 89 90 uint8_t FuzzedDataProvider::ConsumeUint8() { 91 return ConsumeUint32InRange(0, 0xFF); 92 } 93 94 uint16_t FuzzedDataProvider::ConsumeUint16() { 95 return ConsumeUint32InRange(0, 0xFFFF); 96 } 97 98 } // namespace base 99