// Helper class to take care of the fuzzer input, read from it, and keep track // of when the end of the data has been reached. class FuzzDataHelper {
public: explicit FuzzDataHelper(std::span<const uint8_t> data) : data_(data) {}
// Returns true if n bytes can be read. bool CanReadBytes(size_t n) const { return data_ix_ + n <= data_.size(); }
// Reads and returns data of type T. template <typename T>
requires(std::is_trivial_v<T>)
T Read();
// Reads and returns data of type T. Returns default_value if not enough // fuzzer input remains to read a T. template <typename T>
requires(std::is_trivial_v<T>)
T ReadOrDefaultValue(T default_value) { if (!CanReadBytes(sizeof(T))) { return default_value;
} return Read<T>();
}
// Like ReadOrDefaultValue, but replaces the value 0 with default_value. template <typename T>
requires(std::is_integral_v<T>)
T ReadOrDefaultValueNotZero(T default_value) {
T x = ReadOrDefaultValue(default_value); return x == 0 ? default_value : x;
}
// Returns one of the elements from the provided input array. The selection // is based on the fuzzer input data. If not enough fuzzer data is available, // the method will return the first element in the input array. The reason for // not flagging this as an error is to allow the method to be called from // class constructors, and in constructors we typically do not handle // errors. The code will work anyway, and the fuzzer will likely see that // providing more data will actually make this method return something else. template <typename T, size_t N>
T SelectOneOf(const T (&select_from)[N]) {
static_assert(N <= std::numeric_limits<uint8_t>::max(), ""); // Read an index between 0 and select_from.size() - 1 from the fuzzer data.
uint8_t index = ReadOrDefaultValue<uint8_t>(0) % N; return select_from[index];
}
// Same as `SelectOneOf` but move the selected item from the array. template <typename T, size_t N>
T MoveOneOf(T (&select_from)[N]) {
static_assert(N <= std::numeric_limits<uint8_t>::max(), ""); // Read an index between 0 and select_from.size() - 1 from the fuzzer data.
uint8_t index = ReadOrDefaultValue<uint8_t>(0) % N; return std::move(select_from[index]);
}
// Returns all unused fuzzing bytes. May return an empty view.
std::span<const uint8_t> ReadRemaining() {
std::span<const uint8_t> result = data_.subspan(data_ix_);
data_ix_ = data_.size(); return result;
}
// Returns all unused fuzzing bytes as a string.
absl::string_view ReadString() {
std::span<const uint8_t> raw = ReadRemaining(); return absl::string_view(reinterpret_cast<constchar*>(raw.data()),
raw.size());
}
// If sizeof(T) > BytesLeft then the remaining bytes will be used and the rest // of the object will be zero initialized. template <typename T>
requires(std::is_trivial_v<T>) void CopyTo(T& object) {
std::span<uint8_t, sizeof(T)> object_memory(
reinterpret_cast<uint8_t*>(&object), sizeof(T));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.