Merge bitcoin/bitcoin#34913: fuzz: Use time helpers in node_eviction

fa1ebde1ad fuzz: Use time helpers in node_eviction (MarcoFalke)

Pull request description:

  The `node_eviction` fuzz test has many issues:

  * It uses the full `int64_t` range (in seconds) as input, which is absurdly large (millions of years) and also violates https://en.cppreference.com/w/cpp/chrono/duration.html:

  > Each of the predefined duration types up to hours covers a range of at least ±292 years.

  * It does not use the existing `ConsumeDuration` and `ConsumeTime` helpers, which makes specifying a proper range difficult.

  So fix all issues by using `ConsumeTime` for time points with default arguments, and `ConsumeDuration` with the same precision, as well as possibly negative values.

ACKs for top commit:
  marcofleon:
    crACK fa1ebde1ad
  brunoerg:
    reACK fa1ebde1ad
  w0xlt:
    ACK fa1ebde1ad

Tree-SHA512: 22045e6c563a9169327737895ea2f3a7b1dcb4fd24fce56d91caa1e132d03a85cbaaa5f78218d23cfa203fe2ee4b147894c02870eb20ae1c232ad55ccdb6f7f7
This commit is contained in:
merge-script
2026-03-27 08:40:54 +08:00
4 changed files with 18 additions and 13 deletions

View File

@@ -145,7 +145,7 @@ FUZZ_TARGET(addrman, .init = initialize_addrman)
addresses.push_back(ConsumeAddress(fuzzed_data_provider));
}
auto net_addr = ConsumeNetAddr(fuzzed_data_provider);
auto time_penalty = ConsumeDuration(fuzzed_data_provider, /*min=*/0s, /*max=*/100000000s);
auto time_penalty = ConsumeDuration<std::chrono::seconds>(fuzzed_data_provider, /*min=*/0s, /*max=*/100000000s);
addr_man.Add(addresses, net_addr, time_penalty);
},
[&] {

View File

@@ -19,13 +19,14 @@ FUZZ_TARGET(node_eviction)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
std::vector<NodeEvictionCandidate> eviction_candidates;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
{
eviction_candidates.push_back({
/*id=*/fuzzed_data_provider.ConsumeIntegral<NodeId>(),
/*m_connected=*/std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()},
/*m_min_ping_time=*/std::chrono::microseconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()},
/*m_last_block_time=*/std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()},
/*m_last_tx_time=*/std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()},
/*m_connected=*/ConsumeTime(fuzzed_data_provider).time_since_epoch(),
/*m_min_ping_time=*/ConsumeDuration<decltype(NodeEvictionCandidate::m_min_ping_time)>(fuzzed_data_provider, /*min=*/std::chrono::years{-1}, /*max=*/decltype(CNode::m_min_ping_time.load())::max()),
/*m_last_block_time=*/ConsumeTime(fuzzed_data_provider).time_since_epoch(),
/*m_last_tx_time=*/ConsumeTime(fuzzed_data_provider).time_since_epoch(),
/*fRelevantServices=*/fuzzed_data_provider.ConsumeBool(),
/*m_relay_txs=*/fuzzed_data_provider.ConsumeBool(),
/*fBloomFilter=*/fuzzed_data_provider.ConsumeBool(),

View File

@@ -36,12 +36,7 @@ NodeSeconds ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::opt
// Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) disables mocktime.
static const int64_t time_min{ParseISO8601DateTime("2000-01-01T00:00:01Z").value()};
static const int64_t time_max{ParseISO8601DateTime("2100-12-31T23:59:59Z").value()};
return NodeSeconds{ConsumeDuration(fuzzed_data_provider, min.value_or(time_min) * 1s, max.value_or(time_max) * 1s)};
}
std::chrono::seconds ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::chrono::seconds min, std::chrono::seconds max) noexcept
{
return 1s * fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(min.count(), max.count());
return NodeSeconds{ConsumeDuration<std::chrono::seconds>(fuzzed_data_provider, min.value_or(time_min) * 1s, max.value_or(time_max) * 1s)};
}
CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<Txid>>& prevout_txids, const int max_num_in, const int max_num_out) noexcept

View File

@@ -140,7 +140,16 @@ template <typename WeakEnumType, size_t size>
[[nodiscard]] CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::optional<CAmount>& max = std::nullopt) noexcept;
[[nodiscard]] NodeSeconds ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::optional<int64_t>& min = std::nullopt, const std::optional<int64_t>& max = std::nullopt) noexcept;
[[nodiscard]] std::chrono::seconds ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::chrono::seconds min, std::chrono::seconds max) noexcept;
template <class Dur>
// Having the compiler infer the template argument from the function argument
// is dangerous, because the desired return value generally has a different
// type than the function argument. So std::common_type is used to force the
// call site to specify the type of the return value.
[[nodiscard]] Dur ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::common_type_t<Dur> min, std::common_type_t<Dur> max) noexcept
{
return Dur{fuzzed_data_provider.ConsumeIntegralInRange(min.count(), max.count())};
}
[[nodiscard]] CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<Txid>>& prevout_txids, int max_num_in = 10, int max_num_out = 10) noexcept;