diff --git a/core/libs/prx/libSceNKWebKit/Export.cpp b/core/libs/prx/libSceNKWebKit/Export.cpp index b2ecc459d8..8ea08a2e67 100644 --- a/core/libs/prx/libSceNKWebKit/Export.cpp +++ b/core/libs/prx/libSceNKWebKit/Export.cpp @@ -19454,10 +19454,6 @@ int APS5_VABI _ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnO NotImplemented_nid_no_patch(__func__); } -int APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_() { - NotImplemented_nid_no_patch(__func__); -} - int APS5_VABI _ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE() { NotImplemented_nid_no_patch(__func__); } diff --git a/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp b/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp index 1294a580d9..d3f9823f6a 100644 --- a/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp +++ b/core/libs/prx/libSceNKWebKit/include/InventoryExports.hpp @@ -1834,7 +1834,6 @@ int APS5_VABI _ZN3WTF24normalizeLineEndingsToLFEONS_6VectorIhLm0ENS_15CrashOnOve int APS5_VABI _ZN3WTF25activateSignalHandlersForENS_6SignalE(); int APS5_VABI _ZN3WTF26getAndResetAccumulatedLogsEv(); int APS5_VABI _ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE(); -int APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(); int APS5_VABI _ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE(); int APS5_VABI _ZN3WTF28normalizeLineEndingsToNativeEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE(); int APS5_VABI _ZN3WTF30numCodeUnitsInGraphemeClustersENS_10StringViewEj(); diff --git a/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp b/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp index 860b654119..04d520ffb2 100644 --- a/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp +++ b/core/libs/prx/libSceNKWebKit/include/WtfExports.hpp @@ -136,6 +136,7 @@ WTF::LocalTimeOffset APS5_VABI _ZN3WTF24calculateLocalTimeOffsetEdNS_8TimeTypeE( void APS5_VABI _ZN3WTF25addLanguageChangeObserverEPvPFvS0_E(void* context, void (APS5_VABI *observer)(void*)); void APS5_VABI _ZN3WTF25fastDecommitAlignedMemoryEPvm(void*, std::size_t); void APS5_VABI _ZN3WTF25fastMallocDumpMallocStatsEv(); +bool APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(const NKWebKit::WtfAbi::URL* a, const NKWebKit::WtfAbi::URL* b); void APS5_VABI _ZN3WTF27releaseFastMallocFreeMemoryEv(); NKWebKit::WtfAbi::String APS5_VABI _ZN3WTF28displayNameForLanguageLocaleERKNS_6StringE(const NKWebKit::WtfAbi::String* localeName); void APS5_VABI _ZN3WTF28removeLanguageChangeObserverEPv(void* context); diff --git a/core/libs/prx/libSceNKWebKit/src/WtfString.cpp b/core/libs/prx/libSceNKWebKit/src/WtfString.cpp index 32241b1e3d..f6ed222e4b 100644 --- a/core/libs/prx/libSceNKWebKit/src/WtfString.cpp +++ b/core/libs/prx/libSceNKWebKit/src/WtfString.cpp @@ -1116,6 +1116,27 @@ bool APS5_VABI _ZN3WTF31equalIgnoringFragmentIdentifierERKNS_3URLES2_(const URL* return EqualViews(ViewWithoutFragment(first), ViewWithoutFragment(second)); } +bool APS5_VABI _ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_(const URL* a, const URL* b) { + const auto& first = Checked(a); + const auto& second = Checked(b); + unsigned schemeEndA = first.bits >> 6; + unsigned schemeEndB = second.bits >> 6; + if (schemeEndA != schemeEndB) return false; + unsigned hostStartA = HostStart(first); + unsigned hostStartB = HostStart(second); + if (first.hostEnd < hostStartA || second.hostEnd < hostStartB) return false; + unsigned hostLengthA = first.hostEnd - hostStartA; + unsigned hostLengthB = second.hostEnd - hostStartB; + if (hostLengthA != hostLengthB) return false; + auto viewA = View(first.impl); + auto viewB = View(second.impl); + if (schemeEndA > viewA.length || schemeEndB > viewB.length) return false; + if (hostStartA + hostLengthA > viewA.length || hostStartB + hostLengthB > viewB.length) return false; + if (!EqualViews(Slice(viewA, 0, schemeEndA), Slice(viewB, 0, schemeEndB), true)) return false; + if (!EqualViews(Slice(viewA, hostStartA, hostLengthA), Slice(viewB, hostStartB, hostLengthB), true)) return false; + return URLPort(first) == URLPort(second); +} + void APS5_VABI _ZN3WTF3URL10invalidateEv(URL* self) { auto& url = Checked(self); url.bits = 0; diff --git a/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp b/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp index 9add2fce5e..d28828914b 100644 --- a/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp +++ b/core/libs/prx/libSceNKWebKit/tests/Wtf.cpp @@ -804,6 +804,7 @@ const auto URLJavaScript = &_ZNK3WTF3URL20protocolIsJavaScriptEv; const auto URLInvalidate = &_ZN3WTF3URL10invalidateEv; const auto URLEqualIgnoringFragment = &_ZN3WTF31equalIgnoringFragmentIdentifierERKNS_3URLES2_; const auto URLPortAllowed = &_ZN3WTF11portAllowedERKNS_3URLE; +const auto URLProtocolHostAndPortAreEqual = &_ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_; const auto IsJavaScript = &_ZN3WTF20protocolIsJavaScriptENS_10StringViewE; const auto IsHTTP = &_ZN3WTF22protocolIsInHTTPFamilyENS_10StringViewE; const auto JSRealloc = &_ZN3WTF14jsValueReallocEPvm; @@ -1386,6 +1387,127 @@ void TestURLsAndReallocation() { Check(URLPortAllowed(&urlWraparoundPort)); Check(URLPortAllowed(&absent)); Throws([&] { URLPortAllowed(nullptr); }); + { + Check(URLProtocolHostAndPortAreEqual(&url, &url)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlNoFrag)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlDiffQuery)); + Check(URLProtocolHostAndPortAreEqual(&url, &urlDiffPath)); + auto urlUpperSchemeStr = FromUTF8Z(U8("HTTPS://u%20:p%40@example.test:8443/a/b?q=1#frag")); + URL urlUpperScheme = url; + urlUpperScheme.impl = urlUpperSchemeStr.impl; + Check(URLProtocolHostAndPortAreEqual(&url, &urlUpperScheme)); + auto urlUpperHostStr = FromUTF8Z(U8("https://u%20:p%40@EXAMPLE.TEST:8443/a/b?q=1#frag")); + URL urlUpperHost = url; + urlUpperHost.impl = urlUpperHostStr.impl; + Check(URLProtocolHostAndPortAreEqual(&url, &urlUpperHost)); + auto urlHttpStr = FromUTF8Z(U8("http://u%20:p%40@example.test:8443/a/b?q=1#frag")); + URL urlHttp = url; + urlHttp.impl = urlHttpStr.impl; + urlHttp.bits = 1U | 2U | (5U << 3) | (4U << 6); + Check(!URLProtocolHostAndPortAreEqual(&url, &urlHttp)); + Check(!URLProtocolHostAndPortAreEqual(&url, &urlDiffHost)); + auto urlShortHostStr = FromUTF8Z(U8("https://u%20:p%40@ex.test:8443/a/b?q=1#frag")); + URL urlShortHost = url; + urlShortHost.impl = urlShortHostStr.impl; + urlShortHost.hostEnd = 25; + Check(!URLProtocolHostAndPortAreEqual(&url, &urlShortHost)); + auto urlDiffPortStr = FromUTF8Z(U8("https://u%20:p%40@example.test:9443/a/b?q=1#frag")); + URL urlDiffPort = url; + urlDiffPort.impl = urlDiffPortStr.impl; + Check(!URLProtocolHostAndPortAreEqual(&url, &urlDiffPort)); + auto urlPort80Str = FromUTF8Z(U8("http://example.test:80/path")); + URL urlPort80{urlPort80Str.impl, 1U | 2U | (3U << 3) | (4U << 6), 7, 7, 7, 19, 23, 27, 27}; + auto urlNoPortStr = FromUTF8Z(U8("http://example.test/path")); + URL urlNoPort{urlNoPortStr.impl, 1U | 2U | (0U << 3) | (4U << 6), 7, 7, 7, 19, 20, 24, 24}; + Check(!URLProtocolHostAndPortAreEqual(&urlPort80, &urlNoPort)); + auto urlNoPort2Str = FromUTF8Z(U8("http://example.test/other")); + URL urlNoPort2{urlNoPort2Str.impl, 1U | 2U | (0U << 3) | (4U << 6), 7, 7, 7, 19, 20, 25, 25}; + Check(URLProtocolHostAndPortAreEqual(&urlNoPort, &urlNoPort2)); + auto widePort = Create16(u"http://wide.test:8080/path", 26); + URL urlWidePort{widePort.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 26, 26}; + auto widePortMatch = Create16(u"HTTP://WIDE.TEST:8080/other", 27); + URL urlWideMatch{widePortMatch.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePort, &urlWideMatch)); + auto narrowPortStr = FromUTF8Z(U8("http://wide.test:8080/narrow")); + URL urlNarrowPort{narrowPortStr.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 16, 22, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePort, &urlNarrowPort)); + auto urlPort0Str = FromUTF8Z(U8("http://example.test:0/path")); + URL urlPort0{urlPort0Str.impl, 1U | 2U | (2U << 3) | (4U << 6), 7, 7, 7, 19, 22, 26, 26}; + Check(URLProtocolHostAndPortAreEqual(&urlPort0, &urlPort0)); + Check(!URLProtocolHostAndPortAreEqual(&urlPort0, &urlNoPort)); + Check(!URLProtocolHostAndPortAreEqual(&urlPort0, &urlPort80)); + auto urlPortMaxStr = FromUTF8Z(U8("http://example.test:65535/path")); + URL urlPortMax{urlPortMaxStr.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 19, 26, 30, 30}; + Check(URLProtocolHostAndPortAreEqual(&urlPortMax, &urlPortMax)); + Check(!URLProtocolHostAndPortAreEqual(&urlPortMax, &urlPort80)); + auto urlEmptyPortStr = FromUTF8Z(U8("http://example.test:/path")); + URL urlEmptyPort{urlEmptyPortStr.impl, 1U | 2U | (1U << 3) | (4U << 6), 7, 7, 7, 19, 21, 25, 25}; + Check(!URLProtocolHostAndPortAreEqual(&urlEmptyPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlEmptyPort, &urlNoPort)); + auto urlMalformedPortStr = FromUTF8Z(U8("http://example.test:8x/path")); + URL urlMalformedPort{urlMalformedPortStr.impl, 1U | 2U | (3U << 3) | (4U << 6), 7, 7, 7, 19, 23, 27, 27}; + Check(!URLProtocolHostAndPortAreEqual(&urlMalformedPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlMalformedPort, &urlNoPort)); + auto urlOutOfRangePortStr = FromUTF8Z(U8("http://example.test:70000/path")); + URL urlOutOfRangePort{urlOutOfRangePortStr.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 19, 26, 30, 30}; + Check(!URLProtocolHostAndPortAreEqual(&urlOutOfRangePort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlOutOfRangePort, &urlNoPort)); + auto urlPlusPort80Str = FromUTF8Z(U8("http://example.test:+80/path")); + URL urlPlusPort80{urlPlusPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlPlusPort80, &urlPort80)); + Check(!URLProtocolHostAndPortAreEqual(&urlPlusPort80, &urlNoPort)); + auto urlSpacePort80Str = FromUTF8Z(U8("http://example.test: 80 /path")); + URL urlSpacePort80{urlSpacePort80Str.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 19, 25, 29, 29}; + Check(URLProtocolHostAndPortAreEqual(&urlSpacePort80, &urlPort80)); + Check(!URLProtocolHostAndPortAreEqual(&urlSpacePort80, &urlNoPort)); + auto urlTabPort80Str = FromUTF8Z(U8("http://example.test:\t80/path")); + URL urlTabPort80{urlTabPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlTabPort80, &urlPort80)); + auto urlNewlinePort80Str = FromUTF8Z(U8("http://example.test:\n80/path")); + URL urlNewlinePort80{urlNewlinePort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlNewlinePort80, &urlPort80)); + auto urlReturnPort80Str = FromUTF8Z(U8("http://example.test:\r80/path")); + URL urlReturnPort80{urlReturnPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlReturnPort80, &urlPort80)); + auto urlFormFeedPort80Str = FromUTF8Z(U8("http://example.test:\f80/path")); + URL urlFormFeedPort80{urlFormFeedPort80Str.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlFormFeedPort80, &urlPort80)); + auto widePlusPort = Create16(u"http://wide.test:+8080/path", 27); + URL urlWidePlusPort{widePlusPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWidePlusPort, &urlWidePort)); + auto wideSpacePort = Create16(u"http://wide.test: 8080 /path", 28); + URL urlWideSpacePort{wideSpacePort.impl, 1U | 2U | (7U << 3) | (4U << 6), 7, 7, 7, 16, 24, 28, 28}; + Check(URLProtocolHostAndPortAreEqual(&urlWideSpacePort, &urlWidePort)); + auto wideTabPort = Create16(u"http://wide.test:\t8080/path", 27); + URL urlWideTabPort{wideTabPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideTabPort, &urlWidePort)); + auto wideNewlinePort = Create16(u"http://wide.test:\n8080/path", 27); + URL urlWideNewlinePort{wideNewlinePort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideNewlinePort, &urlWidePort)); + auto wideReturnPort = Create16(u"http://wide.test:\r8080/path", 27); + URL urlWideReturnPort{wideReturnPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideReturnPort, &urlWidePort)); + auto wideFormFeedPort = Create16(u"http://wide.test:\f8080/path", 27); + URL urlWideFormFeedPort{wideFormFeedPort.impl, 1U | 2U | (6U << 3) | (4U << 6), 7, 7, 7, 16, 23, 27, 27}; + Check(URLProtocolHostAndPortAreEqual(&urlWideFormFeedPort, &urlWidePort)); + auto urlMinusPortStr = FromUTF8Z(U8("http://example.test:-80/path")); + URL urlMinusPort{urlMinusPortStr.impl, 1U | 2U | (4U << 3) | (4U << 6), 7, 7, 7, 19, 24, 28, 28}; + Check(!URLProtocolHostAndPortAreEqual(&urlMinusPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlMinusPort, &urlNoPort)); + auto urlBarePlusPortStr = FromUTF8Z(U8("http://example.test:+/path")); + URL urlBarePlusPort{urlBarePlusPortStr.impl, 1U | 2U | (2U << 3) | (4U << 6), 7, 7, 7, 19, 22, 26, 26}; + Check(!URLProtocolHostAndPortAreEqual(&urlBarePlusPort, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&urlBarePlusPort, &urlNoPort)); + auto urlPortOutOfBoundsStr = FromUTF8Z(U8("http://example.test:80")); + URL urlPortOutOfBounds{urlPortOutOfBoundsStr.impl, 1U | 2U | (5U << 3) | (4U << 6), 7, 7, 7, 19, 24, 22, 22}; + Check(URLProtocolHostAndPortAreEqual(&urlPortOutOfBounds, &urlNoPort)); + Check(!URLProtocolHostAndPortAreEqual(&urlPortOutOfBounds, &urlPort80)); + Check(URLProtocolHostAndPortAreEqual(&absent, &absent)); + Check(!URLProtocolHostAndPortAreEqual(&url, &absent)); + Check(!URLProtocolHostAndPortAreEqual(&absent, &url)); + Throws([&] { URLProtocolHostAndPortAreEqual(nullptr, &url); }); + Throws([&] { URLProtocolHostAndPortAreEqual(&url, nullptr); }); + } URLInvalidate(&url); Check(url.impl == string.impl && url.bits == 0 && url.userStart == 0 && url.userEnd == 0); Check(url.passwordEnd == 0 && url.hostEnd == 0 && url.pathEnd == 0 && url.pathAfterLastSlash == 0 && url.queryEnd == 0); diff --git a/docs/dev/debt/libSceNKWebKit.md b/docs/dev/debt/libSceNKWebKit.md index 6ab3e588c7..38c89b962d 100644 --- a/docs/dev/debt/libSceNKWebKit.md +++ b/docs/dev/debt/libSceNKWebKit.md @@ -43,7 +43,7 @@ Inventory prose retains historical counts; use the [generated progress report](h - The [revision-pinned identity inventory](https://gist.github.com/kyon-eth/d44995f181e1818977bd38f0e6fc0f34/8afcb14b0707a09b6274ff7f7bcf33ef46cfe2e7) records the module, library, symbol type and NIDs for the declarations in [Export.cpp](../../../core/libs/prx/libSceNKWebKit/Export.cpp); it is a metadata summary rather than independent verification. For the 255 absent from the public catalogue, [per-image ELF records](https://gist.github.com/kyon-eth/147be8dd556e9cced2577ccbed548972/1a659ecfe819e724675991a574a1aebb5fbb48e5) include the raw qualified names, module and library identities, symbol type, values and sizes; the record file SHA-256 is `44bdc4d6073192a8f41b7be359b75364b3d41dbbd11ce649924b8cebdd4ffe51`. Image labels are not authenticated. -- [Additional callable exports](../../../core/libs/prx/libSceNKWebKit/Export.cpp) - 7366 of the 8703 inventory declarations listed below throw through `NotImplemented_nid_no_patch`; signatures and behavior are unverified. The later 13.60-labelled image contains all 8703; 8448 match the public 3.20 catalogue, while 255 are absent and their presence in retail 3.20 is unverified. Per-image records show the latter in a separate 3.20-labelled image, but neither image label is authenticated. Identified names match NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). Data exports need separate analysis. +- [Additional callable exports](../../../core/libs/prx/libSceNKWebKit/Export.cpp) - 7365 of the 8703 inventory declarations listed below throw through `NotImplemented_nid_no_patch`; signatures and behavior are unverified. The later 13.60-labelled image contains all 8703; 8448 match the public 3.20 catalogue, while 255 are absent and their presence in retail 3.20 is unverified. Per-image records show the latter in a separate 3.20-labelled image, but neither image label is authenticated. Identified names match NIDs in the [public symbol database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv) or [supplemental catalog](https://github.com/claimore22/ps5rs/blob/2304be5131221bae0dac24b9767cabffda33f747/data/nids.csv). Data exports need separate analysis. | Name | NID | | --- | --- | @@ -1789,7 +1789,6 @@ Inventory prose retains historical counts; use the [generated progress report](h | `_ZN3WTF25activateSignalHandlersForENS_6SignalE` | `Pyu7Zyt6XUE` | | `_ZN3WTF26getAndResetAccumulatedLogsEv` | `bD3nxh6Om44` | | `_ZN3WTF26normalizeLineEndingsToCRLFEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE` | `oUjgPUMQcao` | -| `_ZN3WTF27protocolHostAndPortAreEqualERKNS_3URLES2_` | `tDDzvLlQ7CE` | | `_ZN3WTF28encodeWithURLEscapeSequencesERKNS_6StringE` | `3DqiPW3mayI` | | `_ZN3WTF28normalizeLineEndingsToNativeEONS_6VectorIhLm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEEE` | `KWwKlT9hDkc` | | `_ZN3WTF30numCodeUnitsInGraphemeClustersENS_10StringViewEj` | `3PZOiy2oZ9w` |