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// Copyright (c) 2009-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <test/fuzz/fuzz.h>7#include <netaddress.h>8#include <netbase.h>9#include <test/fuzz/util/check_globals.h>10#include <test/util/coverage.h>11#include <test/util/random.h>12#include <test/util/setup_common.h>13#include <util/check.h>14#include <util/fs.h>15#include <util/sock.h>16#include <util/time.h>18#include <algorithm>19#include <csignal>20#include <cstdint>21#include <cstdio>22#include <cstdlib>23#include <cstring>24#include <exception>25#include <fstream>26#include <functional>27#include <iostream>28#include <map>29#include <memory>30#include <random>31#include <string>32#include <tuple>33#include <utility>34#include <vector>36#if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && defined(__AFL_FUZZ_INIT)37__AFL_FUZZ_INIT();38#endif40/**41* A copy of the command line arguments that start with `--`.42* First `LLVMFuzzerInitialize()` is called, which saves the arguments to `g_args`.43* Later, depending on the fuzz test, `G_TEST_COMMAND_LINE_ARGUMENTS()` may be44* called by `BasicTestingSetup` constructor to fetch those arguments and store45* them in `BasicTestingSetup::m_node::args`.46*/47static std::vector<const char*> g_args;49static void SetArgs(int argc, char** argv) {50for (int i = 1; i < argc; ++i) {51// Only take into account arguments that start with `--`. The others are for the fuzz engine:52// `fuzz -runs=1 fuzz_corpora/address_deserialize --checkaddrman=5`53if (strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == '-') {54g_args.push_back(argv[i]);55}56}57}59const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS = []() {60return g_args;61};63struct FuzzTarget {64const TypeTestOneInput test_one_input;65const FuzzTargetOptions opts;66};68auto& FuzzTargets()69{70static std::map<std::string_view, FuzzTarget> g_fuzz_targets;71return g_fuzz_targets;72}74void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts)75{76const auto [it, ins]{FuzzTargets().try_emplace(name, std::move(target), std::move(opts))};77Assert(ins);78}80static std::string_view g_fuzz_target;81static const TypeTestOneInput* g_test_one_input{nullptr};83static void test_one_input(FuzzBufferType buffer)84{85CheckGlobals check{};86(*Assert(g_test_one_input))(buffer);87}89const std::function<std::string()> G_TEST_GET_FULL_NAME{[]{90return std::string{g_fuzz_target};91}};93static void initialize()94{95CheckGlobals check{};96// By default, make the RNG deterministic with a fixed seed. This will affect all97// randomness during the fuzz test, except:98// - GetStrongRandBytes(), which is used for the creation of private key material.99// - Randomness obtained before this call in g_rng_temp_path_init100SeedRandomStateForTest(SeedRand::ZEROS);102// Set time to the genesis block timestamp for deterministic initialization.103SetMockTime(1231006505s);105// Terminate immediately if a fuzzing harness ever tries to create a socket.106// Individual tests can override this by pointing CreateSock to a mocked alternative.107CreateSock = [](int, int, int) -> std::unique_ptr<Sock> { std::terminate(); };109// Terminate immediately if a fuzzing harness ever tries to perform a DNS lookup.110g_dns_lookup = [](const std::string& name, bool allow_lookup) {111if (allow_lookup) {112std::terminate();113}114return WrappedGetAddrInfo(name, false);115};117bool should_exit{false};118if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) {119for (const auto& [name, t] : FuzzTargets()) {120if (t.opts.hidden) continue;121std::cout << name << std::endl;122}123should_exit = true;124}125if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) {126std::cout << "Writing all fuzz target names to '" << out_path << "'." << std::endl;127std::ofstream out_stream{out_path, std::ios::binary};128for (const auto& [name, t] : FuzzTargets()) {129if (t.opts.hidden) continue;130out_stream << name << std::endl;131}132should_exit = true;133}134if (should_exit) {135std::exit(EXIT_SUCCESS);136}137if (const auto* env_fuzz{std::getenv("FUZZ")}) {138// To allow for easier fuzz executable binary modification,139static std::string g_copy{env_fuzz}; // create copy to avoid compiler optimizations, and140g_fuzz_target = g_copy.c_str(); // strip string after the first null-char.141} else {142std::cerr << "Must select fuzz target with the FUZZ env var." << std::endl;143std::cerr << "Hint: Set the PRINT_ALL_FUZZ_TARGETS_AND_ABORT=1 env var to see all compiled targets." << std::endl;144std::exit(EXIT_FAILURE);145}146const auto it = FuzzTargets().find(g_fuzz_target);147if (it == FuzzTargets().end()) {148std::cerr << "No fuzz target compiled for " << g_fuzz_target << "." << std::endl;149std::exit(EXIT_FAILURE);150}151if constexpr (!G_FUZZING_BUILD && !G_ABORT_ON_FAILED_ASSUME) {152std::cerr << "Must compile with -DBUILD_FOR_FUZZING=ON or in Debug mode to execute a fuzz target." << std::endl;153std::exit(EXIT_FAILURE);154}155if (!EnableFuzzDeterminism()) {156if (std::getenv("FUZZ_NONDETERMINISM")) {157std::cerr << "Warning: FUZZ_NONDETERMINISM env var set, results may be inconsistent with fuzz build" << std::endl;158} else {159g_enable_dynamic_fuzz_determinism = true;160assert(EnableFuzzDeterminism());161}162}163Assert(!g_test_one_input);164g_test_one_input = &it->second.test_one_input;165it->second.opts.init();167ResetCoverageCounters();168}170#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)171static bool read_stdin(std::vector<uint8_t>& data)172{173std::istream::char_type buffer[1024];174std::streamsize length;175while ((std::cin.read(buffer, 1024), length = std::cin.gcount()) > 0) {176data.insert(data.end(), buffer, buffer + length);177}178return length == 0;179}180#endif182#if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && !defined(__AFL_LOOP)183static bool read_file(fs::path p, std::vector<uint8_t>& data)184{185uint8_t buffer[1024];186FILE* f = fsbridge::fopen(p, "rb");187if (f == nullptr) return false;188do {189const size_t length = fread(buffer, sizeof(uint8_t), sizeof(buffer), f);190if (ferror(f)) return false;191data.insert(data.end(), buffer, buffer + length);192} while (!feof(f));193fclose(f);194return true;195}196#endif198#if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && !defined(__AFL_LOOP)199static fs::path g_input_path;200void signal_handler(int signal)201{202if (signal == SIGABRT) {203std::cerr << "Error processing input " << g_input_path << std::endl;204} else {205std::cerr << "Unexpected signal " << signal << " received\n";206}207std::_Exit(EXIT_FAILURE);208}209#endif211// This function is used by libFuzzer212extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)213{214test_one_input({data, size});215return 0;216}218// This function is used by libFuzzer219extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)220{221SetArgs(*argc, *argv);222initialize();223return 0;224}226#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)227int main(int argc, char** argv)228{229initialize();230#ifdef __AFL_LOOP231// Enable AFL persistent mode. Requires compilation using afl-clang-fast++.232// See fuzzing.md for details.233const uint8_t* buffer = __AFL_FUZZ_TESTCASE_BUF;234while (__AFL_LOOP(100'000)) {235size_t buffer_len = __AFL_FUZZ_TESTCASE_LEN;236test_one_input({buffer, buffer_len});237}238#else239std::vector<uint8_t> buffer;240if (argc <= 1) {241if (!read_stdin(buffer)) {242return 0;243}244test_one_input(buffer);245return 0;246}247std::signal(SIGABRT, signal_handler);248const auto start_time{Now<SteadySeconds>()};249int tested = 0;250for (int i = 1; i < argc; ++i) {
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.