From bd82dfa048d05fff3414d46d1c7e31ca392e336c Mon Sep 17 00:00:00 2001 From: Arran Ireland Date: Fri, 28 Nov 2025 14:18:57 +0000 Subject: [PATCH] AK+LibURL: Use AK::IPv4/6 in Host This resolves two FIXME comments. --- AK/IPv6Address.h | 42 ++++++++++++------- Libraries/LibCore/Proxy.h | 6 +-- Libraries/LibIPC/Decoder.cpp | 18 +++++++- Libraries/LibIPC/Decoder.h | 6 +++ Libraries/LibIPC/Encoder.cpp | 13 ++++++ Libraries/LibIPC/Encoder.h | 7 ++++ Libraries/LibURL/Host.cpp | 6 +-- Libraries/LibURL/Host.h | 13 +----- Libraries/LibURL/Parser.cpp | 6 ++- .../MixedContent/AbstractOperations.cpp | 2 +- .../SecureContexts/AbstractOperations.cpp | 12 +++--- 11 files changed, 87 insertions(+), 44 deletions(-) diff --git a/AK/IPv6Address.h b/AK/IPv6Address.h index 679268d04c..b578eca064 100644 --- a/AK/IPv6Address.h +++ b/AK/IPv6Address.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -36,6 +37,15 @@ public: m_data[i] = data[i]; } + constexpr IPv6Address(Array const& data) + { + for (size_t i = 0; i < 8; i++) { + auto piece = data[i]; + m_data[2 * i] = static_cast(piece >> 8); + m_data[(2 * i) + 1] = static_cast(piece & 0xff); + } + } + template T> constexpr IPv6Address(T const&) = delete; // Disable implicit conversion of char const* -> ipv4 -> ipv6 @@ -50,7 +60,7 @@ public: m_data[15] = ipv4_address[3]; } - constexpr u16 operator[](int i) const { return group(i); } + constexpr u16 operator[](size_t i) const { return piece(i); } ErrorOr to_string() const { @@ -68,13 +78,13 @@ public: Optional longest_zero_span_start; int zero_span_length = 0; for (int i = 0; i < 8;) { - if (group(i) != 0) { + if (piece(i) != 0) { i++; continue; } int contiguous_zeros = 1; for (int j = i + 1; j < 8; j++) { - if (group(j) != 0) + if (piece(j) != 0) break; contiguous_zeros++; } @@ -98,9 +108,9 @@ public: } if (i == 0) - TRY(builder.try_appendff("{:x}", group(i))); + TRY(builder.try_appendff("{:x}", piece(i))); else - TRY(builder.try_appendff(":{:x}", group(i))); + TRY(builder.try_appendff(":{:x}", piece(i))); i++; } @@ -186,8 +196,8 @@ public: } in6_addr_t addr {}; - int group = 0; - int have_groups = 0; + int piece = 0; + int have_pieces = 0; bool found_compressed = false; for (size_t i = 0; i < parts.size();) { auto trimmed_part = parts[i].trim_whitespace(); @@ -216,10 +226,10 @@ public: return {}; } - int remaining_parts = parts.size() - empty_parts - have_groups; + int remaining_parts = parts.size() - empty_parts - have_pieces; found_compressed = true; - group = 8 - remaining_parts; - VERIFY(group >= 0); + piece = 8 - remaining_parts; + VERIFY(piece >= 0); i += empty_parts; continue; } else { @@ -229,13 +239,13 @@ public: if (!part.has_value() || part.value() > 0xffff) return {}; - if (++have_groups > 8) + if (++have_pieces > 8) return {}; - VERIFY(group < 8); - addr[group * sizeof(u16)] = (u8)(part.value() >> 8); - addr[group * sizeof(u16) + 1] = (u8)part.value(); - group++; + VERIFY(piece < 8); + addr[piece * sizeof(u16)] = (u8)(part.value() >> 8); + addr[piece * sizeof(u16) + 1] = (u8)part.value(); + piece++; } return IPv6Address(addr); @@ -278,7 +288,7 @@ public: } private: - constexpr u16 group(unsigned i) const + constexpr u16 piece(size_t i) const { VERIFY(i < 8); return ((u16)m_data[i * sizeof(u16)] << 8) | m_data[i * sizeof(u16) + 1]; diff --git a/Libraries/LibCore/Proxy.h b/Libraries/LibCore/Proxy.h index 43fa7540ac..4bc4d07892 100644 --- a/Libraries/LibCore/Proxy.h +++ b/Libraries/LibCore/Proxy.h @@ -20,7 +20,7 @@ struct ProxyData { SOCKS5, } type { Type::Direct }; - u32 host_ipv4 { 0 }; + IPv4Address host_ipv4; int port { 0 }; bool operator==(ProxyData const& other) const = default; @@ -33,9 +33,9 @@ struct ProxyData { proxy_data.type = ProxyData::Type::SOCKS5; - if (!url.host().has_value() || !url.host()->has()) + if (!url.host().has_value() || !url.host()->has()) return Error::from_string_literal("Invalid proxy host, must be an IPv4 address"); - proxy_data.host_ipv4 = url.host()->get(); + proxy_data.host_ipv4 = url.host()->get(); auto port = url.port(); if (!port.has_value()) diff --git a/Libraries/LibIPC/Decoder.cpp b/Libraries/LibIPC/Decoder.cpp index 35d938f032..a76b05f9eb 100644 --- a/Libraries/LibIPC/Decoder.cpp +++ b/Libraries/LibIPC/Decoder.cpp @@ -5,6 +5,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include #include @@ -87,6 +89,20 @@ ErrorOr decode(Decoder& decoder) return AK::UnixDateTime::from_nanoseconds_since_epoch(nanoseconds); } +template<> +ErrorOr decode(Decoder& decoder) +{ + auto ipv4 = TRY(decoder.decode()); + return IPv4Address(ipv4); +} + +template<> +ErrorOr decode(Decoder& decoder) +{ + auto ipv6 = TRY(decoder.decode>()); + return IPv6Address(ipv6); +} + template<> ErrorOr decode(Decoder& decoder) { @@ -153,7 +169,7 @@ template<> ErrorOr decode(Decoder& decoder) { auto type = TRY(decoder.decode()); - auto host_ipv4 = TRY(decoder.decode()); + auto host_ipv4 = IPv4Address(TRY(decoder.decode())); auto port = TRY(decoder.decode()); return Core::ProxyData { type, host_ipv4, port }; diff --git a/Libraries/LibIPC/Decoder.h b/Libraries/LibIPC/Decoder.h index 6d7710110c..e257b45318 100644 --- a/Libraries/LibIPC/Decoder.h +++ b/Libraries/LibIPC/Decoder.h @@ -106,6 +106,12 @@ ErrorOr decode(Decoder&); template<> ErrorOr decode(Decoder&); +template<> +ErrorOr decode(Decoder&); + +template<> +ErrorOr decode(Decoder&); + template<> ErrorOr decode(Decoder&); diff --git a/Libraries/LibIPC/Encoder.cpp b/Libraries/LibIPC/Encoder.cpp index a679356105..1f2e52d0d9 100644 --- a/Libraries/LibIPC/Encoder.cpp +++ b/Libraries/LibIPC/Encoder.cpp @@ -111,6 +111,19 @@ ErrorOr encode(Encoder& encoder, UnixDateTime const& value) return encoder.encode(value.nanoseconds_since_epoch()); } +template<> +ErrorOr encode(Encoder& encoder, IPv4Address const& ipv4) +{ + return encoder.encode(ipv4.to_u32()); +} + +template<> +ErrorOr encode(Encoder& encoder, IPv6Address const& ipv6) +{ + auto const& data = ipv6.to_in6_addr_t(); + return encoder.encode(ReadonlySpan(data)); +} + template<> ErrorOr encode(Encoder& encoder, URL::URL const& value) { diff --git a/Libraries/LibIPC/Encoder.h b/Libraries/LibIPC/Encoder.h index f172341718..eb42fe726f 100644 --- a/Libraries/LibIPC/Encoder.h +++ b/Libraries/LibIPC/Encoder.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,12 @@ ErrorOr encode(Encoder&, AK::Duration const&); template<> ErrorOr encode(Encoder&, UnixDateTime const&); +template<> +ErrorOr encode(Encoder&, IPv4Address const&); + +template<> +ErrorOr encode(Encoder&, IPv6Address const&); + template<> ErrorOr encode(Encoder&, URL::URL const&); diff --git a/Libraries/LibURL/Host.cpp b/Libraries/LibURL/Host.cpp index f3dcad4a24..8995fca163 100644 --- a/Libraries/LibURL/Host.cpp +++ b/Libraries/LibURL/Host.cpp @@ -30,7 +30,7 @@ static String serialize_ipv4_address(IPv4Address address) Array output; // 2. Let n be the value of address. - u32 n = address; + u32 n = address.to_u32(); // 3. For each i in the range 1 to 4, inclusive: for (size_t i = 0; i <= 3; ++i) { @@ -64,7 +64,7 @@ static Optional find_the_ipv6_address_compressed_piece_index(IPv6Address size_t found_size = 0; // 5. For each pieceIndex of address’s pieces’s indices: - for (size_t piece_index = 0; piece_index < address.size(); ++piece_index) { + for (size_t piece_index = 0; piece_index < 8; ++piece_index) { // 1. If address’s pieces[pieceIndex] is not 0: if (address[piece_index] != 0) { // 1. If foundSize is greater than longestSize, then set longestIndex to foundIndex and longestSize to foundSize. @@ -110,7 +110,7 @@ static void serialize_ipv6_address(IPv6Address const& address, StringBuilder& ou auto ignore0 = false; // 4. For each pieceIndex of address’s pieces’s indices: - for (size_t piece_index = 0; piece_index < address.size(); ++piece_index) { + for (size_t piece_index = 0; piece_index < 8; ++piece_index) { // 1. If ignore0 is true and address[pieceIndex] is 0, then continue. if (ignore0 && address[piece_index] == 0) continue; diff --git a/Libraries/LibURL/Host.h b/Libraries/LibURL/Host.h index 84ae874501..a2ae5107b3 100644 --- a/Libraries/LibURL/Host.h +++ b/Libraries/LibURL/Host.h @@ -8,22 +8,13 @@ #pragma once #include +#include +#include #include #include namespace URL { -// https://url.spec.whatwg.org/#concept-ipv4 -// An IPv4 address is a 32-bit unsigned integer that identifies a network address. [RFC791] -// FIXME: It would be nice if this were an AK::IPv4Address -using IPv4Address = u32; - -// https://url.spec.whatwg.org/#concept-ipv6 -// An IPv6 address is a 128-bit unsigned integer that identifies a network address. For the purposes of this standard -// it is represented as a list of eight 16-bit unsigned integers, also known as IPv6 pieces. [RFC4291] -// FIXME: It would be nice if this were an AK::IPv6Address -using IPv6Address = Array; - // https://url.spec.whatwg.org/#concept-host // A host is a domain, an IP address, an opaque host, or an empty host. Typically a host serves as a network address, // but it is sometimes used as opaque identifier in URLs where a network address is not necessary. diff --git a/Libraries/LibURL/Parser.cpp b/Libraries/LibURL/Parser.cpp index 06bb411aeb..8d51543aa0 100644 --- a/Libraries/LibURL/Parser.cpp +++ b/Libraries/LibURL/Parser.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -226,7 +228,7 @@ static Optional parse_ipv4_address(StringView input) } // 13. Return ipv4. - return ipv4; + return IPv4Address(ipv4); } // https://url.spec.whatwg.org/#concept-ipv6-parser @@ -455,7 +457,7 @@ static Optional parse_ipv6_address(StringView input) } // 9. Return address. - return address; + return IPv6Address(address); } // https://url.spec.whatwg.org/#ends-in-a-number-checker diff --git a/Libraries/LibWeb/MixedContent/AbstractOperations.cpp b/Libraries/LibWeb/MixedContent/AbstractOperations.cpp index 0e009f5bb8..93a39736ff 100644 --- a/Libraries/LibWeb/MixedContent/AbstractOperations.cpp +++ b/Libraries/LibWeb/MixedContent/AbstractOperations.cpp @@ -21,7 +21,7 @@ void upgrade_a_mixed_content_request_to_a_potentially_trustworthy_url_if_appropr SecureContexts::is_url_potentially_trustworthy(request.url()) == SecureContexts::Trustworthiness::PotentiallyTrustworthy // 2. request’s URL’s host is an IP address. - || (request.url().host().has_value() && (request.url().host()->has() || request.url().host()->has())) + || (request.url().host().has_value() && (request.url().host()->has() || request.url().host()->has())) // 3. § 4.3 Does settings prohibit mixed security contexts? returns "Does Not Restrict Mixed Security Contents" when applied to request’s client. || does_settings_prohibit_mixed_security_contexts(request.client()) == ProhibitsMixedSecurityContexts::DoesNotRestrictMixedSecurityContexts diff --git a/Libraries/LibWeb/SecureContexts/AbstractOperations.cpp b/Libraries/LibWeb/SecureContexts/AbstractOperations.cpp index a249d91e4d..f88ba4b6f6 100644 --- a/Libraries/LibWeb/SecureContexts/AbstractOperations.cpp +++ b/Libraries/LibWeb/SecureContexts/AbstractOperations.cpp @@ -28,14 +28,12 @@ Trustworthiness is_origin_potentially_trustworthy(URL::Origin const& origin) return Trustworthiness::PotentiallyTrustworthy; // 4. If origin’s host matches one of the CIDR notations 127.0.0.0/8 or ::1/128 [RFC4632], return "Potentially Trustworthy". - // FIXME: This would be nicer if URL::IPv4Address and URL::IPv6Address were instances of AK::IPv4Address and AK::IPv6Address - if (origin.host().has()) { - if ((origin.host().get() & 0xff000000) != 0) + if (origin.host().has()) { + if ((origin.host().get().to_u32() & 0xff000000) != 0) return Trustworthiness::PotentiallyTrustworthy; - } else if (origin.host().has()) { - auto ipv6_address = origin.host().get(); - static constexpr URL::IPv6Address loopback { 0, 0, 0, 0, 0, 0, 0, 1 }; - if (ipv6_address == loopback) + } else if (origin.host().has()) { + auto ipv6_address = origin.host().get(); + if (ipv6_address == IPv6Address::loopback()) return Trustworthiness::PotentiallyTrustworthy; }