Skip to content

Commit a60d570

Browse files
committed
Merge bitcoin/bitcoin#31486: fuzz: Abort when using global PRNG without re-seed
fae63bf fuzz: Clarify that only SeedRandomStateForTest(SeedRand::ZEROS) is allowed (MarcoFalke) fa18acb fuzz: Abort when using global PRNG without re-seed (MarcoFalke) fa7809a fuzz: Add missing SeedRandomStateForTest(SeedRand::ZEROS) (MarcoFalke) Pull request description: This is the first step toward improving fuzz stability and determinism (bitcoin/bitcoin#29018). A fuzz target using the global test-only PRNG will now abort if the seed is re-used across fuzz inputs. Also, temporarily add `SeedRandomStateForTest(SeedRand::ZEROS)` to all affected fuzz targets. This may slow down the libfuzzer leak detector, but it will disable itself after some time, or it can be disabled explicitly with `-detect_leaks=0`. In a follow-up, each affected fuzz target can be stripped of the global random use and a local `RandomMixin` (or similar) can be added instead. (Can be tested by removing any one of the re-seed calls and observing a fuzz abort) ACKs for top commit: hodlinator: ACK fae63bf dergoegge: utACK fae63bf marcofleon: Tested ACK fae63bf Tree-SHA512: 4a0db69af7f715408edf4f8b08b44f34ce12ee2c79d33b336ad19a6e6bd079c4ff7c971af0a3efa428213407c1171f4e2837ec6a2577086c2f94cd15618a0892
2 parents a95a8ba + fae63bf commit a60d570

39 files changed

+131
-7
lines changed

src/random.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,9 +671,11 @@ void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept
671671
{
672672
GetRNGState().MakeDeterministic(seed);
673673
}
674+
std::atomic<bool> g_used_g_prng{false}; // Only accessed from tests
674675

675676
void GetRandBytes(Span<unsigned char> bytes) noexcept
676677
{
678+
g_used_g_prng = true;
677679
ProcRand(bytes.data(), bytes.size(), RNGLevel::FAST, /*always_use_real_rng=*/false);
678680
}
679681

src/test/fuzz/addrman.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void initialize_addrman()
4141

4242
FUZZ_TARGET(data_stream_addr_man, .init = initialize_addrman)
4343
{
44+
SeedRandomStateForTest(SeedRand::ZEROS);
4445
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
4546
DataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
4647
NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
@@ -113,6 +114,7 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
113114

114115
FUZZ_TARGET(addrman, .init = initialize_addrman)
115116
{
117+
SeedRandomStateForTest(SeedRand::ZEROS);
116118
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
117119
SetMockTime(ConsumeTime(fuzzed_data_provider));
118120
NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
@@ -197,6 +199,7 @@ FUZZ_TARGET(addrman, .init = initialize_addrman)
197199
// Check that serialize followed by unserialize produces the same addrman.
198200
FUZZ_TARGET(addrman_serdeser, .init = initialize_addrman)
199201
{
202+
SeedRandomStateForTest(SeedRand::ZEROS);
200203
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
201204
SetMockTime(ConsumeTime(fuzzed_data_provider));
202205

src/test/fuzz/banman.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs)
4242

4343
FUZZ_TARGET(banman, .init = initialize_banman)
4444
{
45+
SeedRandomStateForTest(SeedRand::ZEROS);
4546
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
4647
SetMockTime(ConsumeTime(fuzzed_data_provider));
4748
fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist";

src/test/fuzz/blockfilter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <test/fuzz/FuzzedDataProvider.h>
77
#include <test/fuzz/fuzz.h>
88
#include <test/fuzz/util.h>
9+
#include <test/util/random.h>
910

1011
#include <cstdint>
1112
#include <optional>
@@ -14,6 +15,7 @@
1415

1516
FUZZ_TARGET(blockfilter)
1617
{
18+
SeedRandomStateForTest(SeedRand::ZEROS);
1719
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
1820
const std::optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
1921
if (!block_filter) {

src/test/fuzz/connman.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void initialize_connman()
3636

3737
FUZZ_TARGET(connman, .init = initialize_connman)
3838
{
39+
SeedRandomStateForTest(SeedRand::ZEROS);
3940
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
4041
SetMockTime(ConsumeTime(fuzzed_data_provider));
4142
auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};

src/test/fuzz/fuzz.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <netaddress.h>
88
#include <netbase.h>
9+
#include <test/fuzz/util/check_globals.h>
910
#include <test/util/random.h>
1011
#include <test/util/setup_common.h>
1112
#include <util/check.h>
@@ -78,6 +79,12 @@ void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target,
7879
static std::string_view g_fuzz_target;
7980
static const TypeTestOneInput* g_test_one_input{nullptr};
8081

82+
inline void test_one_input(FuzzBufferType buffer)
83+
{
84+
CheckGlobals check{};
85+
(*Assert(g_test_one_input))(buffer);
86+
}
87+
8188
const std::function<std::string()> G_TEST_GET_FULL_NAME{[]{
8289
return std::string{g_fuzz_target};
8390
}};
@@ -210,7 +217,6 @@ void signal_handler(int signal)
210217
// This function is used by libFuzzer
211218
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
212219
{
213-
static const auto& test_one_input = *Assert(g_test_one_input);
214220
test_one_input({data, size});
215221
return 0;
216222
}
@@ -227,7 +233,6 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
227233
int main(int argc, char** argv)
228234
{
229235
initialize();
230-
static const auto& test_one_input = *Assert(g_test_one_input);
231236
#ifdef __AFL_LOOP
232237
// Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
233238
// See fuzzing.md for details.

src/test/fuzz/golomb_rice.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <test/fuzz/FuzzedDataProvider.h>
99
#include <test/fuzz/fuzz.h>
1010
#include <test/fuzz/util.h>
11+
#include <test/util/random.h>
1112
#include <util/bytevectorhash.h>
1213
#include <util/golombrice.h>
1314

@@ -42,6 +43,7 @@ std::vector<uint64_t> BuildHashedSet(const std::unordered_set<std::vector<uint8_
4243

4344
FUZZ_TARGET(golomb_rice)
4445
{
46+
SeedRandomStateForTest(SeedRand::ZEROS);
4547
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
4648
std::vector<uint8_t> golomb_rice_data;
4749
std::vector<uint64_t> encoded_deltas;

src/test/fuzz/headerssync.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class FuzzedHeadersSyncState : public HeadersSyncState
4848

4949
FUZZ_TARGET(headers_sync_state, .init = initialize_headers_sync_state_fuzz)
5050
{
51+
SeedRandomStateForTest(SeedRand::ZEROS);
5152
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
5253
auto mock_time{ConsumeTime(fuzzed_data_provider)};
5354

src/test/fuzz/i2p.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void initialize_i2p()
2121

2222
FUZZ_TARGET(i2p, .init = initialize_i2p)
2323
{
24+
SeedRandomStateForTest(SeedRand::ZEROS);
2425
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
2526

2627
SetMockTime(ConsumeTime(fuzzed_data_provider));

src/test/fuzz/key.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <test/fuzz/FuzzedDataProvider.h>
1919
#include <test/fuzz/fuzz.h>
2020
#include <test/fuzz/util.h>
21+
#include <test/util/random.h>
2122
#include <util/chaintype.h>
2223
#include <util/strencodings.h>
2324

@@ -38,6 +39,7 @@ void initialize_key()
3839

3940
FUZZ_TARGET(key, .init = initialize_key)
4041
{
42+
SeedRandomStateForTest(SeedRand::ZEROS);
4143
const CKey key = [&] {
4244
CKey k;
4345
k.Set(buffer.begin(), buffer.end(), true);

0 commit comments

Comments
 (0)