aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/fuzz')
-rw-r--r--src/test/fuzz/addition_overflow.cpp2
-rw-r--r--src/test/fuzz/deserialize.cpp1
-rw-r--r--src/test/fuzz/fuzz.cpp7
-rw-r--r--src/test/fuzz/miniscript.cpp42
-rw-r--r--src/test/fuzz/multiplication_overflow.cpp6
-rw-r--r--src/test/fuzz/partially_downloaded_block.cpp2
-rw-r--r--src/test/fuzz/poolresource.cpp4
-rw-r--r--src/test/fuzz/timedata.cpp31
-rw-r--r--src/test/fuzz/timeoffsets.cpp28
-rw-r--r--src/test/fuzz/tx_pool.cpp2
-rw-r--r--src/test/fuzz/txorphan.cpp32
11 files changed, 94 insertions, 63 deletions
diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp
index 5100b6f438..071e5fb029 100644
--- a/src/test/fuzz/addition_overflow.cpp
+++ b/src/test/fuzz/addition_overflow.cpp
@@ -24,12 +24,14 @@ void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
assert(is_addition_overflow_custom == AdditionOverflow(j, i));
assert(maybe_add == CheckedAdd(j, i));
assert(sat_add == SaturatingAdd(j, i));
+#ifndef _MSC_VER
T result_builtin;
const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin);
assert(is_addition_overflow_custom == is_addition_overflow_builtin);
if (!is_addition_overflow_custom) {
assert(i + j == result_builtin);
}
+#endif
if (is_addition_overflow_custom) {
assert(sat_add == std::numeric_limits<T>::min() || sat_add == std::numeric_limits<T>::max());
} else {
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index ebc5673e71..c9a3bc86ac 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -33,7 +33,6 @@
#include <optional>
#include <stdexcept>
#include <stdint.h>
-#include <unistd.h>
using node::SnapshotMetadata;
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index a8e490b459..f9915187bd 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -25,7 +25,6 @@
#include <memory>
#include <string>
#include <tuple>
-#include <unistd.h>
#include <utility>
#include <vector>
@@ -135,9 +134,9 @@ void initialize()
#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)
static bool read_stdin(std::vector<uint8_t>& data)
{
- uint8_t buffer[1024];
- ssize_t length = 0;
- while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
+ std::istream::char_type buffer[1024];
+ std::streamsize length;
+ while ((std::cin.read(buffer, 1024), length = std::cin.gcount()) > 0) {
data.insert(data.end(), buffer, buffer + length);
}
return length == 0;
diff --git a/src/test/fuzz/miniscript.cpp b/src/test/fuzz/miniscript.cpp
index 0d0ee59ab3..947424c4ac 100644
--- a/src/test/fuzz/miniscript.cpp
+++ b/src/test/fuzz/miniscript.cpp
@@ -391,6 +391,7 @@ std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx, FuzzedDataProvider&
bool allow_K = (type_needed == ""_mst) || (type_needed << "K"_mst);
bool allow_V = (type_needed == ""_mst) || (type_needed << "V"_mst);
bool allow_W = (type_needed == ""_mst) || (type_needed << "W"_mst);
+ static constexpr auto B{"B"_mst}, K{"K"_mst}, V{"V"_mst}, W{"W"_mst};
switch (provider.ConsumeIntegral<uint8_t>()) {
case 0:
@@ -440,22 +441,22 @@ std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx, FuzzedDataProvider&
}
case 11:
if (!(allow_B || allow_K || allow_V)) return {};
- return {{{"B"_mst, type_needed, type_needed}, Fragment::ANDOR}};
+ return {{{B, type_needed, type_needed}, Fragment::ANDOR}};
case 12:
if (!(allow_B || allow_K || allow_V)) return {};
- return {{{"V"_mst, type_needed}, Fragment::AND_V}};
+ return {{{V, type_needed}, Fragment::AND_V}};
case 13:
if (!allow_B) return {};
- return {{{"B"_mst, "W"_mst}, Fragment::AND_B}};
+ return {{{B, W}, Fragment::AND_B}};
case 15:
if (!allow_B) return {};
- return {{{"B"_mst, "W"_mst}, Fragment::OR_B}};
+ return {{{B, W}, Fragment::OR_B}};
case 16:
if (!allow_V) return {};
- return {{{"B"_mst, "V"_mst}, Fragment::OR_C}};
+ return {{{B, V}, Fragment::OR_C}};
case 17:
if (!allow_B) return {};
- return {{{"B"_mst, "B"_mst}, Fragment::OR_D}};
+ return {{{B, B}, Fragment::OR_D}};
case 18:
if (!(allow_B || allow_K || allow_V)) return {};
return {{{type_needed, type_needed}, Fragment::OR_I}};
@@ -472,25 +473,25 @@ std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx, FuzzedDataProvider&
}
case 20:
if (!allow_W) return {};
- return {{{"B"_mst}, Fragment::WRAP_A}};
+ return {{{B}, Fragment::WRAP_A}};
case 21:
if (!allow_W) return {};
- return {{{"B"_mst}, Fragment::WRAP_S}};
+ return {{{B}, Fragment::WRAP_S}};
case 22:
if (!allow_B) return {};
- return {{{"K"_mst}, Fragment::WRAP_C}};
+ return {{{K}, Fragment::WRAP_C}};
case 23:
if (!allow_B) return {};
- return {{{"V"_mst}, Fragment::WRAP_D}};
+ return {{{V}, Fragment::WRAP_D}};
case 24:
if (!allow_V) return {};
- return {{{"B"_mst}, Fragment::WRAP_V}};
+ return {{{B}, Fragment::WRAP_V}};
case 25:
if (!allow_B) return {};
- return {{{"B"_mst}, Fragment::WRAP_J}};
+ return {{{B}, Fragment::WRAP_J}};
case 26:
if (!allow_B) return {};
- return {{{"B"_mst}, Fragment::WRAP_N}};
+ return {{{B}, Fragment::WRAP_N}};
case 27: {
if (!allow_B || !IsTapscript(script_ctx)) return {};
const auto k = provider.ConsumeIntegral<uint16_t>();
@@ -528,20 +529,23 @@ struct SmartInfo
{
/* Construct a set of interesting type requirements to reason with (sections of BKVWzondu). */
std::vector<Type> types;
+ static constexpr auto B_mst{"B"_mst}, K_mst{"K"_mst}, V_mst{"V"_mst}, W_mst{"W"_mst};
+ static constexpr auto d_mst{"d"_mst}, n_mst{"n"_mst}, o_mst{"o"_mst}, u_mst{"u"_mst}, z_mst{"z"_mst};
+ static constexpr auto NONE_mst{""_mst};
for (int base = 0; base < 4; ++base) { /* select from B,K,V,W */
- Type type_base = base == 0 ? "B"_mst : base == 1 ? "K"_mst : base == 2 ? "V"_mst : "W"_mst;
+ Type type_base = base == 0 ? B_mst : base == 1 ? K_mst : base == 2 ? V_mst : W_mst;
for (int zo = 0; zo < 3; ++zo) { /* select from z,o,(none) */
- Type type_zo = zo == 0 ? "z"_mst : zo == 1 ? "o"_mst : ""_mst;
+ Type type_zo = zo == 0 ? z_mst : zo == 1 ? o_mst : NONE_mst;
for (int n = 0; n < 2; ++n) { /* select from (none),n */
if (zo == 0 && n == 1) continue; /* z conflicts with n */
if (base == 3 && n == 1) continue; /* W conflicts with n */
- Type type_n = n == 0 ? ""_mst : "n"_mst;
+ Type type_n = n == 0 ? NONE_mst : n_mst;
for (int d = 0; d < 2; ++d) { /* select from (none),d */
if (base == 2 && d == 1) continue; /* V conflicts with d */
- Type type_d = d == 0 ? ""_mst : "d"_mst;
+ Type type_d = d == 0 ? NONE_mst : d_mst;
for (int u = 0; u < 2; ++u) { /* select from (none),u */
if (base == 2 && u == 1) continue; /* V conflicts with u */
- Type type_u = u == 0 ? ""_mst : "u"_mst;
+ Type type_u = u == 0 ? NONE_mst : u_mst;
Type type = type_base | type_zo | type_n | type_d | type_u;
types.push_back(type);
}
@@ -683,7 +687,7 @@ struct SmartInfo
/* Find which types are useful. The fuzzer logic only cares about constructing
* B,V,K,W nodes, so any type that isn't needed in any recipe (directly or
* indirectly) for the construction of those is uninteresting. */
- std::set<Type> useful_types{"B"_mst, "V"_mst, "K"_mst, "W"_mst};
+ std::set<Type> useful_types{B_mst, V_mst, K_mst, W_mst};
// Find the transitive closure by adding types until the set of types does not change.
while (true) {
size_t set_size = useful_types.size();
diff --git a/src/test/fuzz/multiplication_overflow.cpp b/src/test/fuzz/multiplication_overflow.cpp
index aeef4f24b7..a762a4dfe3 100644
--- a/src/test/fuzz/multiplication_overflow.cpp
+++ b/src/test/fuzz/multiplication_overflow.cpp
@@ -17,12 +17,18 @@ void TestMultiplicationOverflow(FuzzedDataProvider& fuzzed_data_provider)
const T i = fuzzed_data_provider.ConsumeIntegral<T>();
const T j = fuzzed_data_provider.ConsumeIntegral<T>();
const bool is_multiplication_overflow_custom = MultiplicationOverflow(i, j);
+#ifndef _MSC_VER
T result_builtin;
const bool is_multiplication_overflow_builtin = __builtin_mul_overflow(i, j, &result_builtin);
assert(is_multiplication_overflow_custom == is_multiplication_overflow_builtin);
if (!is_multiplication_overflow_custom) {
assert(i * j == result_builtin);
}
+#else
+ if (!is_multiplication_overflow_custom) {
+ (void)(i * j);
+ }
+#endif
}
} // namespace
diff --git a/src/test/fuzz/partially_downloaded_block.cpp b/src/test/fuzz/partially_downloaded_block.cpp
index ab75afe066..2bf47930f4 100644
--- a/src/test/fuzz/partially_downloaded_block.cpp
+++ b/src/test/fuzz/partially_downloaded_block.cpp
@@ -72,7 +72,7 @@ FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
available.insert(i);
}
- if (add_to_mempool) {
+ if (add_to_mempool && !pool.exists(GenTxid::Txid(tx->GetHash()))) {
LOCK2(cs_main, pool.cs);
pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
available.insert(i);
diff --git a/src/test/fuzz/poolresource.cpp b/src/test/fuzz/poolresource.cpp
index ce64ef6472..f764d9f8db 100644
--- a/src/test/fuzz/poolresource.cpp
+++ b/src/test/fuzz/poolresource.cpp
@@ -63,9 +63,9 @@ public:
{
if (m_total_allocated > 0x1000000) return;
size_t alignment_bits = m_provider.ConsumeIntegralInRange<size_t>(0, 7);
- size_t alignment = 1 << alignment_bits;
+ size_t alignment = size_t{1} << alignment_bits;
size_t size_bits = m_provider.ConsumeIntegralInRange<size_t>(0, 16 - alignment_bits);
- size_t size = m_provider.ConsumeIntegralInRange<size_t>(1U << size_bits, (1U << (size_bits + 1)) - 1U) << alignment_bits;
+ size_t size = m_provider.ConsumeIntegralInRange<size_t>(size_t{1} << size_bits, (size_t{1} << (size_bits + 1)) - 1U) << alignment_bits;
Allocate(size, alignment);
}
diff --git a/src/test/fuzz/timedata.cpp b/src/test/fuzz/timedata.cpp
deleted file mode 100644
index f5d005296b..0000000000
--- a/src/test/fuzz/timedata.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2020-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 <test/fuzz/FuzzedDataProvider.h>
-#include <test/fuzz/fuzz.h>
-#include <test/fuzz/util.h>
-#include <timedata.h>
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-FUZZ_TARGET(timedata)
-{
- FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- const unsigned int max_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1000);
- // A max_size of 0 implies no limit, so cap the max number of insertions to avoid timeouts
- auto max_to_insert = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 4000);
- // Divide by 2 to avoid signed integer overflow in .median()
- const int64_t initial_value = fuzzed_data_provider.ConsumeIntegral<int64_t>() / 2;
- CMedianFilter<int64_t> median_filter{max_size, initial_value};
- while (fuzzed_data_provider.remaining_bytes() > 0 && --max_to_insert >= 0) {
- (void)median_filter.median();
- assert(median_filter.size() > 0);
- assert(static_cast<size_t>(median_filter.size()) == median_filter.sorted().size());
- assert(static_cast<unsigned int>(median_filter.size()) <= max_size || max_size == 0);
- // Divide by 2 to avoid signed integer overflow in .median()
- median_filter.input(fuzzed_data_provider.ConsumeIntegral<int64_t>() / 2);
- }
-}
diff --git a/src/test/fuzz/timeoffsets.cpp b/src/test/fuzz/timeoffsets.cpp
new file mode 100644
index 0000000000..019337a94a
--- /dev/null
+++ b/src/test/fuzz/timeoffsets.cpp
@@ -0,0 +1,28 @@
+// Copyright (c) 2024-present 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 <node/timeoffsets.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/util/setup_common.h>
+
+#include <chrono>
+#include <cstdint>
+#include <functional>
+
+void initialize_timeoffsets()
+{
+ static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);
+}
+
+FUZZ_TARGET(timeoffsets, .init = initialize_timeoffsets)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ TimeOffsets offsets{};
+ LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 4'000) {
+ (void)offsets.Median();
+ offsets.Add(std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<std::chrono::seconds::rep>()});
+ offsets.WarnIfOutOfSync();
+ }
+}
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index 0b4019d5eb..9f0aedf29b 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -139,7 +139,6 @@ void CheckATMPInvariants(const MempoolAcceptResult& res, bool txid_in_mempool, b
Assert(wtxid_in_mempool);
Assert(res.m_state.IsValid());
Assert(!res.m_state.IsInvalid());
- Assert(res.m_replaced_transactions);
Assert(res.m_vsize);
Assert(res.m_base_fees);
Assert(res.m_effective_feerate);
@@ -154,7 +153,6 @@ void CheckATMPInvariants(const MempoolAcceptResult& res, bool txid_in_mempool, b
Assert(res.m_state.IsInvalid());
const bool is_reconsiderable{res.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE};
- Assert(!res.m_replaced_transactions);
Assert(!res.m_vsize);
Assert(!res.m_base_fees);
// Fee information is provided if the failure is TX_RECONSIDERABLE.
diff --git a/src/test/fuzz/txorphan.cpp b/src/test/fuzz/txorphan.cpp
index 5423ba8920..a44f47b00d 100644
--- a/src/test/fuzz/txorphan.cpp
+++ b/src/test/fuzz/txorphan.cpp
@@ -45,6 +45,8 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
// if true, allow duplicate input when constructing tx
const bool duplicate_input = fuzzed_data_provider.ConsumeBool();
+ CTransactionRef ptx_potential_parent = nullptr;
+
LIMITED_WHILE(outpoints.size() < 200'000 && fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS)
{
// construct transaction
@@ -78,6 +80,27 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
return new_tx;
}();
+ // Trigger orphanage functions that are called using parents. ptx_potential_parent is a tx we constructed in a
+ // previous loop and potentially the parent of this tx.
+ if (ptx_potential_parent) {
+ // Set up future GetTxToReconsider call.
+ orphanage.AddChildrenToWorkSet(*ptx_potential_parent);
+
+ // Check that all txns returned from GetChildrenFrom* are indeed a direct child of this tx.
+ NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
+ for (const auto& child : orphanage.GetChildrenFromSamePeer(ptx_potential_parent, peer_id)) {
+ assert(std::any_of(child->vin.cbegin(), child->vin.cend(), [&](const auto& input) {
+ return input.prevout.hash == ptx_potential_parent->GetHash();
+ }));
+ }
+ for (const auto& [child, peer] : orphanage.GetChildrenFromDifferentPeer(ptx_potential_parent, peer_id)) {
+ assert(std::any_of(child->vin.cbegin(), child->vin.cend(), [&](const auto& input) {
+ return input.prevout.hash == ptx_potential_parent->GetHash();
+ }));
+ assert(peer != peer_id);
+ }
+ }
+
// trigger orphanage functions
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS)
{
@@ -86,9 +109,6 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
CallOneOf(
fuzzed_data_provider,
[&] {
- orphanage.AddChildrenToWorkSet(*tx);
- },
- [&] {
{
CTransactionRef ref = orphanage.GetTxToReconsider(peer_id);
if (ref) {
@@ -136,6 +156,12 @@ FUZZ_TARGET(txorphan, .init = initialize_orphanage)
orphanage.LimitOrphans(limit, limit_orphans_rng);
Assert(orphanage.Size() <= limit);
});
+
+ }
+ // Set tx as potential parent to be used for future GetChildren() calls.
+ if (!ptx_potential_parent || fuzzed_data_provider.ConsumeBool()) {
+ ptx_potential_parent = tx;
}
+
}
}