//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // A single header library providing an utility class to break up an array of // bytes. Whenever run on the same input, provides the same output, as long as // its methods are called in the same order, with the same arguments. //===----------------------------------------------------------------------===// #ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ #define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ #include <algorithm> #include <array> #include <climits> #include <cstddef> #include <cstdint> #include <cstring> #include <initializer_list> #include <limits> #include <string> #include <type_traits> #include <utility> #include <vector> // In addition to the comments below, the API is also briefly documented at // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider class FuzzedDataProvider { … }; // Returns a std::vector containing |num_bytes| of input data. If fewer than // |num_bytes| of data remain, returns a shorter std::vector containing all // of the data that's left. Can be used with any byte sized type, such as // char, unsigned char, uint8_t, etc. template <typename T> std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) { … } // Similar to |ConsumeBytes|, but also appends the terminator value at the end // of the resulting vector. Useful, when a mutable null-terminated C-string is // needed, for example. But that is a rare case. Better avoid it, if possible, // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods. template <typename T> std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes, T terminator) { … } // Returns a std::vector containing all remaining bytes of the input data. template <typename T> std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() { … } // Returns a std::string containing |num_bytes| of input data. Using this and // |.c_str()| on the resulting string is the best way to get an immutable // null-terminated C string. If fewer than |num_bytes| of data remain, returns // a shorter std::string containing all of the data that's left. inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) { … } // Returns a std::string of length from 0 to |max_length|. When it runs out of // input data, returns what remains of the input. Designed to be more stable // with respect to a fuzzer inserting characters than just picking a random // length and then consuming that many bytes with |ConsumeBytes|. inline std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) { … } // Returns a std::string of length from 0 to |remaining_bytes_|. inline std::string FuzzedDataProvider::ConsumeRandomLengthString() { … } // Returns a std::string containing all remaining bytes of the input data. // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string // object. inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() { … } // Returns a number in the range [Type's min, Type's max]. The value might // not be uniformly distributed in the given range. If there's no input data // left, always returns |min|. template <typename T> T FuzzedDataProvider::ConsumeIntegral() { … } // Returns a number in the range [min, max] by consuming bytes from the // input data. The value might not be uniformly distributed in the given // range. If there's no input data left, always returns |min|. |min| must // be less than or equal to |max|. template <typename T> T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) { … } // Returns a floating point value in the range [Type's lowest, Type's max] by // consuming bytes from the input data. If there's no input data left, always // returns approximately 0. template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() { … } // Returns a floating point value in the given range by consuming bytes from // the input data. If there's no input data left, returns |min|. Note that // |min| must be less than or equal to |max|. template <typename T> T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) { … } // Returns a floating point number in the range [0.0, 1.0]. If there's no // input data left, always returns 0. template <typename T> T FuzzedDataProvider::ConsumeProbability() { … } // Reads one byte and returns a bool, or false when no data remains. inline bool FuzzedDataProvider::ConsumeBool() { … } // Returns an enum value. The enum must start at 0 and be contiguous. It must // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as: // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue }; template <typename T> T FuzzedDataProvider::ConsumeEnum() { … } // Returns a copy of the value selected from the given fixed-size |array|. template <typename T, size_t size> T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) { … } template <typename T, size_t size> T FuzzedDataProvider::PickValueInArray(const std::array<T, size> &array) { … } template <typename T> T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) { … } // Writes |num_bytes| of input data to the given destination pointer. If there // is not enough data left, writes all remaining bytes. Return value is the // number of bytes written. // In general, it's better to avoid using this function, but it may be useful // in cases when it's necessary to fill a certain buffer or object with // fuzzing data. inline size_t FuzzedDataProvider::ConsumeData(void *destination, size_t num_bytes) { … } // Private methods. inline void FuzzedDataProvider::CopyAndAdvance(void *destination, size_t num_bytes) { … } inline void FuzzedDataProvider::Advance(size_t num_bytes) { … } template <typename T> std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) { … } template <typename TS, typename TU> TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) { … } #endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_