mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-05 18:52:29 +02:00
fuzz: extend ConsumeNetAddr() to return I2P and CJDNS addresses
In the process of doing so, refactor `ConsumeNetAddr()` to generate the addresses from IPv4, IPv6, Tor, I2P and CJDNS networks in the same way - by preparing some random stream and deserializing from it. Similar code was already found in `RandAddr()`.
This commit is contained in:
@@ -25,33 +25,63 @@
|
||||
|
||||
class CNode;
|
||||
|
||||
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext* rand) noexcept
|
||||
{
|
||||
const Network network = fuzzed_data_provider.PickValueInArray({Network::NET_IPV4, Network::NET_IPV6, Network::NET_INTERNAL, Network::NET_ONION});
|
||||
CNetAddr net_addr;
|
||||
if (network == Network::NET_IPV4) {
|
||||
in_addr v4_addr = {};
|
||||
v4_addr.s_addr = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
|
||||
net_addr = CNetAddr{v4_addr};
|
||||
} else if (network == Network::NET_IPV6) {
|
||||
if (fuzzed_data_provider.remaining_bytes() >= 16) {
|
||||
in6_addr v6_addr = {};
|
||||
auto addr_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(16);
|
||||
if (addr_bytes[0] == CJDNS_PREFIX) { // Avoid generating IPv6 addresses that look like CJDNS.
|
||||
addr_bytes[0] = 0x55; // Just an arbitrary number, anything != CJDNS_PREFIX would do.
|
||||
}
|
||||
memcpy(v6_addr.s6_addr, addr_bytes.data(), 16);
|
||||
net_addr = CNetAddr{v6_addr, fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
|
||||
struct NetAux {
|
||||
Network net;
|
||||
CNetAddr::BIP155Network bip155;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static constexpr std::array<NetAux, 6> nets{
|
||||
NetAux{.net = Network::NET_IPV4, .bip155 = CNetAddr::BIP155Network::IPV4, .len = ADDR_IPV4_SIZE},
|
||||
NetAux{.net = Network::NET_IPV6, .bip155 = CNetAddr::BIP155Network::IPV6, .len = ADDR_IPV6_SIZE},
|
||||
NetAux{.net = Network::NET_ONION, .bip155 = CNetAddr::BIP155Network::TORV3, .len = ADDR_TORV3_SIZE},
|
||||
NetAux{.net = Network::NET_I2P, .bip155 = CNetAddr::BIP155Network::I2P, .len = ADDR_I2P_SIZE},
|
||||
NetAux{.net = Network::NET_CJDNS, .bip155 = CNetAddr::BIP155Network::CJDNS, .len = ADDR_CJDNS_SIZE},
|
||||
NetAux{.net = Network::NET_INTERNAL, .bip155 = CNetAddr::BIP155Network{0}, .len = 0},
|
||||
};
|
||||
|
||||
const size_t nets_index{rand == nullptr
|
||||
? fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, nets.size() - 1)
|
||||
: static_cast<size_t>(rand->randrange(nets.size()))};
|
||||
|
||||
const auto& aux = nets[nets_index];
|
||||
|
||||
CNetAddr addr;
|
||||
|
||||
if (aux.net == Network::NET_INTERNAL) {
|
||||
if (rand == nullptr) {
|
||||
addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
|
||||
} else {
|
||||
const auto v = rand->randbytes(32);
|
||||
addr.SetInternal(std::string{v.begin(), v.end()});
|
||||
}
|
||||
} else if (network == Network::NET_INTERNAL) {
|
||||
net_addr.SetInternal(fuzzed_data_provider.ConsumeBytesAsString(32));
|
||||
} else if (network == Network::NET_ONION) {
|
||||
auto pub_key{fuzzed_data_provider.ConsumeBytes<uint8_t>(ADDR_TORV3_SIZE)};
|
||||
pub_key.resize(ADDR_TORV3_SIZE);
|
||||
const bool ok{net_addr.SetSpecial(OnionToString(pub_key))};
|
||||
assert(ok);
|
||||
return addr;
|
||||
}
|
||||
return net_addr;
|
||||
|
||||
DataStream s;
|
||||
|
||||
s << static_cast<uint8_t>(aux.bip155);
|
||||
|
||||
std::vector<uint8_t> addr_bytes;
|
||||
if (rand == nullptr) {
|
||||
addr_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(aux.len);
|
||||
addr_bytes.resize(aux.len);
|
||||
} else {
|
||||
addr_bytes = rand->randbytes(aux.len);
|
||||
}
|
||||
if (aux.net == NET_IPV6 && addr_bytes[0] == CJDNS_PREFIX) { // Avoid generating IPv6 addresses that look like CJDNS.
|
||||
addr_bytes[0] = 0x55; // Just an arbitrary number, anything != CJDNS_PREFIX would do.
|
||||
}
|
||||
if (aux.net == NET_CJDNS) { // Avoid generating CJDNS addresses that don't start with CJDNS_PREFIX because those are !IsValid().
|
||||
addr_bytes[0] = CJDNS_PREFIX;
|
||||
}
|
||||
s << addr_bytes;
|
||||
|
||||
s >> CAddress::V2_NETWORK(addr);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
|
||||
@@ -24,7 +24,15 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept;
|
||||
/**
|
||||
* Create a CNetAddr. It may have `addr.IsValid() == false`.
|
||||
* @param[in,out] fuzzed_data_provider Take data for the address from this, if `rand` is `nullptr`.
|
||||
* @param[in,out] rand If not nullptr, take data from it instead of from `fuzzed_data_provider`.
|
||||
* Prefer generating addresses using `fuzzed_data_provider` because it is not uniform. Only use
|
||||
* `rand` if `fuzzed_data_provider` is exhausted or its data is needed for other things.
|
||||
* @return a "random" network address.
|
||||
*/
|
||||
CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext* rand = nullptr) noexcept;
|
||||
|
||||
class FuzzedSock : public Sock
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user