Skip to content

Commit 0a12cff

Browse files
committed
fuzz: move AddrManDeterministic to util
1 parent 33adc75 commit 0a12cff

File tree

2 files changed

+108
-106
lines changed

2 files changed

+108
-106
lines changed

src/test/fuzz/addrman.cpp

Lines changed: 4 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -118,121 +118,19 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
118118
}
119119
}
120120

121-
class AddrManDeterministic : public AddrMan
122-
{
123-
public:
124-
explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider)
125-
: AddrMan(netgroupman, /*deterministic=*/true, GetCheckRatio())
126-
{
127-
WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
128-
}
129-
130-
/**
131-
* Compare with another AddrMan.
132-
* This compares:
133-
* - the values in `mapInfo` (the keys aka ids are ignored)
134-
* - vvNew entries refer to the same addresses
135-
* - vvTried entries refer to the same addresses
136-
*/
137-
bool operator==(const AddrManDeterministic& other) const
138-
{
139-
LOCK2(m_impl->cs, other.m_impl->cs);
140-
141-
if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
142-
m_impl->nTried != other.m_impl->nTried) {
143-
return false;
144-
}
145-
146-
// Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
147-
// Keys may be different.
148-
149-
auto addrinfo_hasher = [](const AddrInfo& a) {
150-
CSipHasher hasher(0, 0);
151-
auto addr_key = a.GetKey();
152-
auto source_key = a.source.GetAddrBytes();
153-
hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
154-
hasher.Write(a.nAttempts);
155-
hasher.Write(a.nRefCount);
156-
hasher.Write(a.fInTried);
157-
hasher.Write(a.GetNetwork());
158-
hasher.Write(a.source.GetNetwork());
159-
hasher.Write(addr_key.size());
160-
hasher.Write(source_key.size());
161-
hasher.Write(addr_key);
162-
hasher.Write(source_key);
163-
return (size_t)hasher.Finalize();
164-
};
165-
166-
auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
167-
return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
168-
std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
169-
};
170-
171-
using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
172-
173-
const size_t num_addresses{m_impl->mapInfo.size()};
174-
175-
Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
176-
for (const auto& [id, addr] : m_impl->mapInfo) {
177-
addresses.insert(addr);
178-
}
179-
180-
Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
181-
for (const auto& [id, addr] : other.m_impl->mapInfo) {
182-
other_addresses.insert(addr);
183-
}
184-
185-
if (addresses != other_addresses) {
186-
return false;
187-
}
188-
189-
auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
190-
if (id == -1 && other_id == -1) {
191-
return true;
192-
}
193-
if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
194-
return false;
195-
}
196-
return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
197-
};
198-
199-
// Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
200-
// contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
201-
// themselves may differ between `vvNew` and `other.vvNew`.
202-
for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
203-
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
204-
if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
205-
return false;
206-
}
207-
}
208-
}
209-
210-
// Same for `vvTried`.
211-
for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
212-
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
213-
if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
214-
return false;
215-
}
216-
}
217-
}
218-
219-
return true;
220-
}
221-
};
222-
223121
FUZZ_TARGET(addrman, .init = initialize_addrman)
224122
{
225123
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
226124
SetMockTime(ConsumeTime(fuzzed_data_provider));
227125
NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
228-
auto addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider);
126+
auto addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
229127
if (fuzzed_data_provider.ConsumeBool()) {
230128
const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
231129
DataStream ds{serialized_data};
232130
try {
233131
ds >> *addr_man_ptr;
234132
} catch (const std::ios_base::failure&) {
235-
addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider);
133+
addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
236134
}
237135
}
238136
AddrManDeterministic& addr_man = *addr_man_ptr;
@@ -310,8 +208,8 @@ FUZZ_TARGET(addrman_serdeser, .init = initialize_addrman)
310208
SetMockTime(ConsumeTime(fuzzed_data_provider));
311209

312210
NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
313-
AddrManDeterministic addr_man1{netgroupman, fuzzed_data_provider};
314-
AddrManDeterministic addr_man2{netgroupman, fuzzed_data_provider};
211+
AddrManDeterministic addr_man1{netgroupman, fuzzed_data_provider, GetCheckRatio()};
212+
AddrManDeterministic addr_man2{netgroupman, fuzzed_data_provider, GetCheckRatio()};
315213

316214
DataStream data_stream{};
317215

src/test/fuzz/util/net.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef BITCOIN_TEST_FUZZ_UTIL_NET_H
66
#define BITCOIN_TEST_FUZZ_UTIL_NET_H
77

8+
#include <addrman.h>
9+
#include <addrman_impl.h>
810
#include <net.h>
911
#include <net_permissions.h>
1012
#include <netaddress.h>
@@ -34,6 +36,108 @@
3436
*/
3537
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext* rand = nullptr) noexcept;
3638

39+
class AddrManDeterministic : public AddrMan
40+
{
41+
public:
42+
explicit AddrManDeterministic(const NetGroupManager& netgroupman, FuzzedDataProvider& fuzzed_data_provider, int32_t check_ratio)
43+
: AddrMan(netgroupman, /*deterministic=*/true, check_ratio)
44+
{
45+
WITH_LOCK(m_impl->cs, m_impl->insecure_rand.Reseed(ConsumeUInt256(fuzzed_data_provider)));
46+
}
47+
48+
/**
49+
* Compare with another AddrMan.
50+
* This compares:
51+
* - the values in `mapInfo` (the keys aka ids are ignored)
52+
* - vvNew entries refer to the same addresses
53+
* - vvTried entries refer to the same addresses
54+
*/
55+
bool operator==(const AddrManDeterministic& other) const
56+
{
57+
LOCK2(m_impl->cs, other.m_impl->cs);
58+
59+
if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
60+
m_impl->nTried != other.m_impl->nTried) {
61+
return false;
62+
}
63+
64+
// Check that all values in `mapInfo` are equal to all values in `other.mapInfo`.
65+
// Keys may be different.
66+
67+
auto addrinfo_hasher = [](const AddrInfo& a) {
68+
CSipHasher hasher(0, 0);
69+
auto addr_key = a.GetKey();
70+
auto source_key = a.source.GetAddrBytes();
71+
hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
72+
hasher.Write(a.nAttempts);
73+
hasher.Write(a.nRefCount);
74+
hasher.Write(a.fInTried);
75+
hasher.Write(a.GetNetwork());
76+
hasher.Write(a.source.GetNetwork());
77+
hasher.Write(addr_key.size());
78+
hasher.Write(source_key.size());
79+
hasher.Write(addr_key);
80+
hasher.Write(source_key);
81+
return (size_t)hasher.Finalize();
82+
};
83+
84+
auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
85+
return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
86+
std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
87+
};
88+
89+
using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
90+
91+
const size_t num_addresses{m_impl->mapInfo.size()};
92+
93+
Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
94+
for (const auto& [id, addr] : m_impl->mapInfo) {
95+
addresses.insert(addr);
96+
}
97+
98+
Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
99+
for (const auto& [id, addr] : other.m_impl->mapInfo) {
100+
other_addresses.insert(addr);
101+
}
102+
103+
if (addresses != other_addresses) {
104+
return false;
105+
}
106+
107+
auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
108+
if (id == -1 && other_id == -1) {
109+
return true;
110+
}
111+
if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
112+
return false;
113+
}
114+
return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
115+
};
116+
117+
// Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
118+
// contains just an id and the address is to be found in `mapInfo.at(id)`. The ids
119+
// themselves may differ between `vvNew` and `other.vvNew`.
120+
for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
121+
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
122+
if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
123+
return false;
124+
}
125+
}
126+
}
127+
128+
// Same for `vvTried`.
129+
for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
130+
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
131+
if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
132+
return false;
133+
}
134+
}
135+
}
136+
137+
return true;
138+
}
139+
};
140+
37141
class FuzzedSock : public Sock
38142
{
39143
FuzzedDataProvider& m_fuzzed_data_provider;

0 commit comments

Comments
 (0)