From e6c775c6d63a1683c9b2ab68d91b335f17e65d55 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Wed, 9 Sep 2026 09:45:19 +0200 Subject: [PATCH 1/2] net: treat RFC 9637 new IPv6 documentation range as invalid --- src/netaddress.cpp | 8 +++++++- src/netaddress.h | 1 + src/test/fuzz/netaddress.cpp | 3 ++- src/test/netbase_tests.cpp | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/netaddress.cpp b/src/netaddress.cpp index fb2c254076a..ffa11f43f68 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -343,6 +343,12 @@ bool CNetAddr::IsRFC3849() const return IsIPv6() && HasPrefix(m_addr, std::array{0x20, 0x01, 0x0D, 0xB8}); } +bool CNetAddr::IsRFC9637() const +{ + return IsIPv6() && HasPrefix(m_addr, std::array{0x3F, 0xFF}) && + (m_addr[2] & 0xF0) == 0x00; +} + bool CNetAddr::IsRFC3964() const { return IsIPv6() && HasPrefix(m_addr, std::array{0x20, 0x02}); @@ -434,7 +440,7 @@ bool CNetAddr::IsValid() const } // documentation IPv6 address - if (IsRFC3849()) + if (IsRFC3849() || IsRFC9637()) return false; if (IsInternal()) diff --git a/src/netaddress.h b/src/netaddress.h index bb452a11275..cfe60a77eb0 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -162,6 +162,7 @@ public: bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) + bool IsRFC9637() const; // IPv6 documentation address (3FFF::/20) bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) bool IsRFC4193() const; // IPv6 unique local (FC00::/7) diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp index fdf4485458a..aeb3a5e7340 100644 --- a/src/test/fuzz/netaddress.cpp +++ b/src/test/fuzz/netaddress.cpp @@ -55,7 +55,7 @@ FUZZ_TARGET(netaddress) assert(net_addr.IsIPv4()); } (void)net_addr.IsRFC2544(); - if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145()) { + if (net_addr.IsRFC3849() || net_addr.IsRFC3964() || net_addr.IsRFC4380() || net_addr.IsRFC4843() || net_addr.IsRFC7343() || net_addr.IsRFC4862() || net_addr.IsRFC6052() || net_addr.IsRFC6145() || net_addr.IsRFC9637()) { assert(net_addr.IsIPv6()); } (void)net_addr.IsRFC3927(); @@ -71,6 +71,7 @@ FUZZ_TARGET(netaddress) (void)net_addr.IsRFC6145(); (void)net_addr.IsRFC6598(); (void)net_addr.IsRFC7343(); + (void)net_addr.IsRFC9637(); if (!net_addr.IsRoutable()) { assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || net_addr.GetNetwork() == Network::NET_INTERNAL); } diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index e376b0cf5a3..e4158578897 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -59,6 +59,9 @@ BOOST_AUTO_TEST_CASE(netbase_properties) BOOST_CHECK(ResolveIP("198.18.0.0").IsRFC2544()); BOOST_CHECK(ResolveIP("198.19.255.255").IsRFC2544()); BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849()); + BOOST_CHECK(ResolveIP("3FFF::").IsRFC9637()); + BOOST_CHECK(ResolveIP("3FFF:0FFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF").IsRFC9637()); + BOOST_CHECK(!ResolveIP("3FFF:1000::").IsRFC9637()); BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927()); BOOST_CHECK(ResolveIP("2002::1").IsRFC3964()); BOOST_CHECK(ResolveIP("FC00::").IsRFC4193()); @@ -73,6 +76,7 @@ BOOST_AUTO_TEST_CASE(netbase_properties) BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable()); BOOST_CHECK(ResolveIP("2001::1").IsRoutable()); BOOST_CHECK(ResolveIP("127.0.0.1").IsValid()); + BOOST_CHECK(!ResolveIP("3FFF::").IsValid()); BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal()); BOOST_CHECK(CreateInternal("bar.com").IsInternal()); From b48a27691ded8c9014be59b190726159b0bff038 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Wed, 9 Sep 2026 13:11:02 +0200 Subject: [PATCH 2/2] fuzz: assert invalid addresses are not routable Co-authored-by: Hodlinator <172445034+hodlinator@users.noreply.github.com> --- src/test/fuzz/netaddress.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp index aeb3a5e7340..91f79edcb04 100644 --- a/src/test/fuzz/netaddress.cpp +++ b/src/test/fuzz/netaddress.cpp @@ -72,7 +72,8 @@ FUZZ_TARGET(netaddress) (void)net_addr.IsRFC6598(); (void)net_addr.IsRFC7343(); (void)net_addr.IsRFC9637(); - if (!net_addr.IsRoutable()) { + const bool routable{net_addr.IsRoutable()}; + if (!routable) { assert(net_addr.GetNetwork() == Network::NET_UNROUTABLE || net_addr.GetNetwork() == Network::NET_INTERNAL); } if (net_addr.IsTor()) { @@ -84,7 +85,9 @@ FUZZ_TARGET(netaddress) if (net_addr.IsCJDNS()) { assert(net_addr.GetNetwork() == Network::NET_CJDNS); } - (void)net_addr.IsValid(); + if (!net_addr.IsValid()) { + assert(!routable); + } (void)net_addr.ToStringAddr(); const CSubNet sub_net{net_addr, fuzzed_data_provider.ConsumeIntegral()};