From da592f42d7043802a86e482e9973b8b3e4ca7af5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 12 Nov 2026 18:23:47 +0100 Subject: [PATCH 1/2] lexbor: Fix the allocation and move sizes of lexbor_array_obj_t lexbor_array_obj_init() and lexbor_array_obj_expand() allocated 8 times the memory they need on 64-bit platforms, and lexbor_array_obj_delete() moved 8 times the bytes of the remaining entries. This is patch 0025, merged upstream as lexbor/lexbor@f4cbbcd. ext/dom uses such an array as its work list when it converts the parsed tree to libxml2, so gh25118.phpt needs a lower memory_limit to still fail during that conversion. --- NEWS | 2 + ext/dom/tests/gh25118.phpt | 5 +- ext/lexbor/lexbor/core/array_obj.c | 9 ++-- ...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 +- ...url_is_special-to-the-public-API-362.patch | 2 +- ...08-URL-fixed-setters-for-empty-hosts.patch | 2 +- ...ialized-memory-in-the-path-buffer-gr.patch | 2 +- ...URL-containing-empty-host-and-userin.patch | 2 +- ...Percent-encode-the-caret-in-the-path.patch | 2 +- .../0012-URL-added-public-IPv6-parser.patch | 2 +- ...URL-added-public-percent-encoder-API.patch | 2 +- ...uffer-overflow-in-lexbor-contains-pa.patch | 2 +- ...uffer-overflows-in-malformed-decode-.patch | 2 +- ...ointer-in-URLSearchParams-for-delimi.patch | 2 +- ...-Fix-parsing-of-usernames-containing.patch | 2 +- ...initialized-memory-in-IDNA-buffer-gr.patch | 2 +- ...e-path-spaces-before-query-and-fragm.patch | 2 +- ...serialize_fragment-without-a-query-4.patch | 2 +- ...xpose-component-reset-functions.-415.patch | 2 +- ...of-query-and-fragment-after-a-dot-co.patch | 2 +- ...ment-file-drive-paths-hierarchical-4.patch | 2 +- ...output-encoding-for-percent-encoding.patch | 2 +- ...ation-and-move-sizes-in-lexbor_array.patch | 52 +++++++++++++++++++ 28 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch diff --git a/NEWS b/NEWS index a0bce4ed6f43..b129a166df34 100644 --- a/NEWS +++ b/NEWS @@ -57,6 +57,8 @@ PHP NEWS after a dot segment in a path, replacement file drive paths, the output encoding used for percent-encoding, the URLSearchParams tail pointer and fragment serialization without a query. (alexandre-daubois) + . Merge patch lexbor/lexbor@f4cbbcd, fixing lexbor_array_obj_t allocating 8 + times the memory it uses. (Nicolas Grekas) - LibXML: . Clear the libxml last error in libxml_use_internal_errors(false). diff --git a/ext/dom/tests/gh25118.phpt b/ext/dom/tests/gh25118.phpt index 790ae71ef337..a8bc65bb22bb 100644 --- a/ext/dom/tests/gh25118.phpt +++ b/ext/dom/tests/gh25118.phpt @@ -5,13 +5,14 @@ dom --SKIPIF-- --INI-- -memory_limit=32M +memory_limit=26M --FILE--

t

' . str_repeat('', 100000) . '
'; Dom\HTMLDocument::createFromString($html, LIBXML_NOERROR); ?> --EXPECTF-- -Fatal error: Allowed memory size of 33554432 bytes exhausted %S(tried to allocate %d bytes) in %s on line %d +Fatal error: Allowed memory size of 27262976 bytes exhausted %S(tried to allocate %d bytes) in %s on line %d diff --git a/ext/lexbor/lexbor/core/array_obj.c b/ext/lexbor/lexbor/core/array_obj.c index 79a4c3a65a81..8cceaf9fe018 100644 --- a/ext/lexbor/lexbor/core/array_obj.c +++ b/ext/lexbor/lexbor/core/array_obj.c @@ -29,8 +29,7 @@ lexbor_array_obj_init(lexbor_array_obj_t *array, array->size = size; array->struct_size = struct_size; - array->list = lexbor_malloc(sizeof(uint8_t *) - * (array->size * struct_size)); + array->list = lexbor_malloc(array->size * struct_size); if (array->list == NULL) { return LXB_STATUS_ERROR_MEMORY_ALLOCATION; } @@ -77,8 +76,7 @@ lexbor_array_obj_expand(lexbor_array_obj_t *array, size_t up_to) new_size = array->length + up_to; - list = lexbor_realloc(array->list, sizeof(uint8_t *) - * (new_size * array->struct_size)); + list = lexbor_realloc(array->list, new_size * array->struct_size); if (list == NULL) { return NULL; } @@ -170,8 +168,7 @@ lexbor_array_obj_delete(lexbor_array_obj_t *array, size_t begin, size_t length) memmove(&array->list[ begin * array->struct_size ], &array->list[ end_len * array->struct_size ], - sizeof(uint8_t *) - * ((array->length - end_len) * array->struct_size)); + (array->length - end_len) * array->struct_size); array->length -= length; } 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 2cd28f9eaf1d..3a4a2072682a 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 01/24] Expose line and column information for use in PHP +Subject: [PATCH 01/25] 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 4cff1b906f8d..6cfa2fe40607 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 02/24] Track implied added nodes for options use in PHP +Subject: [PATCH 02/25] 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 19b411b2ffcf..df0778c5c8ca 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 03/24] Patch utilities and data structure to be able to +Subject: [PATCH 03/25] 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 67f241a96cf9..aab66f18babc 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 04/24] Remove unused upper case tag static data +Subject: [PATCH 04/25] 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 a36832333e12..441e3f5d155e 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 05/24] Shrink size of static binary search tree +Subject: [PATCH 05/25] 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 fa25a94ef3fa..b9466577c059 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 06/24] Patch out unused CSS style code +Subject: [PATCH 06/25] Patch out unused CSS style code --- source/lexbor/css/rule.h | 2 ++ diff --git a/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch b/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch index 2f939cb69f2c..22ab3caea1f7 100644 --- a/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch +++ b/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.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: Sun, 17 May 2026 22:17:14 +0200 -Subject: [PATCH 07/24] Add lxb_url_is_special() to the public API (#362) +Subject: [PATCH 07/25] Add lxb_url_is_special() to the public API (#362) As https://wiki.php.net/rfc/uri_followup#uri_type_detection relies on this information. --- diff --git a/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch b/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch index d72c82fbdaea..6ffd2f11f1cb 100644 --- a/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch +++ b/ext/lexbor/patches/0008-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 08/24] URL: fixed setters for empty hosts. +Subject: [PATCH 08/25] 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/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch b/ext/lexbor/patches/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch index b2ac318e2ec6..8a6c4a9d2f4f 100644 --- a/ext/lexbor/patches/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch +++ b/ext/lexbor/patches/0009-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 09/24] URL: fixed uninitialized memory in the path buffer +Subject: [PATCH 09/25] 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/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch b/ext/lexbor/patches/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch index 937722a246b5..8f3ed0c5b05a 100644 --- a/ext/lexbor/patches/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch +++ b/ext/lexbor/patches/0010-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 10/24] Fix parsing for URL containing empty host and userinfo +Subject: [PATCH 10/25] 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/0011-Percent-encode-the-caret-in-the-path.patch b/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.patch index 9c1a0708a756..542488d1049f 100644 --- a/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.patch +++ b/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.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: Fri, 10 Jul 2026 22:31:16 +0200 -Subject: [PATCH 11/24] Percent-encode the caret in the path +Subject: [PATCH 11/25] Percent-encode the caret in the path The caret (^) is part of the path percent-encode set: diff --git a/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch b/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch index a4007d2a68f9..d4dccb9b898f 100644 --- a/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch +++ b/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 12 Aug 2026 23:29:20 +0300 -Subject: [PATCH 12/24] URL: added public IPv6 parser. +Subject: [PATCH 12/25] URL: added public IPv6 parser. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch b/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch index 729969019b40..9f44f2cce2f1 100644 --- a/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch +++ b/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 13 Aug 2026 23:29:16 +0300 -Subject: [PATCH 13/24] URL: added public percent-encoder API. +Subject: [PATCH 13/25] URL: added public percent-encoder API. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch b/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch index 373a579e0842..f6fa34ec0609 100644 --- a/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch +++ b/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 5 Jun 2026 22:34:23 +0300 -Subject: [PATCH 14/24] CSS: fixed heap buffer overflow in :lexbor-contains() +Subject: [PATCH 14/25] CSS: fixed heap buffer overflow in :lexbor-contains() parsing. The contains string buffer was allocated by the size of the string diff --git a/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch b/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch index 68756c46547e..3d2abe02550a 100644 --- a/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch +++ b/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 10 Jun 2026 19:50:10 +0300 -Subject: [PATCH 15/24] Encoding: fixed buffer overflows in malformed decode +Subject: [PATCH 15/25] Encoding: fixed buffer overflows in malformed decode replay. Fixed out-of-bounds writes in buffering decoders when replacement output diff --git a/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch b/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch index bc44d2ec9b43..f8e9a9bf1ff2 100644 --- a/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch +++ b/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 5 Jun 2026 21:46:26 +0300 -Subject: [PATCH 16/24] URL: fixed tail pointer in URLSearchParams for +Subject: [PATCH 16/25] URL: fixed tail pointer in URLSearchParams for delimiter-free query. When a query had a single token without '=' or '&' (e.g. "?abc"), the diff --git a/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch b/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch index f6009b9709fa..d5719b2abad9 100644 --- a/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch +++ b/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 31 Jul 2026 20:56:18 +0200 -Subject: [PATCH 17/24] URL: Fix parsing of usernames containing `@` +Subject: [PATCH 17/25] URL: Fix parsing of usernames containing `@` Fixes lexbor/lexbor#399. --- diff --git a/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch b/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch index 23c4cf1acc03..34029e75d97f 100644 --- a/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch +++ b/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Mon, 7 Sep 2026 22:11:39 +0300 -Subject: [PATCH 18/24] Unicode: fixed uninitialized memory in IDNA buffer +Subject: [PATCH 18/25] Unicode: fixed uninitialized memory in IDNA buffer growth. When an IDNA buffer outgrew the stack allocation, the move to the heap diff --git a/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch b/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch index 4d8338521997..8ee829a14b70 100644 --- a/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch +++ b/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.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: Fri, 11 Sep 2026 21:58:45 +0200 -Subject: [PATCH 19/24] URL: encode opaque path spaces before query and +Subject: [PATCH 19/25] URL: encode opaque path spaces before query and fragment. (#405) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 diff --git a/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch b/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch index a0eecf7234be..07f44d7a3fe8 100644 --- a/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch +++ b/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 11 Sep 2026 22:45:33 +0200 -Subject: [PATCH 20/24] URL: Fix `lxb_url_serialize_fragment()` without a query +Subject: [PATCH 20/25] URL: Fix `lxb_url_serialize_fragment()` without a query (#410) The `lxb_url_serialize_fragment()` function checked if the query contained data diff --git a/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch b/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch index deaac125e82e..caed16aba8be 100644 --- a/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch +++ b/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.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: Tue, 22 Sep 2026 22:20:28 +0200 -Subject: [PATCH 21/24] URL: expose component reset functions. (#415) +Subject: [PATCH 21/25] URL: expose component reset functions. (#415) * URL: expose component reset functions. diff --git a/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch b/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch index 4f9607068b9d..62b5607e7092 100644 --- a/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch +++ b/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 26 Sep 2026 18:41:05 +0200 -Subject: [PATCH 22/24] URL: Fix parsing of query and fragment after a +Subject: [PATCH 22/25] URL: Fix parsing of query and fragment after a dot-component in path (#411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 diff --git a/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch b/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch index 2caee494342d..e8562311f164 100644 --- a/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch +++ b/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.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: Mon, 21 Sep 2026 20:01:43 +0200 -Subject: [PATCH 23/24] URL: Keep replacement file drive paths hierarchical +Subject: [PATCH 23/25] URL: Keep replacement file drive paths hierarchical (#423) WHATWG file state (https://url.spec.whatwg.org/#file-state) step 4.4.3.2 resets the path to an empty list. Do not mark it opaque, as that makes subsequent pathname updates silently do nothing. diff --git a/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch b/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch index c0d192d24eaf..3f18aada984b 100644 --- a/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch +++ b/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 24 Sep 2026 15:05:51 +0300 -Subject: [PATCH 24/24] URL: normalize output encoding for percent-encoding. +Subject: [PATCH 24/25] URL: normalize output encoding for percent-encoding. --- source/lexbor/url/url.c | 34 +++++++++++++++++++++++++--------- diff --git a/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch b/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch new file mode 100644 index 000000000000..5744a1eb9fac --- /dev/null +++ b/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nicolas Grekas +Date: Mon, 28 Sep 2026 21:25:27 +0200 +Subject: [PATCH 25/25] Core: fixed allocation and move sizes in + lexbor_array_obj_t. (#428) + +lexbor_array_obj_init() and lexbor_array_obj_expand() multiplied the +number of bytes they need by sizeof(uint8_t *), so they allocated 8 +times too much memory on 64-bit platforms. lexbor_array_obj_delete() +moved 8 times the bytes of the remaining entries too, which only stayed +within bounds thanks to the oversized allocation. + +Added tests for the allocated sizes and for the entries after the last +one being left untouched by lexbor_array_obj_delete(). +--- + source/lexbor/core/array_obj.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/source/lexbor/core/array_obj.c b/source/lexbor/core/array_obj.c +index 79a4c3a..8cceaf9 100644 +--- a/source/lexbor/core/array_obj.c ++++ b/source/lexbor/core/array_obj.c +@@ -29,8 +29,7 @@ lexbor_array_obj_init(lexbor_array_obj_t *array, + array->size = size; + array->struct_size = struct_size; + +- array->list = lexbor_malloc(sizeof(uint8_t *) +- * (array->size * struct_size)); ++ array->list = lexbor_malloc(array->size * struct_size); + if (array->list == NULL) { + return LXB_STATUS_ERROR_MEMORY_ALLOCATION; + } +@@ -77,8 +76,7 @@ lexbor_array_obj_expand(lexbor_array_obj_t *array, size_t up_to) + + new_size = array->length + up_to; + +- list = lexbor_realloc(array->list, sizeof(uint8_t *) +- * (new_size * array->struct_size)); ++ list = lexbor_realloc(array->list, new_size * array->struct_size); + if (list == NULL) { + return NULL; + } +@@ -170,8 +168,7 @@ lexbor_array_obj_delete(lexbor_array_obj_t *array, size_t begin, size_t length) + + memmove(&array->list[ begin * array->struct_size ], + &array->list[ end_len * array->struct_size ], +- sizeof(uint8_t *) +- * ((array->length - end_len) * array->struct_size)); ++ (array->length - end_len) * array->struct_size); + + array->length -= length; + } From d58660f420b3102ab32884d930f6d2055f4d1b8f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 12 Nov 2026 18:26:57 +0100 Subject: [PATCH 2/2] lexbor: Shrink the initial tokenizer pools and mraw cache The HTML tokenizer preallocated 4096 tokens and 4096 token attributes, and each lexbor_mraw_t preallocated 512 entries for its cache of freed blocks, 7 of them per parser. This made Dom\HTMLDocument::createFromString() and setting innerHTML allocate about 1.1MB even for a few bytes of input. The tree builder uses a single token and these pools grow on demand, so start with 16 tokens, 256 attributes and 64 cache entries. This is patch 0026, the pending lexbor/lexbor#427. It allows setting the sizes at build time, which PHP does in config.m4 and config.w32. --- NEWS | 2 + UPGRADING | 4 + ext/lexbor/config.m4 | 2 + ext/lexbor/config.w32 | 2 + ext/lexbor/lexbor/core/mraw.c | 6 +- ext/lexbor/lexbor/html/tokenizer.c | 14 ++- ...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 +- ...url_is_special-to-the-public-API-362.patch | 2 +- ...08-URL-fixed-setters-for-empty-hosts.patch | 2 +- ...ialized-memory-in-the-path-buffer-gr.patch | 2 +- ...URL-containing-empty-host-and-userin.patch | 2 +- ...Percent-encode-the-caret-in-the-path.patch | 2 +- .../0012-URL-added-public-IPv6-parser.patch | 2 +- ...URL-added-public-percent-encoder-API.patch | 2 +- ...uffer-overflow-in-lexbor-contains-pa.patch | 2 +- ...uffer-overflows-in-malformed-decode-.patch | 2 +- ...ointer-in-URLSearchParams-for-delimi.patch | 2 +- ...-Fix-parsing-of-usernames-containing.patch | 2 +- ...initialized-memory-in-IDNA-buffer-gr.patch | 2 +- ...e-path-spaces-before-query-and-fragm.patch | 2 +- ...serialize_fragment-without-a-query-4.patch | 2 +- ...xpose-component-reset-functions.-415.patch | 2 +- ...of-query-and-fragment-after-a-dot-co.patch | 2 +- ...ment-file-drive-paths-hierarchical-4.patch | 2 +- ...output-encoding-for-percent-encoding.patch | 2 +- ...ation-and-move-sizes-in-lexbor_array.patch | 2 +- ...d-initial-sizes-of-tokenizer-pools-a.patch | 87 +++++++++++++++++++ ext/lexbor/patches/README.md | 4 + 33 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 ext/lexbor/patches/0026-Core-HTML-reduced-initial-sizes-of-tokenizer-pools-a.patch diff --git a/NEWS b/NEWS index b129a166df34..4191061f0ccd 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,8 @@ PHP NEWS fragment serialization without a query. (alexandre-daubois) . Merge patch lexbor/lexbor@f4cbbcd, fixing lexbor_array_obj_t allocating 8 times the memory it uses. (Nicolas Grekas) + . Reduced the initial size of the tokenizer pools and of the memory pool + caches, saving about 900KB per HTML parse. (Nicolas Grekas) - LibXML: . Clear the libxml last error in libxml_use_internal_errors(false). diff --git a/UPGRADING b/UPGRADING index d9242ecb3c17..5e95bc667573 100644 --- a/UPGRADING +++ b/UPGRADING @@ -205,6 +205,10 @@ PHP 8.7 UPGRADE NOTES target does not keep is now released at that assignment instead of after the last one. +- DOM: + . Parsing HTML with Dom\HTMLDocument or innerHTML uses much less memory for + small inputs. + - Standard: . Improved performance of strcspn() and strpbrk() when searching longer strings with a single-byte character mask. diff --git a/ext/lexbor/config.m4 b/ext/lexbor/config.m4 index 43123578a727..2c53e0c4f56a 100644 --- a/ext/lexbor/config.m4 +++ b/ext/lexbor/config.m4 @@ -1,4 +1,6 @@ PHP_LEXBOR_CFLAGS="-Wno-unknown-warning-option -Wno-unterminated-string-initialization -I@ext_srcdir@/" +dnl Initial sizes of the tokenizer pools and of the mraw cache, see patch 0026. +PHP_LEXBOR_CFLAGS="$PHP_LEXBOR_CFLAGS -DLXB_HTML_TKZ_TOKEN_POOL_SIZE=16 -DLXB_HTML_TKZ_ATTR_POOL_SIZE=256 -DLEXBOR_MRAW_CACHE_SIZE=64" LEXBOR_DIR="lexbor" AC_DEFINE([HAVE_LEXBOR], [1], [Define to 1 if the PHP extension 'lexbor' is available.]) diff --git a/ext/lexbor/config.w32 b/ext/lexbor/config.w32 index 403c3b98afb5..773b57d0516c 100644 --- a/ext/lexbor/config.w32 +++ b/ext/lexbor/config.w32 @@ -24,6 +24,8 @@ ADD_SOURCES("ext/lexbor/lexbor/tag", "tag.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/unicode", "idna.c unicode.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/url", "url.c","lexbor"); ADD_FLAG("CFLAGS_LEXBOR", "/D LEXBOR_BUILDING /utf-8"); +// Initial sizes of the tokenizer pools and of the mraw cache, see patch 0026. +ADD_FLAG("CFLAGS_LEXBOR", "/D LXB_HTML_TKZ_TOKEN_POOL_SIZE=16 /D LXB_HTML_TKZ_ATTR_POOL_SIZE=256 /D LEXBOR_MRAW_CACHE_SIZE=64"); AC_DEFINE("HAVE_LEXBOR", 1, "Define to 1 if the PHP extension 'lexbor' is available."); diff --git a/ext/lexbor/lexbor/core/mraw.c b/ext/lexbor/lexbor/core/mraw.c index c9904050dd84..30faca63135a 100644 --- a/ext/lexbor/lexbor/core/mraw.c +++ b/ext/lexbor/lexbor/core/mraw.c @@ -11,6 +11,10 @@ #include #endif +#ifndef LEXBOR_MRAW_CACHE_SIZE + #define LEXBOR_MRAW_CACHE_SIZE 64 +#endif + #define lexbor_mraw_meta_set(data, size) \ do { \ @@ -62,7 +66,7 @@ lexbor_mraw_init(lexbor_mraw_t *mraw, size_t chunk_size) /* Cache */ mraw->cache = lexbor_bst_create(); - status = lexbor_bst_init(mraw->cache, 512); + status = lexbor_bst_init(mraw->cache, LEXBOR_MRAW_CACHE_SIZE); if (status) { return status; } diff --git a/ext/lexbor/lexbor/html/tokenizer.c b/ext/lexbor/lexbor/html/tokenizer.c index 1d9f3781255d..219314691564 100644 --- a/ext/lexbor/lexbor/html/tokenizer.c +++ b/ext/lexbor/lexbor/html/tokenizer.c @@ -20,6 +20,14 @@ #define LXB_HTML_TKZ_TEMP_SIZE (4096 * 4) +#ifndef LXB_HTML_TKZ_TOKEN_POOL_SIZE + #define LXB_HTML_TKZ_TOKEN_POOL_SIZE 16 +#endif + +#ifndef LXB_HTML_TKZ_ATTR_POOL_SIZE + #define LXB_HTML_TKZ_ATTR_POOL_SIZE 256 +#endif + enum { LXB_HTML_TOKENIZER_OPT_TAGS_SELF = 1 << 0, @@ -63,14 +71,16 @@ lxb_html_tokenizer_init(lxb_html_tokenizer_t *tkz) tkz->dobj_token = lexbor_dobject_create(); status = lexbor_dobject_init(tkz->dobj_token, - 4096, sizeof(lxb_html_token_t)); + LXB_HTML_TKZ_TOKEN_POOL_SIZE, + sizeof(lxb_html_token_t)); if (status != LXB_STATUS_OK) { return status; } /* Init Token Attributes */ tkz->dobj_token_attr = lexbor_dobject_create(); - status = lexbor_dobject_init(tkz->dobj_token_attr, 4096, + status = lexbor_dobject_init(tkz->dobj_token_attr, + LXB_HTML_TKZ_ATTR_POOL_SIZE, sizeof(lxb_html_token_attr_t)); if (status != LXB_STATUS_OK) { return 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 3a4a2072682a..8a5a13166a78 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 01/25] Expose line and column information for use in PHP +Subject: [PATCH 01/26] 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 6cfa2fe40607..c6f567e9954d 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 02/25] Track implied added nodes for options use in PHP +Subject: [PATCH 02/26] 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 df0778c5c8ca..e2bddc62b70f 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 03/25] Patch utilities and data structure to be able to +Subject: [PATCH 03/26] 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 aab66f18babc..2a4dcdc4e4d9 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 04/25] Remove unused upper case tag static data +Subject: [PATCH 04/26] 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 441e3f5d155e..5ed745307ad6 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 05/25] Shrink size of static binary search tree +Subject: [PATCH 05/26] 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 b9466577c059..58e64a0441cd 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 06/25] Patch out unused CSS style code +Subject: [PATCH 06/26] Patch out unused CSS style code --- source/lexbor/css/rule.h | 2 ++ diff --git a/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch b/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch index 22ab3caea1f7..f8c4b4d21bda 100644 --- a/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.patch +++ b/ext/lexbor/patches/0007-Add-lxb_url_is_special-to-the-public-API-362.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: Sun, 17 May 2026 22:17:14 +0200 -Subject: [PATCH 07/25] Add lxb_url_is_special() to the public API (#362) +Subject: [PATCH 07/26] Add lxb_url_is_special() to the public API (#362) As https://wiki.php.net/rfc/uri_followup#uri_type_detection relies on this information. --- diff --git a/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch b/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch index 6ffd2f11f1cb..869d4b645bbf 100644 --- a/ext/lexbor/patches/0008-URL-fixed-setters-for-empty-hosts.patch +++ b/ext/lexbor/patches/0008-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 08/25] URL: fixed setters for empty hosts. +Subject: [PATCH 08/26] 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/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch b/ext/lexbor/patches/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch index 8a6c4a9d2f4f..3dc3ba50e59e 100644 --- a/ext/lexbor/patches/0009-URL-fixed-uninitialized-memory-in-the-path-buffer-gr.patch +++ b/ext/lexbor/patches/0009-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 09/25] URL: fixed uninitialized memory in the path buffer +Subject: [PATCH 09/26] 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/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch b/ext/lexbor/patches/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch index 8f3ed0c5b05a..23eb758d671d 100644 --- a/ext/lexbor/patches/0010-Fix-parsing-for-URL-containing-empty-host-and-userin.patch +++ b/ext/lexbor/patches/0010-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 10/25] Fix parsing for URL containing empty host and userinfo +Subject: [PATCH 10/26] 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/0011-Percent-encode-the-caret-in-the-path.patch b/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.patch index 542488d1049f..f977e68a12cc 100644 --- a/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.patch +++ b/ext/lexbor/patches/0011-Percent-encode-the-caret-in-the-path.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: Fri, 10 Jul 2026 22:31:16 +0200 -Subject: [PATCH 11/25] Percent-encode the caret in the path +Subject: [PATCH 11/26] Percent-encode the caret in the path The caret (^) is part of the path percent-encode set: diff --git a/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch b/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch index d4dccb9b898f..d633aa5c150a 100644 --- a/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch +++ b/ext/lexbor/patches/0012-URL-added-public-IPv6-parser.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 12 Aug 2026 23:29:20 +0300 -Subject: [PATCH 12/25] URL: added public IPv6 parser. +Subject: [PATCH 12/26] URL: added public IPv6 parser. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch b/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch index 9f44f2cce2f1..5086da0e34e8 100644 --- a/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch +++ b/ext/lexbor/patches/0013-URL-added-public-percent-encoder-API.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 13 Aug 2026 23:29:16 +0300 -Subject: [PATCH 13/25] URL: added public percent-encoder API. +Subject: [PATCH 13/26] URL: added public percent-encoder API. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch b/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch index f6fa34ec0609..8f494632948d 100644 --- a/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch +++ b/ext/lexbor/patches/0014-CSS-fixed-heap-buffer-overflow-in-lexbor-contains-pa.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 5 Jun 2026 22:34:23 +0300 -Subject: [PATCH 14/25] CSS: fixed heap buffer overflow in :lexbor-contains() +Subject: [PATCH 14/26] CSS: fixed heap buffer overflow in :lexbor-contains() parsing. The contains string buffer was allocated by the size of the string diff --git a/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch b/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch index 3d2abe02550a..59731a6d9258 100644 --- a/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch +++ b/ext/lexbor/patches/0015-Encoding-fixed-buffer-overflows-in-malformed-decode-.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 10 Jun 2026 19:50:10 +0300 -Subject: [PATCH 15/25] Encoding: fixed buffer overflows in malformed decode +Subject: [PATCH 15/26] Encoding: fixed buffer overflows in malformed decode replay. Fixed out-of-bounds writes in buffering decoders when replacement output diff --git a/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch b/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch index f8e9a9bf1ff2..67582c73bbd4 100644 --- a/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch +++ b/ext/lexbor/patches/0016-URL-fixed-tail-pointer-in-URLSearchParams-for-delimi.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Fri, 5 Jun 2026 21:46:26 +0300 -Subject: [PATCH 16/25] URL: fixed tail pointer in URLSearchParams for +Subject: [PATCH 16/26] URL: fixed tail pointer in URLSearchParams for delimiter-free query. When a query had a single token without '=' or '&' (e.g. "?abc"), the diff --git a/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch b/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch index d5719b2abad9..9607196ab19b 100644 --- a/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch +++ b/ext/lexbor/patches/0017-URL-Fix-parsing-of-usernames-containing.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 31 Jul 2026 20:56:18 +0200 -Subject: [PATCH 17/25] URL: Fix parsing of usernames containing `@` +Subject: [PATCH 17/26] URL: Fix parsing of usernames containing `@` Fixes lexbor/lexbor#399. --- diff --git a/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch b/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch index 34029e75d97f..791180bb156f 100644 --- a/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch +++ b/ext/lexbor/patches/0018-Unicode-fixed-uninitialized-memory-in-IDNA-buffer-gr.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Mon, 7 Sep 2026 22:11:39 +0300 -Subject: [PATCH 18/25] Unicode: fixed uninitialized memory in IDNA buffer +Subject: [PATCH 18/26] Unicode: fixed uninitialized memory in IDNA buffer growth. When an IDNA buffer outgrew the stack allocation, the move to the heap diff --git a/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch b/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch index 8ee829a14b70..99c116b1dfda 100644 --- a/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.patch +++ b/ext/lexbor/patches/0019-URL-encode-opaque-path-spaces-before-query-and-fragm.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: Fri, 11 Sep 2026 21:58:45 +0200 -Subject: [PATCH 19/25] URL: encode opaque path spaces before query and +Subject: [PATCH 19/26] URL: encode opaque path spaces before query and fragment. (#405) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 diff --git a/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch b/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch index 07f44d7a3fe8..d0224ac3e881 100644 --- a/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch +++ b/ext/lexbor/patches/0020-URL-Fix-lxb_url_serialize_fragment-without-a-query-4.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 11 Sep 2026 22:45:33 +0200 -Subject: [PATCH 20/25] URL: Fix `lxb_url_serialize_fragment()` without a query +Subject: [PATCH 20/26] URL: Fix `lxb_url_serialize_fragment()` without a query (#410) The `lxb_url_serialize_fragment()` function checked if the query contained data diff --git a/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch b/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch index caed16aba8be..43fc3e582355 100644 --- a/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.patch +++ b/ext/lexbor/patches/0021-URL-expose-component-reset-functions.-415.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: Tue, 22 Sep 2026 22:20:28 +0200 -Subject: [PATCH 21/25] URL: expose component reset functions. (#415) +Subject: [PATCH 21/26] URL: expose component reset functions. (#415) * URL: expose component reset functions. diff --git a/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch b/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch index 62b5607e7092..27a0f1c0ae1b 100644 --- a/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch +++ b/ext/lexbor/patches/0022-URL-Fix-parsing-of-query-and-fragment-after-a-dot-co.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 26 Sep 2026 18:41:05 +0200 -Subject: [PATCH 22/25] URL: Fix parsing of query and fragment after a +Subject: [PATCH 22/26] URL: Fix parsing of query and fragment after a dot-component in path (#411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 diff --git a/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch b/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch index e8562311f164..39ff7528aeb3 100644 --- a/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.patch +++ b/ext/lexbor/patches/0023-URL-Keep-replacement-file-drive-paths-hierarchical-4.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: Mon, 21 Sep 2026 20:01:43 +0200 -Subject: [PATCH 23/25] URL: Keep replacement file drive paths hierarchical +Subject: [PATCH 23/26] URL: Keep replacement file drive paths hierarchical (#423) WHATWG file state (https://url.spec.whatwg.org/#file-state) step 4.4.3.2 resets the path to an empty list. Do not mark it opaque, as that makes subsequent pathname updates silently do nothing. diff --git a/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch b/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch index 3f18aada984b..866daef041fc 100644 --- a/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch +++ b/ext/lexbor/patches/0024-URL-normalize-output-encoding-for-percent-encoding.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 24 Sep 2026 15:05:51 +0300 -Subject: [PATCH 24/25] URL: normalize output encoding for percent-encoding. +Subject: [PATCH 24/26] URL: normalize output encoding for percent-encoding. --- source/lexbor/url/url.c | 34 +++++++++++++++++++++++++--------- diff --git a/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch b/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch index 5744a1eb9fac..2b30cc67b4f4 100644 --- a/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch +++ b/ext/lexbor/patches/0025-Core-fixed-allocation-and-move-sizes-in-lexbor_array.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 28 Sep 2026 21:25:27 +0200 -Subject: [PATCH 25/25] Core: fixed allocation and move sizes in +Subject: [PATCH 25/26] Core: fixed allocation and move sizes in lexbor_array_obj_t. (#428) lexbor_array_obj_init() and lexbor_array_obj_expand() multiplied the diff --git a/ext/lexbor/patches/0026-Core-HTML-reduced-initial-sizes-of-tokenizer-pools-a.patch b/ext/lexbor/patches/0026-Core-HTML-reduced-initial-sizes-of-tokenizer-pools-a.patch new file mode 100644 index 000000000000..1a50a90e9169 --- /dev/null +++ b/ext/lexbor/patches/0026-Core-HTML-reduced-initial-sizes-of-tokenizer-pools-a.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nicolas Grekas +Date: Sun, 27 Sep 2026 19:49:58 +0200 +Subject: [PATCH 26/26] Core/HTML: reduced initial sizes of tokenizer pools and + mraw cache. + +The HTML tokenizer preallocated 4096 tokens and 4096 token attributes, +and every lexbor_mraw_t preallocated 512 entries for its cache of freed +blocks. A document parser has 7 mraws, so about 1 MB was allocated +before parsing a single byte. + +The tree builder uses a single token, and all these pools grow on +demand, so they now start with 16 tokens, 256 attributes and 64 cache +entries. + +The initial sizes can be set at build time by defining +LXB_HTML_TKZ_TOKEN_POOL_SIZE, LXB_HTML_TKZ_ATTR_POOL_SIZE and +LEXBOR_MRAW_CACHE_SIZE, e.g. with -D compiler flags. + +This is lexbor/lexbor#427. +--- + source/lexbor/core/mraw.c | 6 +++++- + source/lexbor/html/tokenizer.c | 14 ++++++++++++-- + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/source/lexbor/core/mraw.c b/source/lexbor/core/mraw.c +index c990405..30faca6 100644 +--- a/source/lexbor/core/mraw.c ++++ b/source/lexbor/core/mraw.c +@@ -11,6 +11,10 @@ + #include + #endif + ++#ifndef LEXBOR_MRAW_CACHE_SIZE ++ #define LEXBOR_MRAW_CACHE_SIZE 64 ++#endif ++ + + #define lexbor_mraw_meta_set(data, size) \ + do { \ +@@ -62,7 +66,7 @@ lexbor_mraw_init(lexbor_mraw_t *mraw, size_t chunk_size) + /* Cache */ + mraw->cache = lexbor_bst_create(); + +- status = lexbor_bst_init(mraw->cache, 512); ++ status = lexbor_bst_init(mraw->cache, LEXBOR_MRAW_CACHE_SIZE); + if (status) { + return status; + } +diff --git a/source/lexbor/html/tokenizer.c b/source/lexbor/html/tokenizer.c +index 1d9f378..2193146 100644 +--- a/source/lexbor/html/tokenizer.c ++++ b/source/lexbor/html/tokenizer.c +@@ -20,6 +20,14 @@ + + #define LXB_HTML_TKZ_TEMP_SIZE (4096 * 4) + ++#ifndef LXB_HTML_TKZ_TOKEN_POOL_SIZE ++ #define LXB_HTML_TKZ_TOKEN_POOL_SIZE 16 ++#endif ++ ++#ifndef LXB_HTML_TKZ_ATTR_POOL_SIZE ++ #define LXB_HTML_TKZ_ATTR_POOL_SIZE 256 ++#endif ++ + + enum { + LXB_HTML_TOKENIZER_OPT_TAGS_SELF = 1 << 0, +@@ -63,14 +71,16 @@ lxb_html_tokenizer_init(lxb_html_tokenizer_t *tkz) + + tkz->dobj_token = lexbor_dobject_create(); + status = lexbor_dobject_init(tkz->dobj_token, +- 4096, sizeof(lxb_html_token_t)); ++ LXB_HTML_TKZ_TOKEN_POOL_SIZE, ++ sizeof(lxb_html_token_t)); + if (status != LXB_STATUS_OK) { + return status; + } + + /* Init Token Attributes */ + tkz->dobj_token_attr = lexbor_dobject_create(); +- status = lexbor_dobject_init(tkz->dobj_token_attr, 4096, ++ status = lexbor_dobject_init(tkz->dobj_token_attr, ++ LXB_HTML_TKZ_ATTR_POOL_SIZE, + sizeof(lxb_html_token_attr_t)); + if (status != LXB_STATUS_OK) { + return status; diff --git a/ext/lexbor/patches/README.md b/ext/lexbor/patches/README.md index 6c7b78fd59fa..0af4e2d978c2 100644 --- a/ext/lexbor/patches/README.md +++ b/ext/lexbor/patches/README.md @@ -29,6 +29,10 @@ This contains the following patch files in mailbox format. **Note** for this patch the utilities to generate the tables are also patched. Make sure to apply on a fresh Lexbor clone and run (in `lexbor/utils/encoding`): `python3 single-byte.py` to generate the tables. Also run (in `lexbor/utils/lexbor/html`) `python3 tokenizer_entities_bst.py` to generate the static binary search tree for entities. +* 0026-Core-HTML-reduced-initial-sizes-of-tokenizer-pools-a.patch + The patch of https://github.com/lexbor/lexbor/pull/427, which is not merged yet. It reduces the initial sizes + of the tokenizer pools and of the mraw cache, and allows setting them at build time. + PHP sets them in config.m4 and config.w32, so this patch can be replaced by the upstream commit once it is merged. ## How to apply