Changeset 267837 in webkit
- Timestamp:
- Oct 1, 2020, 10:05:41 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r267833 r267837 1 2020-10-01 Alex Christensen <achristensen@webkit.org> 2 3 Non-special URLs are not idempotent 4 https://bugs.webkit.org/show_bug.cgi?id=215762 5 6 Reviewed by Tim Horton. 7 8 * web-platform-tests/url/a-element-expected.txt: 9 * web-platform-tests/url/a-element-xhtml-expected.txt: 10 * web-platform-tests/url/url-constructor-expected.txt: 11 * web-platform-tests/url/url-setters-expected.txt: 12 1 13 2020-10-01 Youenn Fablet <youenn@apple.com> 2 14 -
trunk/LayoutTests/imported/w3c/web-platform-tests/url/a-element-expected.txt
r267647 r267837 512 512 PASS Parsing: <urn:ietf:rfc:2648> against <about:blank> 513 513 PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank> 514 FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 515 FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 516 FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 517 FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 518 FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 519 FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 520 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 521 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 522 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 523 FAIL Parsing: <a/..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 524 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec://p" 525 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 514 PASS Parsing: <non-spec:/.//> against <about:blank> 515 PASS Parsing: <non-spec:/..//> against <about:blank> 516 PASS Parsing: <non-spec:/a/..//> against <about:blank> 517 PASS Parsing: <non-spec:/.//path> against <about:blank> 518 PASS Parsing: <non-spec:/..//path> against <about:blank> 519 PASS Parsing: <non-spec:/a/..//path> against <about:blank> 520 PASS Parsing: </.//path> against <non-spec:/p> 521 PASS Parsing: </..//path> against <non-spec:/p> 522 PASS Parsing: <..//path> against <non-spec:/p> 523 PASS Parsing: <a/..//path> against <non-spec:/p> 524 PASS Parsing: <> against <non-spec:/..//p> 525 PASS Parsing: <path> against <non-spec:/..//p> 526 526 PASS Parsing: <../path> against <non-spec:/.//p> 527 527 PASS Parsing: <non-special://%E2%80%A0/> against <about:blank> -
trunk/LayoutTests/imported/w3c/web-platform-tests/url/a-element-xhtml-expected.txt
r267647 r267837 512 512 PASS Parsing: <urn:ietf:rfc:2648> against <about:blank> 513 513 PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank> 514 FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 515 FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 516 FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 517 FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 518 FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 519 FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 520 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 521 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 522 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 523 FAIL Parsing: <a/..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 524 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec://p" 525 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 514 PASS Parsing: <non-spec:/.//> against <about:blank> 515 PASS Parsing: <non-spec:/..//> against <about:blank> 516 PASS Parsing: <non-spec:/a/..//> against <about:blank> 517 PASS Parsing: <non-spec:/.//path> against <about:blank> 518 PASS Parsing: <non-spec:/..//path> against <about:blank> 519 PASS Parsing: <non-spec:/a/..//path> against <about:blank> 520 PASS Parsing: </.//path> against <non-spec:/p> 521 PASS Parsing: </..//path> against <non-spec:/p> 522 PASS Parsing: <..//path> against <non-spec:/p> 523 PASS Parsing: <a/..//path> against <non-spec:/p> 524 PASS Parsing: <> against <non-spec:/..//p> 525 PASS Parsing: <path> against <non-spec:/..//p> 526 526 PASS Parsing: <../path> against <non-spec:/.//p> 527 527 PASS Parsing: <non-special://%E2%80%A0/> against <about:blank> -
trunk/LayoutTests/imported/w3c/web-platform-tests/url/url-constructor-expected.txt
r267647 r267837 515 515 PASS Parsing: <urn:ietf:rfc:2648> against <about:blank> 516 516 PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank> 517 FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 518 FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 519 FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec://" 520 FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 521 FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 522 FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 523 FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 524 FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 525 FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 526 FAIL Parsing: <a/..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 527 FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec://p" 528 FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" 517 PASS Parsing: <non-spec:/.//> against <about:blank> 518 PASS Parsing: <non-spec:/..//> against <about:blank> 519 PASS Parsing: <non-spec:/a/..//> against <about:blank> 520 PASS Parsing: <non-spec:/.//path> against <about:blank> 521 PASS Parsing: <non-spec:/..//path> against <about:blank> 522 PASS Parsing: <non-spec:/a/..//path> against <about:blank> 523 PASS Parsing: </.//path> against <non-spec:/p> 524 PASS Parsing: </..//path> against <non-spec:/p> 525 PASS Parsing: <..//path> against <non-spec:/p> 526 PASS Parsing: <a/..//path> against <non-spec:/p> 527 PASS Parsing: <> against <non-spec:/..//p> 528 PASS Parsing: <path> against <non-spec:/..//p> 529 529 PASS Parsing: <../path> against <non-spec:/.//p> 530 530 PASS Parsing: <non-special://%E2%80%A0/> against <about:blank> -
trunk/LayoutTests/imported/w3c/web-platform-tests/url/url-setters-expected.txt
r267647 r267837 430 430 PASS <a>: Setting <non-spec:/.//p>.hostname = 'h' Drop /. from path 431 431 PASS <area>: Setting <non-spec:/.//p>.hostname = 'h' Drop /. from path 432 FAIL URL: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/ /p"433 FAIL <a>: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/ /p"434 FAIL <area>: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/ /p"432 FAIL URL: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/.//p" 433 FAIL <a>: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/.//p" 434 FAIL <area>: Setting <non-spec:/.//p>.hostname = '' assert_equals: expected "non-spec:////p" but got "non-spec:/.//p" 435 435 PASS URL: Setting <http://example.net>.port = '8080' 436 436 PASS <a>: Setting <http://example.net>.port = '8080' … … 544 544 FAIL <a>: Setting <file:///unicorn>.pathname = '//monkey/..//' File URLs and (back)slashes assert_equals: expected "file:///" but got "file://///" 545 545 FAIL <area>: Setting <file:///unicorn>.pathname = '//monkey/..//' File URLs and (back)slashes assert_equals: expected "file:///" but got "file://///" 546 FAIL URL: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 547 FAIL <a>: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 548 FAIL <area>: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 549 FAIL URL: Setting <non-spec:/>.pathname = '/..//p' assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 550 FAIL <a>: Setting <non-spec:/>.pathname = '/..//p' assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 551 FAIL <area>: Setting <non-spec:/>.pathname = '/..//p' assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 546 PASS URL: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path 547 PASS <a>: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path 548 PASS <area>: Setting <non-spec:/>.pathname = '/.//p' Serialize /. in path 549 PASS URL: Setting <non-spec:/>.pathname = '/..//p' 550 PASS <a>: Setting <non-spec:/>.pathname = '/..//p' 551 PASS <area>: Setting <non-spec:/>.pathname = '/..//p' 552 552 FAIL URL: Setting <non-spec:/>.pathname = '//p' assert_equals: expected "non-spec:/.//p" but got "non-spec://p" 553 553 FAIL <a>: Setting <non-spec:/>.pathname = '//p' assert_equals: expected "non-spec:/.//p" but got "non-spec://p" -
trunk/Source/WTF/ChangeLog
r267797 r267837 1 2020-10-01 Alex Christensen <achristensen@webkit.org> 2 3 Non-special URLs are not idempotent 4 https://bugs.webkit.org/show_bug.cgi?id=215762 5 6 Reviewed by Tim Horton. 7 8 https://github.com/whatwg/url/pull/505 added an interesting edge case to the URL serialization: 9 "If url’s host is null, url’s path’s size is greater than 1, and url’s path[0] is the empty string, then append U+002F (/) followed by U+002E (.) to output." 10 The problem was that URLs like "a:/a/..//a" would be parsed into "a://a" with a pathname of "//a" and an empty host. If "a://a" was then reparsed, it would again have an href of "a://a" 11 but its host would be "a" and it would have an empty path. There is consensus that URL parsing should be idempotent, so we need to do something different here. 12 According to https://github.com/whatwg/url/issues/415#issuecomment-419197290 this follows what Edge did (and then subsequently abandoned when they switched to Chromium) 13 to make URL parsing idempotent by adding "/." before the path in the edge case of a URL with a non-special scheme (not http, https, wss, etc.) and a null host and a non-empty path that 14 has an empty first segment. All the members of the URL remain unchanged except the full serialization (href). This is not important in practice, but important in theory. 15 16 Our URL parser tries very hard to use the exact same WTF::String object given as input if it can. However, this step is better implemented as a post-processing step that will almost never happen 17 because otherwise we would have to parse the entire path twice to find out if we need to add "./" or if the "./" that may have already been there needs to stay. This is illustrated with the test URL 18 "t:/.//p/../../../..//x" which does need the "./". 19 20 In the common case, this adds one well-predicted branch to URL parsing, so I expect performance to be unaffected. Since this is such a rare edge case of URLs, I expect no compatibility problems. 21 22 * wtf/URL.cpp: 23 (WTF::URL::pathStart const): 24 * wtf/URL.h: 25 (WTF::URL::pathStart const): Deleted. 26 * wtf/URLParser.cpp: 27 (WTF::URLParser::copyURLPartsUntil): 28 (WTF::URLParser::URLParser): 29 (WTF::URLParser::needsNonSpecialDotSlash const): 30 (WTF::URLParser::addNonSpecialDotSlash): 31 * wtf/URLParser.h: 32 1 33 2020-09-30 Commit Queue <commit-queue@webkit.org> 2 34 -
trunk/Source/WTF/wtf/URL.cpp
r265735 r267837 92 92 93 93 return StringView(m_string).substring(start, end - start + 1); 94 } 95 96 unsigned URL::pathStart() const 97 { 98 unsigned start = m_hostEnd + m_portLength; 99 if (start == m_schemeEnd + 1 100 && start + 1 < m_string.length() 101 && m_string[start] == '/' && m_string[start + 1] == '.') 102 start += 2; 103 return start; 94 104 } 95 105 -
trunk/Source/WTF/wtf/URL.h
r264304 r267837 168 168 WTF_EXPORT_PRIVATE static bool hostIsIPAddress(StringView); 169 169 170 unsigned pathStart() const;170 WTF_EXPORT_PRIVATE unsigned pathStart() const; 171 171 unsigned pathEnd() const; 172 172 unsigned pathAfterLastSlash() const; … … 371 371 } 372 372 373 inline unsigned URL::pathStart() const374 {375 return m_hostEnd + m_portLength;376 }377 378 373 inline unsigned URL::pathEnd() const 379 374 { -
trunk/Source/WTF/wtf/URLParser.cpp
r266399 r267837 1 1 /* 2 * Copyright (C) 2016-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2016-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 808 808 m_url.m_schemeEnd = base.m_schemeEnd; 809 809 } 810 810 811 switch (scheme(StringView(m_asciiBuffer.data(), m_url.m_schemeEnd))) { 811 812 case Scheme::WS: … … 825 826 m_urlIsSpecial = false; 826 827 nonUTF8QueryEncoding = nullptr; 828 auto pathStart = m_url.m_hostEnd + m_url.m_portLength; 829 if (pathStart + 2 < m_asciiBuffer.size() 830 && m_asciiBuffer[pathStart] == '/' 831 && m_asciiBuffer[pathStart + 1] == '.' 832 && m_asciiBuffer[pathStart + 2] == '/') { 833 m_asciiBuffer.remove(pathStart + 1, 2); 834 m_url.m_pathAfterLastSlash = std::max(2u, m_url.m_pathAfterLastSlash) - 2; 835 m_url.m_pathEnd = std::max(2u, m_url.m_pathEnd) - 2; 836 m_url.m_queryEnd = std::max(2u, m_url.m_queryEnd) - 2; 837 } 827 838 return; 828 839 } … … 1076 1087 } 1077 1088 #endif // ASSERT_ENABLED 1089 1090 if (UNLIKELY(needsNonSpecialDotSlash())) 1091 addNonSpecialDotSlash(); 1078 1092 } 1079 1093 … … 2435 2449 } 2436 2450 2451 bool URLParser::needsNonSpecialDotSlash() const 2452 { 2453 auto pathStart = m_url.m_hostEnd + m_url.m_portLength; 2454 return !m_urlIsSpecial 2455 && pathStart == m_url.m_schemeEnd + 1 2456 && pathStart + 1 < m_url.m_string.length() 2457 && m_url.m_string[pathStart] == '/' 2458 && m_url.m_string[pathStart + 1] == '/'; 2459 } 2460 2461 void URLParser::addNonSpecialDotSlash() 2462 { 2463 auto oldPathStart = m_url.m_hostEnd + m_url.m_portLength; 2464 auto& oldString = m_url.m_string; 2465 m_url.m_string = makeString(oldString.substring(0, oldPathStart + 1), "./", oldString.substring(oldPathStart + 1)); 2466 m_url.m_pathAfterLastSlash += 2; 2467 m_url.m_pathEnd += 2; 2468 m_url.m_queryEnd += 2; 2469 } 2470 2437 2471 template<typename CharacterType> Optional<URLParser::LCharBuffer> URLParser::domainToASCII(StringImpl& domain, const CodePointIterator<CharacterType>& iteratorForSyntaxViolationPosition) 2438 2472 { -
trunk/Source/WTF/wtf/URLParser.h
r248546 r267837 115 115 UChar parsedDataView(size_t position); 116 116 117 bool needsNonSpecialDotSlash() const; 118 void addNonSpecialDotSlash(); 119 117 120 using IPv4Address = uint32_t; 118 121 void serializeIPv4(IPv4Address); -
trunk/Tools/ChangeLog
r267831 r267837 1 2020-10-01 Alex Christensen <achristensen@webkit.org> 2 3 Non-special URLs are not idempotent 4 https://bugs.webkit.org/show_bug.cgi?id=215762 5 6 Reviewed by Tim Horton. 7 8 * TestWebKitAPI/Tests/WTF/URLParser.cpp: 9 (TestWebKitAPI::TEST_F): 10 1 11 2020-10-01 Carlos Garcia Campos <cgarcia@igalia.com> 2 12 -
trunk/Tools/TestWebKitAPI/Tests/WTF/URLParser.cpp
r266399 r267837 208 208 { 209 209 checkRelativeURL(urlString, baseString, {"", "", "", "", 0, "", "", "", urlString}); 210 } 211 212 TEST_F(WTF_URLParser, Idempotence) 213 { 214 checkURL("a://", {"a", "", "", "", 0, "", "", "", "a://"}); 215 checkURL("b:///", {"b", "", "", "", 0, "/", "", "", "b:///"}); 216 checkURL("c:/.//", {"c", "", "", "", 0, "//", "", "", "c:/.//"}); 217 checkURL("d:/..//", {"d", "", "", "", 0, "//", "", "", "d:/.//"}); 218 checkURL("e:/../..//", {"e", "", "", "", 0, "//", "", "", "e:/.//"}); 219 checkURL("f:/../../", {"f", "", "", "", 0, "/", "", "", "f:/"}); 220 checkURL("g:/././", {"g", "", "", "", 0, "/", "", "", "g:/"}); 221 checkURL("h:/./../", {"h", "", "", "", 0, "/", "", "", "h:/"}); 222 checkURL("i:/.././", {"i", "", "", "", 0, "/", "", "", "i:/"}); 223 checkURL("j:/./..//", {"j", "", "", "", 0, "//", "", "", "j:/.//"}); 224 checkURL("k:/.././/", {"k", "", "", "", 0, "//", "", "", "k:/.//"}); 225 checkURL("l:/.?", {"l", "", "", "", 0, "/", "", "", "l:/?"}); 226 checkURL("m:/./?", {"m", "", "", "", 0, "/", "", "", "m:/?"}); 227 checkURL("n:/.//?", {"n", "", "", "", 0, "//", "", "", "n:/.//?"}); 228 checkURL("o:/.#", {"o", "", "", "", 0, "/", "", "", "o:/#"}); 229 checkURL("p:/%2e//", {"p", "", "", "", 0, "//", "", "", "p:/.//"}); 230 checkURL("q:/%2e%2e//", {"q", "", "", "", 0, "//", "", "", "q:/.//"}); 231 checkURL("r:/%2e%2e/", {"r", "", "", "", 0, "/", "", "", "r:/"}); 232 checkURL("s:/%2e/", {"s", "", "", "", 0, "/", "", "", "s:/"}); 233 checkURL("t:/.//p/../../../..//x", {"t", "", "", "", 0, "//x", "", "", "t:/.//x"}); 234 checkRelativeURL("../path", "u:/.//p", {"u", "", "", "", 0, "/path", "", "", "u:/path"}); 235 checkURL("v:/.//..", {"v", "", "", "", 0, "/", "", "", "v:/"}); 236 checkURL("w:/.//..//", {"w", "", "", "", 0, "//", "", "", "w:/.//"}); 237 checkURL("x:/.//../a", {"x", "", "", "", 0, "/a", "", "", "x:/a"}); 238 checkURL("http://host/./", {"http", "", "", "host", 0, "/", "", "", "http://host/"}); 239 checkURL("http://host/../", {"http", "", "", "host", 0, "/", "", "", "http://host/"}); 240 checkURL("http://host/.../", {"http", "", "", "host", 0, "/.../", "", "", "http://host/.../"}); 241 checkURL("http://host/..", {"http", "", "", "host", 0, "/", "", "", "http://host/"}); 242 checkURL("http://host/.", {"http", "", "", "host", 0, "/", "", "", "http://host/"}); 210 243 } 211 244
Note:
See TracChangeset
for help on using the changeset viewer.