diff --git a/NEWS b/NEWS index bf4e4d2bdb50..a4f1a24223ec 100644 --- a/NEWS +++ b/NEWS @@ -104,6 +104,8 @@ PHP NEWS - URI: . Fixed behavior of Uri\WhatWg\Url wither methods with regards to empty opaque hosts. (kocsismate) + . Fixed bug GH-22628 (Percent-encoding of caret in WHATWG URL paths is not + performed). (kocsismate) . Fixed bug GH-22629 (WHATWG Validation error incorrect with empty host and non-empty userinfo). (kocsismate) diff --git a/ext/lexbor/lexbor/url/url.c b/ext/lexbor/lexbor/url/url.c index 19ec23829a23..de19239936a1 100644 --- a/ext/lexbor/lexbor/url/url.c +++ b/ext/lexbor/lexbor/url/url.c @@ -159,7 +159,7 @@ static const uint8_t lxb_url_map[256] = LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5b ([) */ LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5c (\) */ LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5d (]) */ - LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5e (^) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5e (^) */ LXB_URL_MAP_UNDEF, /* 0x5f (_) */ LXB_URL_MAP_PATH|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x60 (`) */ LXB_URL_MAP_UNDEF, /* 0x61 (a) */ diff --git a/ext/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch b/ext/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch index e106b413c22c..533598837822 100644 --- a/ext/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch +++ b/ext/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Aug 2023 15:08:59 +0200 -Subject: [PATCH 1/9] Expose line and column information for use in PHP +Subject: [PATCH 01/10] Expose line and column information for use in PHP --- source/lexbor/dom/interfaces/node.h | 2 ++ diff --git a/ext/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch b/ext/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch index 9e83700198e1..8814d5955354 100644 --- a/ext/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch +++ b/ext/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:18:51 +0200 -Subject: [PATCH 2/9] Track implied added nodes for options use in PHP +Subject: [PATCH 02/10] Track implied added nodes for options use in PHP --- source/lexbor/html/tree.h | 3 +++ diff --git a/ext/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch b/ext/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch index 9ed36fda109d..aa4802320491 100644 --- a/ext/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch +++ b/ext/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch @@ -1,8 +1,8 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:57:48 +0200 -Subject: [PATCH 3/9] Patch utilities and data structure to be able to generate - smaller lookup tables +Subject: [PATCH 03/10] Patch utilities and data structure to be able to + generate smaller lookup tables Changed the generation script to check if everything fits in 32-bits. And change the actual field types to 32-bits. This decreases the hash diff --git a/ext/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch b/ext/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch index 9e9fcaf8db7a..1a28b21ccdc5 100644 --- a/ext/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch +++ b/ext/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 29 Nov 2023 21:26:47 +0100 -Subject: [PATCH 4/9] Remove unused upper case tag static data +Subject: [PATCH 04/10] Remove unused upper case tag static data --- source/lexbor/tag/res.h | 2 ++ diff --git a/ext/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch b/ext/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch index ce3448169395..a1dda1fcd112 100644 --- a/ext/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch +++ b/ext/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 29 Nov 2023 21:29:31 +0100 -Subject: [PATCH 5/9] Shrink size of static binary search tree +Subject: [PATCH 05/10] Shrink size of static binary search tree This also makes it more efficient on the data cache. --- diff --git a/ext/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch b/ext/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch index c8f485f34807..57f1e0e92fcb 100644 --- a/ext/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch +++ b/ext/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 7 Jan 2024 21:59:28 +0100 -Subject: [PATCH 6/9] Patch out unused CSS style code +Subject: [PATCH 06/10] Patch out unused CSS style code --- source/lexbor/css/rule.h | 2 ++ diff --git a/ext/lexbor/patches/0007-URL-fixed-setters-for-empty-hosts.patch b/ext/lexbor/patches/0007-URL-fixed-setters-for-empty-hosts.patch index 56e206f63d2f..b55f5aac5894 100644 --- a/ext/lexbor/patches/0007-URL-fixed-setters-for-empty-hosts.patch +++ b/ext/lexbor/patches/0007-URL-fixed-setters-for-empty-hosts.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 26 Jun 2026 18:55:56 +0300 -Subject: [PATCH 7/9] URL: fixed setters for empty hosts. +Subject: [PATCH 07/10] URL: fixed setters for empty hosts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/ext/lexbor/patches/0008-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch b/ext/lexbor/patches/0008-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch index c8cd2332eeff..d967c8ca4eb9 100644 --- a/ext/lexbor/patches/0008-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch +++ b/ext/lexbor/patches/0008-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 5 Jun 2026 22:13:32 +0300 -Subject: [PATCH 8/9] URL: fixed uninitialized memory in the path buffer +Subject: [PATCH 08/10] URL: fixed uninitialized memory in the path buffer growth. When a path was long enough to outgrow the on-stack buffer, the first diff --git a/ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch b/ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch index ef7743e61539..1e7aa4d1087d 100644 --- a/ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch +++ b/ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 9 Jul 2026 21:51:05 +0200 -Subject: [PATCH 9/9] Fix parsing for URL containing empty host and userinfo +Subject: [PATCH 09/10] Fix parsing for URL containing empty host and userinfo The returned error code (LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS) apparently contradicts the specification: diff --git a/ext/lexbor/patches/0010-Percent-encode-the-caret-in-the-path.patch b/ext/lexbor/patches/0010-Percent-encode-the-caret-in-the-path.patch new file mode 100644 index 000000000000..04d91bda68a9 --- /dev/null +++ b/ext/lexbor/patches/0010-Percent-encode-the-caret-in-the-path.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= +Date: Fri, 10 Jul 2026 22:31:16 +0200 +Subject: [PATCH 10/10] Percent-encode the caret in the path + +The caret (^) is part of the path percent-encode set: + +"The path percent-encode set is a percent-encode set consisting of the query percent-encode set and U+003F (?), U+005E (^), U+0060 (`), U+007B ({), and U+007D (})." + +Until now, this character wasn't percent-encoded in the path likely due to a copy-paste error. This is mistake is fixed by adding LXB_URL_MAP_PATH to the lxb_url_map entry for the caret. + +Originally reported at https://github.com/php/php-src/issues/22628 +--- + source/lexbor/url/url.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source/lexbor/url/url.c b/source/lexbor/url/url.c +index 19ec238..de19239 100644 +--- a/source/lexbor/url/url.c ++++ b/source/lexbor/url/url.c +@@ -159,7 +159,7 @@ static const uint8_t lxb_url_map[256] = + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5b ([) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5c (\) */ + LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5d (]) */ +- LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5e (^) */ ++ LXB_URL_MAP_USERINFO|LXB_URL_MAP_PATH|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x5e (^) */ + LXB_URL_MAP_UNDEF, /* 0x5f (_) */ + LXB_URL_MAP_PATH|LXB_URL_MAP_FRAGMENT|LXB_URL_MAP_USERINFO|LXB_URL_MAP_COMPONENT|LXB_URL_MAP_X_WWW_FORM, /* 0x60 (`) */ + LXB_URL_MAP_UNDEF, /* 0x61 (a) */ diff --git a/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt index 59f539124c68..8a168b928820 100644 --- a/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt +++ b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt @@ -15,5 +15,5 @@ var_dump($url2->toAsciiString()); ?> --EXPECT-- string(1) "/" -string(8) "/p^th%23" -string(27) "https://example.com/p^th%23" +string(10) "/p%5Eth%23" +string(29) "https://example.com/p%5Eth%23" diff --git a/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt b/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt index 9419c817fbbd..dd82beeff101 100644 --- a/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt +++ b/ext/uri/tests/whatwg/parsing/path_success_percent_encode_set2.phpt @@ -22,10 +22,10 @@ object(Uri\WhatWg\Url)#%d (%d) { ["port"]=> NULL ["path"]=> - string(28) "/foo%22/%3Cbar%3E/^%7Bbaz%7D" + string(30) "/foo%22/%3Cbar%3E/%5E%7Bbaz%7D" ["query"]=> NULL ["fragment"]=> NULL } -string(47) "https://example.com/foo%22/%3Cbar%3E/^%7Bbaz%7D" +string(49) "https://example.com/foo%22/%3Cbar%3E/%5E%7Bbaz%7D"