diff options
author | Vasil Dimov <vd@FreeBSD.org> | 2023-01-09 14:31:22 +0100 |
---|---|---|
committer | Vasil Dimov <vd@FreeBSD.org> | 2024-01-23 11:49:32 +0100 |
commit | b851c5385d0a0acec4493be1561cea285065d5dc (patch) | |
tree | f63b84cb6d02abe85703c6fb5a350a47a7a67eb2 /src/test/fuzz/util | |
parent | 651fb034d85eb5db561bfd24b74f7271417defa5 (diff) |
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()`.
Diffstat (limited to 'src/test/fuzz/util')
-rw-r--r-- | src/test/fuzz/util/net.cpp | 78 | ||||
-rw-r--r-- | src/test/fuzz/util/net.h | 10 |
2 files changed, 63 insertions, 25 deletions
diff --git a/src/test/fuzz/util/net.cpp b/src/test/fuzz/util/net.cpp index eb0f14ede0..99151bb84d 100644 --- a/src/test/fuzz/util/net.cpp +++ b/src/test/fuzz/util/net.cpp @@ -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; + } + + 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); } - return net_addr; + 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 diff --git a/src/test/fuzz/util/net.h b/src/test/fuzz/util/net.h index 47e4a2fac0..a6c9e23f2e 100644 --- a/src/test/fuzz/util/net.h +++ b/src/test/fuzz/util/net.h @@ -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 { |