You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.1 KiB
99 lines
3.1 KiB
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/test/fuzzed_data_provider.h"
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
#include "base/logging.h"
|
|
|
|
namespace base {
|
|
|
|
FuzzedDataProvider::FuzzedDataProvider(const uint8_t* data, size_t size)
|
|
: remaining_data_(reinterpret_cast<const char*>(data), size) {}
|
|
|
|
FuzzedDataProvider::~FuzzedDataProvider() = default;
|
|
|
|
std::string FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
|
|
num_bytes = std::min(num_bytes, remaining_data_.length());
|
|
StringPiece result(remaining_data_.data(), num_bytes);
|
|
remaining_data_ = remaining_data_.substr(num_bytes);
|
|
return result.as_string();
|
|
}
|
|
|
|
std::string FuzzedDataProvider::ConsumeRemainingBytes() {
|
|
return ConsumeBytes(remaining_data_.length());
|
|
}
|
|
|
|
uint32_t FuzzedDataProvider::ConsumeUint32InRange(uint32_t min, uint32_t max) {
|
|
CHECK_LE(min, max);
|
|
|
|
uint32_t range = max - min;
|
|
uint32_t offset = 0;
|
|
uint32_t result = 0;
|
|
|
|
while (offset < 32 && (range >> offset) > 0 && !remaining_data_.empty()) {
|
|
// Pull bytes off the end of the seed data. Experimentally, this seems to
|
|
// allow the fuzzer to more easily explore the input space. This makes
|
|
// sense, since it works by modifying inputs that caused new code to run,
|
|
// and this data is often used to encode length of data read by
|
|
// ConsumeBytes. Separating out read lengths makes it easier modify the
|
|
// contents of the data that is actually read.
|
|
uint8_t next_byte = remaining_data_.back();
|
|
remaining_data_.remove_suffix(1);
|
|
result = (result << 8) | next_byte;
|
|
offset += 8;
|
|
}
|
|
|
|
// Avoid division by 0, in the case |range + 1| results in overflow.
|
|
if (range == std::numeric_limits<uint32_t>::max())
|
|
return result;
|
|
|
|
return min + result % (range + 1);
|
|
}
|
|
|
|
std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
|
|
// Reads bytes from start of |remaining_data_|. Maps "\\" to "\", and maps "\"
|
|
// followed by anything else to the end of the string. As a result of this
|
|
// logic, a fuzzer can insert characters into the string, and the string will
|
|
// be lengthened to include those new characters, resulting in a more stable
|
|
// fuzzer than picking the length of a string independently from picking its
|
|
// contents.
|
|
std::string out;
|
|
for (size_t i = 0; i < max_length && !remaining_data_.empty(); ++i) {
|
|
char next = remaining_data_[0];
|
|
remaining_data_.remove_prefix(1);
|
|
if (next == '\\' && !remaining_data_.empty()) {
|
|
next = remaining_data_[0];
|
|
remaining_data_.remove_prefix(1);
|
|
if (next != '\\')
|
|
return out;
|
|
}
|
|
out += next;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) {
|
|
CHECK_LE(min, max);
|
|
|
|
uint32_t range = max - min;
|
|
return min + ConsumeUint32InRange(0, range);
|
|
}
|
|
|
|
bool FuzzedDataProvider::ConsumeBool() {
|
|
return (ConsumeUint8() & 0x01) == 0x01;
|
|
}
|
|
|
|
uint8_t FuzzedDataProvider::ConsumeUint8() {
|
|
return ConsumeUint32InRange(0, 0xFF);
|
|
}
|
|
|
|
uint16_t FuzzedDataProvider::ConsumeUint16() {
|
|
return ConsumeUint32InRange(0, 0xFFFF);
|
|
}
|
|
|
|
} // namespace base
|