diff --git a/AK/IPv6Address.h b/AK/IPv6Address.h index dd64d9f58a8..fc5c708c7f4 100644 --- a/AK/IPv6Address.h +++ b/AK/IPv6Address.h @@ -111,6 +111,18 @@ public: if (string.is_null()) return {}; + // NOTE: This supports URI syntax (square brackets) for IPv6 addresses. + // See: https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2 + auto const starts_with_bracket = string.starts_with('['); + auto const ends_with_bracket = string.ends_with(']'); + + if (starts_with_bracket || ends_with_bracket) { + if (!starts_with_bracket || !ends_with_bracket) + return {}; + + string = string.substring_view(1, string.length() - 2); + } + auto const parts = string.split_view(':', SplitBehavior::KeepEmpty); if (parts.is_empty()) return {}; diff --git a/Tests/AK/TestIPv6Address.cpp b/Tests/AK/TestIPv6Address.cpp index 41073241647..7d94d8b8e3a 100644 --- a/Tests/AK/TestIPv6Address.cpp +++ b/Tests/AK/TestIPv6Address.cpp @@ -82,6 +82,17 @@ TEST_CASE(should_make_ipv6_address_from_string) EXPECT_EQ(IPv6Address::from_string("102:0:506:708:900::"sv).value(), IPv6Address({ 1, 2, 0, 0, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 })); EXPECT_EQ(IPv6Address::from_string("::304:506:708:90a:b0c:d0e:f10"sv).value(), IPv6Address({ 0, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); EXPECT_EQ(IPv6Address::from_string("102:304::708:90a:b0c:d0e:f10"sv).value(), IPv6Address({ 1, 2, 3, 4, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); + EXPECT_EQ(IPv6Address::from_string("[102:304::708:90a:b0c:d0e:f10]"sv).value(), IPv6Address({ 1, 2, 3, 4, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); + EXPECT_EQ(IPv6Address::from_string("[::304:506:708:90a:b0c:d0e:f10]"sv).value(), IPv6Address({ 0, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); +} + +TEST_CASE(should_not_make_ipv6_address_from_string) +{ + EXPECT_EQ(IPv6Address::from_string("[102:0:506:708:900::10"sv), OptionalNone {}); + EXPECT_EQ(IPv6Address::from_string("102:0:506:708:900::10]"sv), OptionalNone {}); + EXPECT_EQ(IPv6Address::from_string("[::304:506:708:90a:b0c:d0e:f10]]"sv), OptionalNone {}); + EXPECT_EQ(IPv6Address::from_string("[[::304:506:708:90a:b0c:d0e:f10]"sv), OptionalNone {}); + EXPECT_EQ(IPv6Address::from_string("[[::304:506:708:90a:b0c:d0e:f10]]"sv), OptionalNone {}); } TEST_CASE(ipv4_mapped_ipv6)