diff options
Diffstat (limited to 'src/test/fuzz')
-rw-r--r-- | src/test/fuzz/addrman.cpp | 5 | ||||
-rw-r--r-- | src/test/fuzz/banman.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/connman.cpp | 13 | ||||
-rw-r--r-- | src/test/fuzz/fee_rate.cpp | 4 | ||||
-rw-r--r-- | src/test/fuzz/fuzz.cpp | 8 | ||||
-rw-r--r-- | src/test/fuzz/i2p.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/net.cpp | 22 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 7 | ||||
-rw-r--r-- | src/test/fuzz/tx_pool.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/utxo_snapshot.cpp | 87 |
10 files changed, 115 insertions, 38 deletions
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index 0baf30aef6..98ae32a8d0 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -60,7 +60,10 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman) (void)addr_man.Select(fuzzed_data_provider.ConsumeBool()); }, [&] { - (void)addr_man.GetAddr(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096)); + (void)addr_man.GetAddr( + /* max_addresses */ fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), + /* max_pct */ fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), + /* network */ std::nullopt); }, [&] { const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index 8bf484722c..4a04eed463 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -34,7 +34,7 @@ FUZZ_TARGET_INIT(banman, initialize_banman) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; SetMockTime(ConsumeTime(fuzzed_data_provider)); - const fs::path banlist_file = GetDataDir() / "fuzzed_banlist.dat"; + const fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist.dat"; fs::remove(banlist_file); { BanMan ban_man{banlist_file, nullptr, ConsumeBanTimeOffset(fuzzed_data_provider)}; diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index e07f25dedf..bbec5943af 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -65,16 +65,19 @@ FUZZ_TARGET_INIT(connman, initialize_connman) connman.ForEachNode([](auto) {}); }, [&] { - connman.ForEachNodeThen([](auto) {}, []() {}); - }, - [&] { (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); }); }, [&] { - (void)connman.GetAddresses(fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + (void)connman.GetAddresses( + /* max_addresses */ fuzzed_data_provider.ConsumeIntegral<size_t>(), + /* max_pct */ fuzzed_data_provider.ConsumeIntegral<size_t>(), + /* network */ std::nullopt); }, [&] { - (void)connman.GetAddresses(random_node, fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + (void)connman.GetAddresses( + /* requestor */ random_node, + /* max_addresses */ fuzzed_data_provider.ConsumeIntegral<size_t>(), + /* max_pct */ fuzzed_data_provider.ConsumeIntegral<size_t>()); }, [&] { (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); diff --git a/src/test/fuzz/fee_rate.cpp b/src/test/fuzz/fee_rate.cpp index 2955213635..dff0e58000 100644 --- a/src/test/fuzz/fee_rate.cpp +++ b/src/test/fuzz/fee_rate.cpp @@ -20,8 +20,8 @@ FUZZ_TARGET(fee_rate) const CFeeRate fee_rate{satoshis_per_k}; (void)fee_rate.GetFeePerK(); - const size_t bytes = fuzzed_data_provider.ConsumeIntegral<size_t>(); - if (!MultiplicationOverflow(static_cast<int64_t>(bytes), satoshis_per_k) && bytes <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { + const auto bytes = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + if (!MultiplicationOverflow(int64_t{bytes}, satoshis_per_k)) { (void)fee_rate.GetFee(bytes); } (void)fee_rate.ToString(); diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 0d8d960d56..631c861bb6 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -4,10 +4,15 @@ #include <test/fuzz/fuzz.h> +#include <netaddress.h> +#include <netbase.h> #include <test/util/setup_common.h> #include <util/check.h> +#include <util/sock.h> #include <cstdint> +#include <exception> +#include <memory> #include <unistd.h> #include <vector> @@ -29,6 +34,9 @@ static TypeTestOneInput* g_test_one_input{nullptr}; void initialize() { + // Terminate immediately if a fuzzing harness ever tries to create a TCP socket. + CreateSock = [](const CService&) -> std::unique_ptr<Sock> { std::terminate(); }; + bool should_abort{false}; if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) { for (const auto& t : FuzzTargets()) { diff --git a/src/test/fuzz/i2p.cpp b/src/test/fuzz/i2p.cpp index e0d62fb493..fb6d23aca5 100644 --- a/src/test/fuzz/i2p.cpp +++ b/src/test/fuzz/i2p.cpp @@ -30,7 +30,7 @@ FUZZ_TARGET_INIT(i2p, initialize_i2p) const CService sam_proxy; CThreadInterrupt interrupt; - i2p::sam::Session sess{GetDataDir() / "fuzzed_i2p_private_key", sam_proxy, &interrupt}; + i2p::sam::Session sess{gArgs.GetDataDirNet() / "fuzzed_i2p_private_key", sam_proxy, &interrupt}; i2p::Connection conn; diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 272f6415a9..20d8581312 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -58,27 +58,6 @@ FUZZ_TARGET_INIT(net, initialize_net) } }, [&] { - if (node.m_addr_known == nullptr) { - return; - } - const std::optional<CAddress> addr_opt = ConsumeDeserializable<CAddress>(fuzzed_data_provider); - if (!addr_opt) { - return; - } - node.AddAddressKnown(*addr_opt); - }, - [&] { - if (node.m_addr_known == nullptr) { - return; - } - const std::optional<CAddress> addr_opt = ConsumeDeserializable<CAddress>(fuzzed_data_provider); - if (!addr_opt) { - return; - } - FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)}; - node.PushAddress(*addr_opt, fast_random_context); - }, - [&] { const std::optional<CInv> inv_opt = ConsumeDeserializable<CInv>(fuzzed_data_provider); if (!inv_opt) { return; @@ -110,7 +89,6 @@ FUZZ_TARGET_INIT(net, initialize_net) const int ref_count = node.GetRefCount(); assert(ref_count >= 0); (void)node.GetCommonVersion(); - (void)node.RelayAddrsWithConn(); const NetPermissionFlags net_permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS); (void)node.HasPermission(net_permission_flags); diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 797b9cea3e..ff34cc87b2 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -103,9 +103,6 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction) (void)IsWitnessStandard(tx, coins_view_cache); UniValue u(UniValue::VOBJ); - TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ true, u); - TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ false, u); - static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - TxToUniv(tx, u256_max, /* include_addresses */ true, u); - TxToUniv(tx, u256_max, /* include_addresses */ false, u); + TxToUniv(tx, /* hashBlock */ uint256::ZERO, /* include_addresses */ true, u); + TxToUniv(tx, /* hashBlock */ uint256::ONE, /* include_addresses */ false, u); } diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp index 068e207118..ad11f2c5f2 100644 --- a/src/test/fuzz/tx_pool.cpp +++ b/src/test/fuzz/tx_pool.cpp @@ -21,8 +21,9 @@ std::vector<COutPoint> g_outpoints_coinbase_init_mature; std::vector<COutPoint> g_outpoints_coinbase_init_immature; struct MockedTxPool : public CTxMemPool { - void RollingFeeUpdate() + void RollingFeeUpdate() EXCLUSIVE_LOCKS_REQUIRED(!cs) { + LOCK(cs); lastRollingFeeUpdate = GetTime(); blockSinceLastRollingFeeBump = true; } diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp new file mode 100644 index 0000000000..6f2bc081c6 --- /dev/null +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -0,0 +1,87 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <chainparams.h> +#include <consensus/validation.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/mining.h> +#include <test/util/setup_common.h> +#include <validation.h> +#include <validationinterface.h> + +namespace { + +const std::vector<std::shared_ptr<CBlock>>* g_chain; + +void initialize_chain() +{ + const auto params{CreateChainParams(ArgsManager{}, CBaseChainParams::REGTEST)}; + static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)}; + g_chain = &chain; +} + +FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()}; + const auto& node = setup->m_node; + auto& chainman{*node.chainman}; + + const auto snapshot_path = gArgs.GetDataDirNet() / "fuzzed_snapshot.dat"; + + Assert(!chainman.SnapshotBlockhash()); + + { + CAutoFile outfile{fsbridge::fopen(snapshot_path, "wb"), SER_DISK, CLIENT_VERSION}; + const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; + outfile << Span<const uint8_t>{file_data}; + } + + const auto ActivateFuzzedSnapshot{[&] { + CAutoFile infile{fsbridge::fopen(snapshot_path, "rb"), SER_DISK, CLIENT_VERSION}; + SnapshotMetadata metadata; + try { + infile >> metadata; + } catch (const std::ios_base::failure&) { + return false; + } + return chainman.ActivateSnapshot(infile, metadata, /* in_memory */ true); + }}; + + if (fuzzed_data_provider.ConsumeBool()) { + for (const auto& block : *g_chain) { + BlockValidationState dummy; + bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy, ::Params())}; + Assert(processed); + const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))}; + Assert(index); + } + } + + if (ActivateFuzzedSnapshot()) { + LOCK(::cs_main); + Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull()); + Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash == + *chainman.SnapshotBlockhash()); + const auto& coinscache{chainman.ActiveChainstate().CoinsTip()}; + int64_t chain_tx{}; + for (const auto& block : *g_chain) { + Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0})); + const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())}; + const auto num_tx{Assert(index)->nTx}; + Assert(num_tx == 1); + chain_tx += num_tx; + } + Assert(g_chain->size() == coinscache.GetCacheSize()); + Assert(chain_tx == chainman.ActiveTip()->nChainTx); + } else { + Assert(!chainman.SnapshotBlockhash()); + Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash); + } + // Snapshot should refuse to load a second time regardless of validity + Assert(!ActivateFuzzedSnapshot()); +} +} // namespace |