diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95e509d0e086..424e47e43665 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,15 +75,6 @@ jobs: container-path: ${{ needs.container.outputs.path }} depends-key: ${{ needs.depends-linux64.outputs.key }} - src-linux64_cxx20: - name: linux64_cxx20-build - uses: ./.github/workflows/build-src.yml - needs: [container, depends-linux64] - with: - build-target: linux64_cxx20 - container-path: ${{ needs.container.outputs.path }} - depends-key: ${{ needs.depends-linux64.outputs.key }} - src-linux64_fuzz: name: linux64_fuzz-build uses: ./.github/workflows/build-src.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6cbc4440cf15..cd25b42f9fdb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -235,15 +235,6 @@ linux64-build: variables: BUILD_TARGET: linux64 -linux64_cxx20-build: - extends: - - .build-template - - .skip-in-fast-mode-template - needs: - - x86_64-pc-linux-gnu - variables: - BUILD_TARGET: linux64_cxx20 - linux64_sqlite-build: extends: - .build-template diff --git a/CMakeLists.txt b/CMakeLists.txt index 863806b85754..1af0d14fa95d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.7) project(dash) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) include_directories( src diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 index e0fb05a0e43d..51a35054d08c 100644 --- a/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4 @@ -10,14 +10,13 @@ # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard), -# '14' (for the C++14 standard), '17' (for the C++17 standard) or -# '20' (for the C++20 standard) +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. +# preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is @@ -36,25 +35,24 @@ # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 11 +#serial 14 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). -dnl Modifications: -dnl Add support for C++20, with no new tests - AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], - [$1], [20], [ax_cxx_compile_alternatives="20 2a"], + [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -67,6 +65,16 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl AC_LANG_PUSH([C++])dnl ac_success=no + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do @@ -145,7 +153,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) - dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], @@ -153,25 +160,21 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) +dnl Test body for checking C++17 support + m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) +dnl Test body for checking C++20 support -dnl Test body for checking C++20 support: R modification m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], -#ifndef __cplusplus -#error "This is not a C++ compiler" -dnl value from 2020-01-14 draft, clang 11 has 202002L -#elif __cplusplus < 201703L -#error "This is not a C++20 compiler" -#else _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 -#endif + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 ) @@ -272,7 +275,7 @@ namespace cxx11 } int - test(const int c, volatile int v) // 'volatile is deprecated in C++20' + test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); @@ -970,3 +973,33 @@ namespace cxx17 #endif // __cplusplus < 201703L ]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L + +]]) diff --git a/ci/dash/matrix.sh b/ci/dash/matrix.sh index 9822a727890b..2ffe70623311 100755 --- a/ci/dash/matrix.sh +++ b/ci/dash/matrix.sh @@ -22,8 +22,6 @@ elif [ "$BUILD_TARGET" = "linux64" ]; then source ./ci/test/00_setup_env_native_qt5.sh elif [ "$BUILD_TARGET" = "linux64_asan" ]; then source ./ci/test/00_setup_env_native_asan.sh -elif [ "$BUILD_TARGET" = "linux64_cxx20" ]; then - source ./ci/test/00_setup_env_native_cxx20.sh elif [ "$BUILD_TARGET" = "linux64_fuzz" ]; then source ./ci/test/00_setup_env_native_fuzz.sh elif [ "$BUILD_TARGET" = "linux64_multiprocess" ]; then diff --git a/ci/test/00_setup_env_native_cxx20.sh b/ci/test/00_setup_env_native_cxx20.sh deleted file mode 100755 index 422da6b4ca40..000000000000 --- a/ci/test/00_setup_env_native_cxx20.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2019 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -export LC_ALL=C.UTF-8 - -export CONTAINER_NAME=ci_native_cxx20 -export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev" -export DEP_OPTS="NO_UPNP=1 DEBUG=1" -export CPPFLAGS="-DDEBUG_LOCKORDER -DARENA_DEBUG" -export PYZMQ=true -export RUN_FUNCTIONAL_TESTS=false -export GOAL="install" -export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --enable-crash-hooks --enable-c++20" - diff --git a/ci/test/00_setup_env_native_fuzz.sh b/ci/test/00_setup_env_native_fuzz.sh index d1bb30d1991c..485ca639b2ee 100755 --- a/ci/test/00_setup_env_native_fuzz.sh +++ b/ci/test/00_setup_env_native_fuzz.sh @@ -10,7 +10,7 @@ export CONTAINER_NAME=ci_native_fuzz export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev" export DEP_OPTS="NO_UPNP=1 DEBUG=1" export CPPFLAGS="-DDEBUG_LOCKORDER -DARENA_DEBUG" -export CXXFLAGS="-Werror -Wno-unused-command-line-argument -Wno-unused-value -Wno-deprecated-builtins" +export CXXFLAGS="-Werror -Wno-unused-command-line-argument -Wno-unused-value -Wno-deprecated-builtins -Wno-deprecated-volatile" export PYZMQ=true export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index d6f74f0f872a..393e7a7d2891 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -85,7 +85,11 @@ if [ "$RUN_FUZZ_TESTS" = "true" ] || [ "$RUN_UNIT_TESTS" = "true" ] || [ "$RUN_U if [ ! -d "${DIR_QA_ASSETS}" ]; then DOCKER_EXEC git clone --depth=1 https://github.com/bitcoin-core/qa-assets "${DIR_QA_ASSETS}" fi - + ( + DOCKER_EXEC cd "${DIR_QA_ASSETS}" + DOCKER_EXEC echo "Using qa-assets repo from commit ..." + DOCKER_EXEC git log -1 + ) export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_seed_corpus/ fi diff --git a/configure.ac b/configure.ac index 2b84eb19235d..d92044edfa6a 100644 --- a/configure.ac +++ b/configure.ac @@ -77,18 +77,8 @@ case $host in ;; esac -AC_ARG_ENABLE([c++20], - [AS_HELP_STRING([--enable-c++20], - [enable compilation in c++20 mode (disabled by default)])], - [use_cxx20=$enableval], - [use_cxx20=no]) - -dnl Require C++17 compiler (no GNU extensions) -if test "$use_cxx20" = "no"; then - AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) -else - AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) -fi +dnl Require C++20 compiler (no GNU extensions) +AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures dnl that we get the same -std flags for both. diff --git a/depends/Makefile b/depends/Makefile index 8583521f3f75..e464f57697b0 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -46,7 +46,7 @@ LTO ?= FALLBACK_DOWNLOAD_PATH ?= http://dash-depends-sources.s3-website-us-west-2.amazonaws.com C_STANDARD ?= c11 -CXX_STANDARD ?= c++17 +CXX_STANDARD ?= c++20 BUILD = $(shell ./config.guess) HOST ?= $(BUILD) diff --git a/depends/README.md b/depends/README.md index 59fb62b24d77..b0c58b5960de 100644 --- a/depends/README.md +++ b/depends/README.md @@ -108,7 +108,7 @@ The following can be set when running make: `make FOO=bar` - `SDK_PATH`: Path where SDKs can be found (used by macOS) - `FALLBACK_DOWNLOAD_PATH`: If a source file can't be fetched, try here before giving up - `C_STANDARD`: Set the C standard version used. Defaults to `c11`. -- `CXX_STANDARD`: Set the C++ standard version used. Defaults to `c++17`. +- `CXX_STANDARD`: Set the C++ standard version used. Defaults to `c++20`. - `NO_QT`: Don't download/build/cache Qt and its dependencies - `NO_QR`: Don't download/build/cache packages needed for enabling qrencode - `NO_ZMQ`: Don't download/build/cache packages needed for enabling ZeroMQ diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index cc8094cc332d..18c01e7cf063 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -43,7 +43,7 @@ $(package)_config_opts_release += -silent $(package)_config_opts_debug = -debug $(package)_config_opts_debug += -optimized-tools $(package)_config_opts += -bindir $(build_prefix)/bin -$(package)_config_opts += -c++std c++17 +$(package)_config_opts += -c++std c++2a $(package)_config_opts += -confirm-license $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -no-compile-examples diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 7d1241675fa0..8f8924fad091 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -556,7 +556,7 @@ class NetinfoRequestHandler : public BaseRequestHandler peer.is_outbound ? "out" : "in", ConnectionTypeForNetinfo(peer.conn_type), peer.network, - peer.transport_protocol_type.rfind('v', 0) == 0 ? peer.transport_protocol_type[1] : ' ', + peer.transport_protocol_type.starts_with('v') == 0 ? peer.transport_protocol_type[1] : ' ', PingTimeToString(peer.min_ping), PingTimeToString(peer.ping), peer.last_send ? ToString(time_now - peer.last_send) : "", diff --git a/src/compat/assumptions.h b/src/compat/assumptions.h index 0298f78b96de..7839a5d1049a 100644 --- a/src/compat/assumptions.h +++ b/src/compat/assumptions.h @@ -11,20 +11,6 @@ #include #include -// Assumption: We assume that the macro NDEBUG is not defined. -// Example(s): We use assert(...) extensively with the assumption of it never -// being a noop at runtime. -#if defined(NDEBUG) -# error "Dash Core cannot be compiled without assertions." -#endif - -// Assumption: We assume a C++17 (ISO/IEC 14882:2017) compiler (minimum requirement). -// Example(s): We assume the presence of C++17 features everywhere :-) -// ISO Standard C++17 [cpp.predefined]p1: -// "The name __cplusplus is defined to the value 201703L when compiling a C++ -// translation unit." -static_assert(__cplusplus >= 201703L, "C++17 standard assumed"); - // Assumption: We assume the floating-point types to fulfill the requirements of // IEC 559 (IEEE 754) standard. // Example(s): Floating-point division by zero in ConnectBlock, CreateTransaction diff --git a/src/fs.h b/src/fs.h index c37e4a6a5225..d50a65c8a08d 100644 --- a/src/fs.h +++ b/src/fs.h @@ -8,7 +8,7 @@ #include #include -#include +#include // IWYU pragma: export #include #include #include diff --git a/src/net.cpp b/src/net.cpp index 28df16d2e661..8ebe74db7110 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1119,16 +1119,9 @@ constexpr std::array V2ShortIDs() { static_assert(std::size(V2_DASH_IDS) <= 128); std::array ret{}; - for (size_t idx{0}; idx < std::size(ret); idx++) { - if (idx < 128 && idx < std::size(V2_BITCOIN_IDS)) { - ret[idx] = V2_BITCOIN_IDS[idx]; - } else if (idx >= 128 && idx - 128 < std::size(V2_DASH_IDS)) { - ret[idx] = V2_DASH_IDS[idx - 128]; - } else { - ret[idx] = ""; - } - } - + std::fill(ret.begin(), ret.end(), ""); + std::copy(V2_BITCOIN_IDS.begin(), V2_BITCOIN_IDS.end(), ret.begin()); + std::copy(V2_DASH_IDS.begin(), V2_DASH_IDS.end(), ret.begin() + 128); return ret; } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4616a08c7b9f..05ee2b03eb51 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -35,7 +35,7 @@ #include #include #include -#include // For NDEBUG compile time check +#include #include #include #include diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index 9baf26a0b2c0..84091a32b7a1 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -45,7 +45,7 @@ void initialize_addrman() return NetGroupManager(asmap); } -FUZZ_TARGET_INIT(data_stream_addr_man, initialize_addrman) +FUZZ_TARGET(data_stream_addr_man, .init = initialize_addrman) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider); @@ -232,7 +232,7 @@ class AddrManDeterministic : public AddrMan } }; -FUZZ_TARGET_INIT(addrman, initialize_addrman) +FUZZ_TARGET(addrman, .init = initialize_addrman) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); SetMockTime(ConsumeTime(fuzzed_data_provider)); @@ -313,7 +313,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman) } // Check that serialize followed by unserialize produces the same addrman. -FUZZ_TARGET_INIT(addrman_serdeser, initialize_addrman) +FUZZ_TARGET(addrman_serdeser, .init = initialize_addrman) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); SetMockTime(ConsumeTime(fuzzed_data_provider)); diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index 7c8ebfff0602..d252c44ece70 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -40,7 +40,7 @@ static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs) lhs.nBanUntil == rhs.nBanUntil; } -FUZZ_TARGET_INIT(banman, initialize_banman) +FUZZ_TARGET(banman, .init = initialize_banman) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; SetMockTime(ConsumeTime(fuzzed_data_provider)); diff --git a/src/test/fuzz/bip324.cpp b/src/test/fuzz/bip324.cpp index 7954ea4ad154..56ee0f58a92d 100644 --- a/src/test/fuzz/bip324.cpp +++ b/src/test/fuzz/bip324.cpp @@ -19,7 +19,7 @@ void initialize_bip324() SelectParams(CBaseChainParams::MAIN); } -FUZZ_TARGET_INIT(bip324_cipher_roundtrip, initialize_bip324) +FUZZ_TARGET(bip324_cipher_roundtrip, .init = initialize_bip324) { // Test that BIP324Cipher's encryption and decryption agree. diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp index a0d4fc7306f3..2508f4f88df8 100644 --- a/src/test/fuzz/block.cpp +++ b/src/test/fuzz/block.cpp @@ -22,7 +22,7 @@ void initialize_block() SelectParams(CBaseChainParams::REGTEST); } -FUZZ_TARGET_INIT(block, initialize_block) +FUZZ_TARGET(block, .init = initialize_block) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); CBlock block; diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 86be7adf94c3..2e56d331a0f5 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -44,7 +44,7 @@ void initialize_coins_view() g_setup = testing_setup.get(); } -FUZZ_TARGET_INIT(coins_view, initialize_coins_view) +FUZZ_TARGET(coins_view, .init = initialize_coins_view) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; CCoinsView backend_coins_view; diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index 6fa704323f47..978a54e7a59b 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -29,7 +29,7 @@ void initialize_connman() g_setup = testing_setup.get(); } -FUZZ_TARGET_INIT(connman, initialize_connman) +FUZZ_TARGET(connman, .init = initialize_connman) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; SetMockTime(ConsumeTime(fuzzed_data_provider)); diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index bd8ec80f6576..bf8bb04240f4 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -15,7 +15,7 @@ void initialize_descriptor_parse() SelectParams(CBaseChainParams::MAIN); } -FUZZ_TARGET_INIT(descriptor_parse, initialize_descriptor_parse) +FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse) { const std::string descriptor(buffer.begin(), buffer.end()); FlatSigningProvider signing_provider; diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index bcd7d4d87c05..a9967ecbe323 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -46,7 +46,7 @@ void initialize_deserialize() } #define FUZZ_TARGET_DESERIALIZE(name, code) \ - FUZZ_TARGET_INIT(name, initialize_deserialize) \ + FUZZ_TARGET(name, .init = initialize_deserialize) \ { \ try { \ code \ diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index ee91b15ed006..9b224be284c1 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -14,12 +14,17 @@ #include #include +#include +#include +#include #include #include #include +#include #include #include #include +#include #include #if defined(PROVIDE_FUZZ_MAIN_FUNCTION) && defined(__AFL_FUZZ_INIT) @@ -51,20 +56,25 @@ const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS = return g_args; }; -std::map>& FuzzTargets() +struct FuzzTarget { + const TypeTestOneInput test_one_input; + const FuzzTargetOptions opts; +}; + +auto& FuzzTargets() { - static std::map> g_fuzz_targets; + static std::map g_fuzz_targets; return g_fuzz_targets; } -void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden) +void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts) { - const auto it_ins = FuzzTargets().try_emplace(name, std::move(target), std::move(init), hidden); + const auto it_ins{FuzzTargets().try_emplace(name, FuzzTarget /* temporary can be dropped in C++20 */ {std::move(target), std::move(opts)})}; Assert(it_ins.second); } static std::string_view g_fuzz_target; -static TypeTestOneInput* g_test_one_input{nullptr}; +static const TypeTestOneInput* g_test_one_input{nullptr}; void initialize() { @@ -79,33 +89,43 @@ void initialize() return WrappedGetAddrInfo(name, false); }; - bool should_abort{false}; + bool should_exit{false}; if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) { - for (const auto& t : FuzzTargets()) { - if (std::get<2>(t.second)) continue; - std::cout << t.first << std::endl; + for (const auto& [name, t] : FuzzTargets()) { + if (t.opts.hidden) continue; + std::cout << name << std::endl; } - should_abort = true; + should_exit = true; } if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) { std::cout << "Writing all fuzz target names to '" << out_path << "'." << std::endl; std::ofstream out_stream{out_path, std::ios::binary}; - for (const auto& t : FuzzTargets()) { - if (std::get<2>(t.second)) continue; - out_stream << t.first << std::endl; + for (const auto& [name, t] : FuzzTargets()) { + if (t.opts.hidden) continue; + out_stream << name << std::endl; } - should_abort = true; + should_exit = true; + } + if (should_exit) { + std::exit(EXIT_SUCCESS); + } + if (const auto* env_fuzz{std::getenv("FUZZ")}) { + // To allow for easier fuzz executable binary modification, + static std::string g_copy{env_fuzz}; // create copy to avoid compiler optimizations, and + g_fuzz_target = g_copy.c_str(); // strip string after the first null-char. + } else { + std::cerr << "Must select fuzz target with the FUZZ env var." << std::endl; + std::cerr << "Hint: Set the PRINT_ALL_FUZZ_TARGETS_AND_ABORT=1 env var to see all compiled targets." << std::endl; + std::exit(EXIT_FAILURE); } - Assert(!should_abort); - g_fuzz_target = Assert(std::getenv("FUZZ")); const auto it = FuzzTargets().find(g_fuzz_target); if (it == FuzzTargets().end()) { - std::cerr << "No fuzzer for " << g_fuzz_target << "." << std::endl; + std::cerr << "No fuzz target compiled for " << g_fuzz_target << "." << std::endl; std::exit(EXIT_FAILURE); } Assert(!g_test_one_input); - g_test_one_input = &std::get<0>(it->second); - std::get<1>(it->second)(); + g_test_one_input = &it->second.test_one_input; + it->second.opts.init(); } #if defined(PROVIDE_FUZZ_MAIN_FUNCTION) diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index 88f12ef9b1c9..bc1805a05053 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -21,25 +21,21 @@ using FuzzBufferType = Span; using TypeTestOneInput = std::function; -using TypeInitialize = std::function; -using TypeHidden = bool; +struct FuzzTargetOptions { + std::function init{[] {}}; + bool hidden{false}; +}; -void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden); +void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts); -inline void FuzzFrameworkEmptyInitFun() {} +#define FUZZ_TARGET(...) DETAIL_FUZZ(__VA_ARGS__) -#define FUZZ_TARGET(name) \ - FUZZ_TARGET_INIT(name, FuzzFrameworkEmptyInitFun) - -#define FUZZ_TARGET_INIT(name, init_fun) \ - FUZZ_TARGET_INIT_HIDDEN(name, init_fun, false) - -#define FUZZ_TARGET_INIT_HIDDEN(name, init_fun, hidden) \ +#define DETAIL_FUZZ(name, ...) \ void name##_fuzz_target(FuzzBufferType); \ struct name##_Before_Main { \ name##_Before_Main() \ { \ - FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, init_fun, hidden); \ + FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, {__VA_ARGS__}); \ } \ } const static g_##name##_before_main; \ void name##_fuzz_target(FuzzBufferType buffer) diff --git a/src/test/fuzz/i2p.cpp b/src/test/fuzz/i2p.cpp index fb6d23aca5a3..26c525806210 100644 --- a/src/test/fuzz/i2p.cpp +++ b/src/test/fuzz/i2p.cpp @@ -17,7 +17,7 @@ void initialize_i2p() static const auto testing_setup = MakeNoLogFileContext<>(); } -FUZZ_TARGET_INIT(i2p, initialize_i2p) +FUZZ_TARGET(i2p, .init = initialize_i2p) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp index 5ab3810578da..1fe2ec62838d 100644 --- a/src/test/fuzz/integer.cpp +++ b/src/test/fuzz/integer.cpp @@ -47,7 +47,7 @@ void initialize_integer() SelectParams(CBaseChainParams::REGTEST); } -FUZZ_TARGET_INIT(integer, initialize_integer) +FUZZ_TARGET(integer, .init = initialize_integer) { if (buffer.size() < sizeof(uint256) + sizeof(uint160)) { return; diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp index 466308db69d4..59be9ba6bb01 100644 --- a/src/test/fuzz/key.cpp +++ b/src/test/fuzz/key.cpp @@ -33,7 +33,7 @@ void initialize_key() SelectParams(CBaseChainParams::REGTEST); } -FUZZ_TARGET_INIT(key, initialize_key) +FUZZ_TARGET(key, .init = initialize_key) { const CKey key = [&] { CKey k; @@ -261,7 +261,7 @@ FUZZ_TARGET_INIT(key, initialize_key) } } -FUZZ_TARGET_INIT(ellswift_roundtrip, initialize_key) +FUZZ_TARGET(ellswift_roundtrip, .init = initialize_key) { FuzzedDataProvider fdp{buffer.data(), buffer.size()}; @@ -280,7 +280,7 @@ FUZZ_TARGET_INIT(ellswift_roundtrip, initialize_key) assert(decoded_pubkey.Verify(hash, sig)); } -FUZZ_TARGET_INIT(bip324_ecdh, initialize_key) +FUZZ_TARGET(bip324_ecdh, .init = initialize_key) { FuzzedDataProvider fdp{buffer.data(), buffer.size()}; diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp index 30f4160c4fde..60f49bbe639a 100644 --- a/src/test/fuzz/key_io.cpp +++ b/src/test/fuzz/key_io.cpp @@ -19,7 +19,7 @@ void initialize_key_io() SelectParams(CBaseChainParams::MAIN); } -FUZZ_TARGET_INIT(key_io, initialize_key_io) +FUZZ_TARGET(key_io, .init = initialize_key_io) { const std::string random_string(buffer.begin(), buffer.end()); diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp index 16b916dc7004..a2f8694ee618 100644 --- a/src/test/fuzz/load_external_block_file.cpp +++ b/src/test/fuzz/load_external_block_file.cpp @@ -23,7 +23,7 @@ void initialize_load_external_block_file() g_setup = testing_setup.get(); } -FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file) +FUZZ_TARGET(load_external_block_file, .init = initialize_load_external_block_file) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider); diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp index 1b0696929b1a..acbe5eb0749e 100644 --- a/src/test/fuzz/message.cpp +++ b/src/test/fuzz/message.cpp @@ -22,7 +22,7 @@ void initialize_message() SelectParams(CBaseChainParams::REGTEST); } -FUZZ_TARGET_INIT(message, initialize_message) +FUZZ_TARGET(message, .init = initialize_message) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const std::string random_message = fuzzed_data_provider.ConsumeRandomLengthString(1024); diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 91face354d24..e9de2b56ac7b 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -40,7 +40,7 @@ void initialize_net() // From src/test/fuzz/addrman.cpp extern NetGroupManager ConsumeNetGroupManager(FuzzedDataProvider& fuzzed_data_provider) noexcept; -FUZZ_TARGET_INIT(net, initialize_net) +FUZZ_TARGET(net, .init = initialize_net) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); diff --git a/src/test/fuzz/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp index f5f8486e5f3f..034d93d1cca0 100644 --- a/src/test/fuzz/p2p_transport_serialization.cpp +++ b/src/test/fuzz/p2p_transport_serialization.cpp @@ -28,7 +28,7 @@ void initialize_p2p_transport_serialization() std::sort(g_all_messages.begin(), g_all_messages.end()); } -FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serialization) +FUZZ_TARGET(p2p_transport_serialization, .init = initialize_p2p_transport_serialization) { // Construct transports for both sides, with dummy NodeIds. V1Transport recv_transport{NodeId{0}, SER_NETWORK, INIT_PROTO_VERSION}; @@ -370,7 +370,7 @@ std::unique_ptr MakeV2Transport(NodeId nodeid, bool initiator, RNG& r } // namespace -FUZZ_TARGET_INIT(p2p_transport_bidirectional, initialize_p2p_transport_serialization) +FUZZ_TARGET(p2p_transport_bidirectional, .init = initialize_p2p_transport_serialization) { // Test with two V1 transports talking to each other. FuzzedDataProvider provider{buffer.data(), buffer.size()}; @@ -381,7 +381,7 @@ FUZZ_TARGET_INIT(p2p_transport_bidirectional, initialize_p2p_transport_serializa SimulationTest(*t1, *t2, rng, provider); } -FUZZ_TARGET_INIT(p2p_transport_bidirectional_v2, initialize_p2p_transport_serialization) +FUZZ_TARGET(p2p_transport_bidirectional_v2, .init = initialize_p2p_transport_serialization) { // Test with two V2 transports talking to each other. FuzzedDataProvider provider{buffer.data(), buffer.size()}; @@ -392,7 +392,7 @@ FUZZ_TARGET_INIT(p2p_transport_bidirectional_v2, initialize_p2p_transport_serial SimulationTest(*t1, *t2, rng, provider); } -FUZZ_TARGET_INIT(p2p_transport_bidirectional_v1v2, initialize_p2p_transport_serialization) +FUZZ_TARGET(p2p_transport_bidirectional_v1v2, .init = initialize_p2p_transport_serialization) { // Test with a V1 initiator talking to a V2 responder. FuzzedDataProvider provider{buffer.data(), buffer.size()}; diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp index cc827695926f..85ffe78cf470 100644 --- a/src/test/fuzz/parse_univalue.cpp +++ b/src/test/fuzz/parse_univalue.cpp @@ -18,7 +18,7 @@ void initialize_parse_univalue() SelectParams(CBaseChainParams::REGTEST); } -FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue) +FUZZ_TARGET(parse_univalue, .init = initialize_parse_univalue) { const std::string random_string(buffer.begin(), buffer.end()); bool valid = true; diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp index f03a0e4faf5d..2426733487cd 100644 --- a/src/test/fuzz/policy_estimator.cpp +++ b/src/test/fuzz/policy_estimator.cpp @@ -20,7 +20,7 @@ void initialize_policy_estimator() static const auto testing_setup = MakeNoLogFileContext<>(); } -FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator) +FUZZ_TARGET(policy_estimator, .init = initialize_policy_estimator) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); CBlockPolicyEstimator block_policy_estimator; diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp index 3fe9a6fafe60..8de00981e1c6 100644 --- a/src/test/fuzz/policy_estimator_io.cpp +++ b/src/test/fuzz/policy_estimator_io.cpp @@ -16,7 +16,7 @@ void initialize_policy_estimator_io() static const auto testing_setup = MakeNoLogFileContext<>(); } -FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io) +FUZZ_TARGET(policy_estimator_io, .init = initialize_policy_estimator_io) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider); diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index 3d29ad519787..85ed1cadc251 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -21,7 +21,7 @@ void initialize_pow() SelectParams(CBaseChainParams::MAIN); } -FUZZ_TARGET_INIT(pow, initialize_pow) +FUZZ_TARGET(pow, .init = initialize_pow) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const Consensus::Params& consensus_params = Params().GetConsensus(); diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 132fb71f4f35..7830b2998218 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -2,15 +2,16 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include -#include #include #include #include +#include #include -#include #include