Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// A single header library providing an utility class to break up an array of9// bytes. Whenever run on the same input, provides the same output, as long as10// its methods are called in the same order, with the same arguments.11//===----------------------------------------------------------------------===//13#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_14#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_16#include <algorithm>17#include <array>18#include <climits>19#include <cstddef>20#include <cstdint>21#include <cstdlib>22#include <cstring>23#include <initializer_list>24#include <limits>25#include <string>26#include <type_traits>27#include <utility>28#include <vector>30// In addition to the comments below, the API is also briefly documented at31// https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider32class FuzzedDataProvider {33public:34// |data| is an array of length |size| that the FuzzedDataProvider wraps to35// provide more granular access. |data| must outlive the FuzzedDataProvider.36FuzzedDataProvider(const uint8_t *data, size_t size)37: data_ptr_(data), remaining_bytes_(size) {}38~FuzzedDataProvider() = default;40// See the implementation below (after the class definition) for more verbose41// comments for each of the methods.43// Methods returning std::vector of bytes. These are the most popular choice44// when splitting fuzzing input into pieces, as every piece is put into a45// separate buffer (i.e. ASan would catch any under-/overflow) and the memory46// will be released automatically.47template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes);48template <typename T>49std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator = 0);50template <typename T> std::vector<T> ConsumeRemainingBytes();52// Methods returning strings. Use only when you need a std::string or a null53// terminated C-string. Otherwise, prefer the methods returning std::vector.54std::string ConsumeBytesAsString(size_t num_bytes);55std::string ConsumeRandomLengthString(size_t max_length);56std::string ConsumeRandomLengthString();57std::string ConsumeRemainingBytesAsString();59// Methods returning integer values.60template <typename T> T ConsumeIntegral();61template <typename T> T ConsumeIntegralInRange(T min, T max);63// Methods returning floating point values.64template <typename T> T ConsumeFloatingPoint();65template <typename T> T ConsumeFloatingPointInRange(T min, T max);67// 0 <= return value <= 1.68template <typename T> T ConsumeProbability();70bool ConsumeBool();72// Returns a value chosen from the given enum.73template <typename T> T ConsumeEnum();75// Returns a value from the given array.76template <typename T, size_t size> T PickValueInArray(const T (&array)[size]);77template <typename T, size_t size>78T PickValueInArray(const std::array<T, size> &array);79template <typename T> T PickValueInArray(std::initializer_list<const T> list);81// Writes data to the given destination and returns number of bytes written.82size_t ConsumeData(void *destination, size_t num_bytes);84// Reports the remaining bytes available for fuzzed input.85size_t remaining_bytes() { return remaining_bytes_; }87private:88FuzzedDataProvider(const FuzzedDataProvider &) = delete;89FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete;91void CopyAndAdvance(void *destination, size_t num_bytes);93void Advance(size_t num_bytes);95template <typename T>96std::vector<T> ConsumeBytes(size_t size, size_t num_bytes);98template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value);100const uint8_t *data_ptr_;101size_t remaining_bytes_;102};104// Returns a std::vector containing |num_bytes| of input data. If fewer than105// |num_bytes| of data remain, returns a shorter std::vector containing all106// of the data that's left. Can be used with any byte sized type, such as107// char, unsigned char, uint8_t, etc.108template <typename T>109std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {110num_bytes = std::min(num_bytes, remaining_bytes_);111return ConsumeBytes<T>(num_bytes, num_bytes);112}114// Similar to |ConsumeBytes|, but also appends the terminator value at the end115// of the resulting vector. Useful, when a mutable null-terminated C-string is116// needed, for example. But that is a rare case. Better avoid it, if possible,117// and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods.118template <typename T>119std::vector<T> FuzzedDataProvider::ConsumeBytesWithTerminator(size_t num_bytes,120T terminator) {121num_bytes = std::min(num_bytes, remaining_bytes_);122std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes);123result.back() = terminator;124return result;125}127// Returns a std::vector containing all remaining bytes of the input data.128template <typename T>129std::vector<T> FuzzedDataProvider::ConsumeRemainingBytes() {130return ConsumeBytes<T>(remaining_bytes_);131}133// Returns a std::string containing |num_bytes| of input data. Using this and134// |.c_str()| on the resulting string is the best way to get an immutable135// null-terminated C string. If fewer than |num_bytes| of data remain, returns136// a shorter std::string containing all of the data that's left.137inline std::string FuzzedDataProvider::ConsumeBytesAsString(size_t num_bytes) {138static_assert(sizeof(std::string::value_type) == sizeof(uint8_t),139"ConsumeBytesAsString cannot convert the data to a string.");141num_bytes = std::min(num_bytes, remaining_bytes_);142std::string result(143reinterpret_cast<const std::string::value_type *>(data_ptr_), num_bytes);144Advance(num_bytes);145return result;146}148// Returns a std::string of length from 0 to |max_length|. When it runs out of149// input data, returns what remains of the input. Designed to be more stable150// with respect to a fuzzer inserting characters than just picking a random151// length and then consuming that many bytes with |ConsumeBytes|.152inline std::string153FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {154// Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\"155// followed by anything else to the end of the string. As a result of this156// logic, a fuzzer can insert characters into the string, and the string157// will be lengthened to include those new characters, resulting in a more158// stable fuzzer than picking the length of a string independently from159// picking its contents.160std::string result;162// Reserve the anticipated capacity to prevent several reallocations.163result.reserve(std::min(max_length, remaining_bytes_));164for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) {165char next = ConvertUnsignedToSigned<char>(data_ptr_[0]);166Advance(1);167if (next == '\\' && remaining_bytes_ != 0) {168next = ConvertUnsignedToSigned<char>(data_ptr_[0]);169Advance(1);170if (next != '\\')171break;172}173result += next;174}176result.shrink_to_fit();177return result;178}180// Returns a std::string of length from 0 to |remaining_bytes_|.181inline std::string FuzzedDataProvider::ConsumeRandomLengthString() {182return ConsumeRandomLengthString(remaining_bytes_);183}185// Returns a std::string containing all remaining bytes of the input data.186// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string187// object.188inline std::string FuzzedDataProvider::ConsumeRemainingBytesAsString() {189return ConsumeBytesAsString(remaining_bytes_);190}192// Returns a number in the range [Type's min, Type's max]. The value might193// not be uniformly distributed in the given range. If there's no input data194// left, always returns |min|.195template <typename T> T FuzzedDataProvider::ConsumeIntegral() {196return ConsumeIntegralInRange(std::numeric_limits<T>::min(),197std::numeric_limits<T>::max());198}200// Returns a number in the range [min, max] by consuming bytes from the201// input data. The value might not be uniformly distributed in the given202// range. If there's no input data left, always returns |min|. |min| must203// be less than or equal to |max|.204template <typename T>205T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) {206static_assert(std::is_integral_v<T>, "An integral type is required.");207static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type.");209if (min > max)210abort();212// Use the biggest type possible to hold the range and the result.213uint64_t range = static_cast<uint64_t>(max) - static_cast<uint64_t>(min);214uint64_t result = 0;215size_t offset = 0;217while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 &&218remaining_bytes_ != 0) {219// Pull bytes off the end of the seed data. Experimentally, this seems to220// allow the fuzzer to more easily explore the input space. This makes221// sense, since it works by modifying inputs that caused new code to run,222// and this data is often used to encode length of data read by223// |ConsumeBytes|. Separating out read lengths makes it easier modify the224// contents of the data that is actually read.225--remaining_bytes_;226result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_];227offset += CHAR_BIT;228}230// Avoid division by 0, in case |range + 1| results in overflow.231if (range != std::numeric_limits<decltype(range)>::max())232result = result % (range + 1);234return static_cast<T>(static_cast<uint64_t>(min) + result);235}237// Returns a floating point value in the range [Type's lowest, Type's max] by238// consuming bytes from the input data. If there's no input data left, always239// returns approximately 0.240template <typename T> T FuzzedDataProvider::ConsumeFloatingPoint() {241return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest(),242std::numeric_limits<T>::max());243}245// Returns a floating point value in the given range by consuming bytes from246// the input data. If there's no input data left, returns |min|. Note that247// |min| must be less than or equal to |max|.248template <typename T>249T FuzzedDataProvider::ConsumeFloatingPointInRange(T min, T max) {250if (min > max)
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.