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.
251abort();253T range = .0;254T result = min;255constexpr T zero(.0);256if (max > zero && min < zero && max > min + std::numeric_limits<T>::max()) {257// The diff |max - min| would overflow the given floating point type. Use258// the half of the diff as the range and consume a bool to decide whether259// the result is in the first of the second part of the diff.260range = (max / 2.0) - (min / 2.0);261if (ConsumeBool()) {262result += range;263}264} else {265range = max - min;266}268return result + range * ConsumeProbability<T>();269}271// Returns a floating point number in the range [0.0, 1.0]. If there's no272// input data left, always returns 0.273template <typename T> T FuzzedDataProvider::ConsumeProbability() {274static_assert(std::is_floating_point_v<T>,275"A floating point type is required.");277// Use different integral types for different floating point types in order278// to provide better density of the resulting values.279using IntegralType =280typename std::conditional_t<(sizeof(T) <= sizeof(uint32_t)), uint32_t,281uint64_t>;283T result = static_cast<T>(ConsumeIntegral<IntegralType>());284result /= static_cast<T>(std::numeric_limits<IntegralType>::max());285return result;286}288// Reads one byte and returns a bool, or false when no data remains.289inline bool FuzzedDataProvider::ConsumeBool() {290return 1 & ConsumeIntegral<uint8_t>();291}293// Returns an enum value. The enum must start at 0 and be contiguous. It must294// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:295// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };296template <typename T> T FuzzedDataProvider::ConsumeEnum() {297static_assert(std::is_enum_v<T>, "|T| must be an enum type.");298return static_cast<T>(299ConsumeIntegralInRange<uint32_t>(0, static_cast<uint32_t>(T::kMaxValue)));300}302// Returns a copy of the value selected from the given fixed-size |array|.303template <typename T, size_t size>304T FuzzedDataProvider::PickValueInArray(const T (&array)[size]) {305static_assert(size > 0, "The array must be non empty.");306return array[ConsumeIntegralInRange<size_t>(0, size - 1)];307}309template <typename T, size_t size>310T FuzzedDataProvider::PickValueInArray(const std::array<T, size> &array) {311static_assert(size > 0, "The array must be non empty.");312return array[ConsumeIntegralInRange<size_t>(0, size - 1)];313}315template <typename T>316T FuzzedDataProvider::PickValueInArray(std::initializer_list<const T> list) {317if (!list.size())318abort();320return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1));321}323// Writes |num_bytes| of input data to the given destination pointer. If there324// is not enough data left, writes all remaining bytes. Return value is the325// number of bytes written.326// In general, it's better to avoid using this function, but it may be useful327// in cases when it's necessary to fill a certain buffer or object with328// fuzzing data.329inline size_t FuzzedDataProvider::ConsumeData(void *destination,330size_t num_bytes) {331num_bytes = std::min(num_bytes, remaining_bytes_);332CopyAndAdvance(destination, num_bytes);333return num_bytes;334}336// Private methods.337inline void FuzzedDataProvider::CopyAndAdvance(void *destination,338size_t num_bytes) {339std::memcpy(destination, data_ptr_, num_bytes);340Advance(num_bytes);341}343inline void FuzzedDataProvider::Advance(size_t num_bytes) {344if (num_bytes > remaining_bytes_)345abort();347data_ptr_ += num_bytes;348remaining_bytes_ -= num_bytes;349}351template <typename T>352std::vector<T> FuzzedDataProvider::ConsumeBytes(size_t size, size_t num_bytes) {353static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type.");355// The point of using the size-based constructor below is to increase the356// odds of having a vector object with capacity being equal to the length.357// That part is always implementation specific, but at least both libc++ and358// libstdc++ allocate the requested number of bytes in that constructor,359// which seems to be a natural choice for other implementations as well.360// To increase the odds even more, we also call |shrink_to_fit| below.361std::vector<T> result(size);362if (size == 0) {363if (num_bytes != 0)364abort();365return result;366}368CopyAndAdvance(result.data(), num_bytes);370// Even though |shrink_to_fit| is also implementation specific, we expect it371// to provide an additional assurance in case vector's constructor allocated372// a buffer which is larger than the actual amount of data we put inside it.373result.shrink_to_fit();374return result;375}377template <typename TS, typename TU>378TS FuzzedDataProvider::ConvertUnsignedToSigned(TU value) {379static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types.");380static_assert(!std::numeric_limits<TU>::is_signed,381"Source type must be unsigned.");383if constexpr (std::numeric_limits<TS>::is_modulo)384return static_cast<TS>(value);386// Avoid using implementation-defined unsigned to signed conversions.387// To learn more, see https://stackoverflow.com/questions/13150449.388constexpr auto TS_max = static_cast<TU>(std::numeric_limits<TS>::max());389if (value <= TS_max) {390return static_cast<TS>(value);391} else {392constexpr auto TS_min = std::numeric_limits<TS>::min();393return TS_min + static_cast<TS>(value - TS_min);394}395}397#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
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.