From 8e3ec77e134eaad6519fb9b516ed3ec33df0d2e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sat, 11 Jul 2026 21:30:21 +0200 Subject: [PATCH] ext/uri: Fix GH-22629 WHATWG validation error incorrect with empty host and non-empty userinfo The returned error code (LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS) apparently contradicts the specification: "If atSignSeen is true and buffer is the empty string, host-missing validation error, return failure." --- NEWS | 2 + ext/lexbor/lexbor/url/url.c | 2 +- ...nd-column-information-for-use-in-PHP.patch | 2 +- ...d-added-nodes-for-options-use-in-PHP.patch | 2 +- ...and-data-structure-to-be-able-to-gen.patch | 2 +- ...ve-unused-upper-case-tag-static-data.patch | 2 +- ...nk-size-of-static-binary-search-tree.patch | 2 +- ...0006-Patch-out-unused-CSS-style-code.patch | 2 +- ...07-URL-fixed-setters-for-empty-hosts.patch | 2 +- ...ialized-memory-in-the-path-buffer-gr.patch | 2 +- ...URL-containing-empty-host-and-userin.patch | 48 +++++++++++++++++++ ext/lexbor/patches/update-lexbor.sh | 5 +- .../whatwg/parsing/host_error_empty2.phpt | 2 +- 13 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch diff --git a/NEWS b/NEWS index ecd2c1267112..bf4e4d2bdb50 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-22629 (WHATWG Validation error incorrect with empty host and + non-empty userinfo). (kocsismate) - Zip: . Fixed bug GH-22649 (ZipArchive::setCommentName() and setCommentIndex() diff --git a/ext/lexbor/lexbor/url/url.c b/ext/lexbor/lexbor/url/url.c index b6c0a1e8f65e..19ec23829a23 100644 --- a/ext/lexbor/lexbor/url/url.c +++ b/ext/lexbor/lexbor/url/url.c @@ -1814,7 +1814,7 @@ lxb_url_parse_basic_h(lxb_url_parser_t *parser, lxb_url_t *url, if (at_sign) { if (begin == p || begin == p - 1) { status = lxb_url_log_append(parser, p, - LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS); + LXB_URL_ERROR_TYPE_HOST_MISSING); if (status != LXB_STATUS_OK) { lxb_url_parse_return(orig_data, buf, status); } 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 04136b29f58f..e106b413c22c 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/8] Expose line and column information for use in PHP +Subject: [PATCH 1/9] 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 615655d7f2ec..9e83700198e1 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/8] Track implied added nodes for options use in PHP +Subject: [PATCH 2/9] 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 73c5afa19e12..9ed36fda109d 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,7 +1,7 @@ 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/8] Patch utilities and data structure to be able to generate +Subject: [PATCH 3/9] 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. 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 cc0a65a7cd5c..9e9fcaf8db7a 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/8] Remove unused upper case tag static data +Subject: [PATCH 4/9] 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 b84120bf6c8c..ce3448169395 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/8] Shrink size of static binary search tree +Subject: [PATCH 5/9] 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 196a5a8a62de..c8f485f34807 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/8] Patch out unused CSS style code +Subject: [PATCH 6/9] 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 2592372c6b02..56e206f63d2f 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/8] URL: fixed setters for empty hosts. +Subject: [PATCH 7/9] 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 243053e87fa4..c8cd2332eeff 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/8] URL: fixed uninitialized memory in the path buffer +Subject: [PATCH 8/9] 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 new file mode 100644 index 000000000000..ef7743e61539 --- /dev/null +++ b/ext/lexbor/patches/0009-Fix-parsing-for-URL-containing-empty-host-and-userin.patch @@ -0,0 +1,48 @@ +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 + +The returned error code (LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS) apparently contradicts the specification: + +"If atSignSeen is true and buffer is the empty string, host-missing validation error, return failure." +--- + source/lexbor/url/url.c | 2 +- + test/files/lexbor/url/username_password.ton | 8 +++++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/source/lexbor/url/url.c b/source/lexbor/url/url.c +index b6c0a1e..19ec238 100644 +--- a/source/lexbor/url/url.c ++++ b/source/lexbor/url/url.c +@@ -1814,7 +1814,7 @@ again: + if (at_sign) { + if (begin == p || begin == p - 1) { + status = lxb_url_log_append(parser, p, +- LXB_URL_ERROR_TYPE_INVALID_CREDENTIALS); ++ LXB_URL_ERROR_TYPE_HOST_MISSING); + if (status != LXB_STATUS_OK) { + lxb_url_parse_return(orig_data, buf, status); + } +diff --git a/test/files/lexbor/url/username_password.ton b/test/files/lexbor/url/username_password.ton +index 28a27fd..5a5e63e 100644 +--- a/test/files/lexbor/url/username_password.ton ++++ b/test/files/lexbor/url/username_password.ton +@@ -1,5 +1,5 @@ + [ +- /* Test count: 11 */ ++ /* Test count: 12 */ + /* 1 */ + { + "url": "https://user:password@lexbor.com", +@@ -124,4 +124,10 @@ + "failed": false, + "encoding": "utf-8" + } ++ /* 12 */ ++ { ++ "url": "https://user:pass@", ++ "failed": true, ++ "encoding": "utf-8" ++ } + ] diff --git a/ext/lexbor/patches/update-lexbor.sh b/ext/lexbor/patches/update-lexbor.sh index ae288285453d..92ef8aa58f66 100755 --- a/ext/lexbor/patches/update-lexbor.sh +++ b/ext/lexbor/patches/update-lexbor.sh @@ -15,7 +15,10 @@ git clone "$LEXBOR_REPO" "$LEXBOR_TMP_DIR" (cd "$LEXBOR_TMP_DIR" && git checkout "$LEXBOR_REF") # Apply patches -mapfile -t patches < <(ls "$PATCHES_DIR"/*.patch) +patches=() +for f in "$PATCHES_DIR"/*.patch; do + [ -e "$f" ] && patches+=("$f") +done cd "$LEXBOR_TMP_DIR" for patch in "${patches[@]}"; do if ! git am -3 "$patch"; then diff --git a/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt b/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt index 934185455641..726241674fae 100644 --- a/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt +++ b/ext/uri/tests/whatwg/parsing/host_error_empty2.phpt @@ -11,4 +11,4 @@ try { ?> --EXPECT-- -Uri\WhatWg\InvalidUrlException: The specified URI is malformed +Uri\WhatWg\InvalidUrlException: The specified URI is malformed (HostMissing)