From 3fb9c3dd29252e3b023f0068fd64e25caffd6843 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <7931-claudiucristea@users.noreply.drupalcode.org> Date: Wed, 12 Mar 2025 19:33:51 +0000 Subject: [PATCH 1/3] Test coverage --- .../Tests/Component/Utility/UrlHelperTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php index 158e626c8213..f7372b438694 100644 --- a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php @@ -386,6 +386,30 @@ public static function providerTestParse() { 'fragment' => 'footer', ], ], + 'Absolute URL with URL as fragment' => [ + 'http://example.com/my/path#http://example.com', + [ + 'fragment' => 'http://example.com', + 'path' => 'http://example.com/my/path', + 'query' => [], + ], + ], + 'Relative URL with URL as fragment' => [ + '/my/path#http://example.com', + [ + 'fragment' => 'http://example.com', + 'path' => 'http://example.com/my/path', + 'query' => [], + ], + ], + 'URL as fragment' => [ + '#http://example.com', + [ + 'fragment' => 'http://example.com', + 'path' => 'http://example.com/my/path', + 'query' => [], + ], + ], ]; } -- GitLab From 6addc663e775cf5ab052c002dff0bb2df9de6148 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <7931-claudiucristea@users.noreply.drupalcode.org> Date: Wed, 12 Mar 2025 19:37:08 +0000 Subject: [PATCH 2/3] Fix expectancy --- core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php index f7372b438694..f22d6ac3118a 100644 --- a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php @@ -398,7 +398,7 @@ public static function providerTestParse() { '/my/path#http://example.com', [ 'fragment' => 'http://example.com', - 'path' => 'http://example.com/my/path', + 'path' => '/my/path', 'query' => [], ], ], @@ -406,7 +406,7 @@ public static function providerTestParse() { '#http://example.com', [ 'fragment' => 'http://example.com', - 'path' => 'http://example.com/my/path', + 'path' => '', 'query' => [], ], ], -- GitLab From 8fa99bb13e5fdf120c8352460117e8333e23f160 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <7931-claudiucristea@users.noreply.drupalcode.org> Date: Wed, 12 Mar 2025 19:52:27 +0000 Subject: [PATCH 3/3] The fix --- core/lib/Drupal/Component/Utility/UrlHelper.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/lib/Drupal/Component/Utility/UrlHelper.php b/core/lib/Drupal/Component/Utility/UrlHelper.php index 9619dcf07031..27dfc945b18f 100644 --- a/core/lib/Drupal/Component/Utility/UrlHelper.php +++ b/core/lib/Drupal/Component/Utility/UrlHelper.php @@ -187,13 +187,18 @@ public static function parse($url) { ]; // External URLs: not using parse_url() here, so we do not have to rebuild - // the scheme, host, and path without having any use for it. - // The URL is considered external if it contains the '://' delimiter. Since - // a URL can also be passed as a query argument, we check if this delimiter - // appears in front of the '?' query argument delimiter. + // the scheme, host, and path without having any use for it. The URL is + // considered external if it contains the '://' delimiter. Since a URL can + // also be passed as a query or fragment argument, check if this delimiter + // appears in front of the '?' and '#' query/fragment argument delimiters. $scheme_delimiter_position = strpos($url, '://'); $query_delimiter_position = strpos($url, '?'); - if ($scheme_delimiter_position !== FALSE && ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position)) { + $fragment_delimiter_position = strpos($url, '#'); + if ( + $scheme_delimiter_position !== FALSE && + ($query_delimiter_position === FALSE || $scheme_delimiter_position < $query_delimiter_position) && + ($fragment_delimiter_position === FALSE || $scheme_delimiter_position < $fragment_delimiter_position) + ) { // Split off the fragment, if any. if (str_contains($url, '#')) { [$url, $options['fragment']] = explode('#', $url, 2); -- GitLab