summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--failed.txt33
-rw-r--r--php-7.0.7-curl.patch15
-rw-r--r--php-8.0.30-icu.patch35
-rw-r--r--php-8.0.30-libxml212.patch681
-rw-r--r--php-8.0.30-pcretests.patch43
-rw-r--r--php-8.0.30-proto.patch341
-rw-r--r--php-cve-2024-11233.patch67
-rw-r--r--php-cve-2024-11234.patch118
-rw-r--r--php-cve-2024-11236.patch117
-rw-r--r--php-cve-2024-8929.patch2301
-rw-r--r--php-cve-2024-8932.patch130
-rw-r--r--php-cve-2025-1217.patch909
-rw-r--r--php-cve-2025-1219.patch1779
-rw-r--r--php-cve-2025-1220.patch153
-rw-r--r--php-cve-2025-1734.patch300
-rw-r--r--php-cve-2025-1735.patch490
-rw-r--r--php-cve-2025-1736.patch241
-rw-r--r--php-cve-2025-1861.patch348
-rw-r--r--php-cve-2025-6491.patch102
-rw-r--r--php-fpm.service2
-rw-r--r--php-ghsa-4w77-75f9-2c8w.patch133
-rw-r--r--php-keyring.gpg1544
-rw-r--r--php.spec122
23 files changed, 8480 insertions, 1524 deletions
diff --git a/failed.txt b/failed.txt
index 5e34040..36f704e 100644
--- a/failed.txt
+++ b/failed.txt
@@ -1,28 +1,21 @@
-===== 8.0.30-9 (2024-09-26)
+===== 8.0.30-14 (2025-07-03)
$ grep -ar 'Tests failed' /var/lib/mock/*/build.log
-/var/lib/mock/scl80el8a/build.log:Tests failed : 3
-/var/lib/mock/scl80el8x/build.log:Tests failed : 3
-/var/lib/mock/scl80el9a/build.log:Tests failed : 2
-/var/lib/mock/scl80el9x/build.log:Tests failed : 2
-/var/lib/mock/scl80fc39a/build.log:Tests failed : 2
-/var/lib/mock/scl80fc39x/build.log:Tests failed : 2
-/var/lib/mock/scl80fc40a/build.log:Tests failed : 3
-/var/lib/mock/scl80fc40x/build.log:Tests failed : 3
-/var/lib/mock/scl80fc41a/build.log:Tests failed : 3
-/var/lib/mock/scl80fc41x/build.log:Tests failed : 3
+/var/lib/mock/scl80el8a/build.log:Tests failed : 0
+/var/lib/mock/scl80el8x/build.log:Tests failed : 0
+/var/lib/mock/scl80el9a/build.log:Tests failed : 0
+/var/lib/mock/scl80el9x/build.log:Tests failed : 0
+/var/lib/mock/scl80el10a/build.log:Tests failed : 0
+/var/lib/mock/scl80el10x/build.log:Tests failed : 0
+/var/lib/mock/scl80fc40a/build.log:Tests failed : 0
+/var/lib/mock/scl80fc40x/build.log:Tests failed : 0
+/var/lib/mock/scl80fc41a/build.log:Tests failed : 0
+/var/lib/mock/scl80fc41x/build.log:Tests failed : 0
+/var/lib/mock/scl80fc42a/build.log:Tests failed : 0
+/var/lib/mock/scl80fc42x/build.log:Tests failed : 0
-el8:
- 3 openssl_error_string() tests [ext/openssl/tests/openssl_error_string_basic.phpt]
- 3 openssl_open() tests [ext/openssl/tests/openssl_open_basic.phpt]
-all:
- 3 openssl_private_decrypt() tests [ext/openssl/tests/openssl_private_decrypt_basic.phpt]
-fc39, fc40, fc41, el9:
- 3 openssl_error_string() tests (OpenSSL >= 3.0) [ext/openssl/tests/openssl_error_string_basic_openssl3.phpt]
-fc40, fc41:
- 3 openssl_x509_parse() tests [ext/openssl/tests/openssl_x509_parse_basic.phpt]
(1) proc_open give erratic test results :(
diff --git a/php-7.0.7-curl.patch b/php-7.0.7-curl.patch
deleted file mode 100644
index 218db98..0000000
--- a/php-7.0.7-curl.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff -up php-7.0.7RC1/ext/curl/interface.c.curltls php-7.0.7RC1/ext/curl/interface.c
---- php-7.0.7RC1/ext/curl/interface.c.curltls 2016-05-10 17:28:33.000000000 +0200
-+++ php-7.0.7RC1/ext/curl/interface.c 2016-05-12 07:43:00.900419946 +0200
-@@ -1257,7 +1257,11 @@ PHP_MINIT_FUNCTION(curl)
-
- #if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */
- REGISTER_CURL_CONSTANT(CURLOPT_LOGIN_OPTIONS);
-+#endif
-
-+#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 (in upstream curl 7.34)
-+ backported in RHEL-7 curl-7.29.0-16.el7 rhbz#1012136
-+ backported in RHEL-6 curl-7.19.7-43.el6 rhbz#1036789 */
- REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_0);
- REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_1);
- REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_2);
diff --git a/php-8.0.30-icu.patch b/php-8.0.30-icu.patch
new file mode 100644
index 0000000..38b7b0f
--- /dev/null
+++ b/php-8.0.30-icu.patch
@@ -0,0 +1,35 @@
+From cc46a4e6b5a413bab3e264c1dcaaf7052f54fbc4 Mon Sep 17 00:00:00 2001
+From: David Carlier <devnexen@gmail.com>
+Date: Sat, 17 Feb 2024 21:38:21 +0000
+Subject: [PATCH] ext/intl: level up c++ runtime std for icu 74 and onwards.
+
+to align with what is required to build icu 74 itself.
+
+Close GH-14002
+---
+ NEWS | 3 +++
+ ext/intl/config.m4 | 11 ++++++++++-
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/ext/intl/config.m4 b/ext/intl/config.m4
+index dd687bcd97de3..48f5147ca7bbf 100644
+--- a/ext/intl/config.m4
++++ b/ext/intl/config.m4
+@@ -83,7 +83,16 @@ if test "$PHP_INTL" != "no"; then
+ breakiterator/codepointiterator_methods.cpp"
+
+ PHP_REQUIRE_CXX()
+- PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX)
++
++ AC_MSG_CHECKING([if intl requires -std=gnu++17])
++ AS_IF([test "$PKG_CONFIG icu-uc --atleast-version=74"],[
++ AC_MSG_RESULT([yes])
++ PHP_CXX_COMPILE_STDCXX(17, mandatory, PHP_INTL_STDCXX)
++ ],[
++ AC_MSG_RESULT([no])
++ PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX)
++ ])
++
+ PHP_INTL_CXX_FLAGS="$INTL_COMMON_FLAGS $PHP_INTL_STDCXX $ICU_CXXFLAGS"
+ case $host_alias in
+ *cygwin*) PHP_INTL_CXX_FLAGS="$PHP_INTL_CXX_FLAGS -D_POSIX_C_SOURCE=200809L"
diff --git a/php-8.0.30-libxml212.patch b/php-8.0.30-libxml212.patch
deleted file mode 100644
index 2fb4cd6..0000000
--- a/php-8.0.30-libxml212.patch
+++ /dev/null
@@ -1,681 +0,0 @@
-From fe8de9dc9194de70b32afd78b89d7cc8ca577b27 Mon Sep 17 00:00:00 2001
-From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
-Date: Fri, 17 Nov 2023 19:45:40 +0100
-Subject: [PATCH 1/4] Fix GH-12702: libxml2 2.12.0 issue building from src
-
-Fixes GH-12702.
-
-Co-authored-by: nono303 <github@nono303.net>
----
- ext/dom/document.c | 1 +
- ext/libxml/php_libxml.h | 1 +
- 2 files changed, 2 insertions(+)
-
-diff --git a/ext/dom/document.c b/ext/dom/document.c
-index 02522b5014..6d1b074085 100644
---- a/ext/dom/document.c
-+++ b/ext/dom/document.c
-@@ -23,6 +23,7 @@
- #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
- #include "php_dom.h"
- #include <libxml/SAX.h>
-+#include <libxml/xmlsave.h>
- #ifdef LIBXML_SCHEMAS_ENABLED
- #include <libxml/relaxng.h>
- #include <libxml/xmlschemas.h>
-diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h
-index d0ce7cec71..02717417a7 100644
---- a/ext/libxml/php_libxml.h
-+++ b/ext/libxml/php_libxml.h
-@@ -35,6 +35,7 @@ extern zend_module_entry libxml_module_entry;
-
- #include "zend_smart_str.h"
- #include <libxml/tree.h>
-+#include <libxml/parser.h>
-
- #define LIBXML_SAVE_NOEMPTYTAG 1<<2
-
---
-2.43.0
-
-From f344d24ed5d723a132f3a793eb2ee8204195067c Mon Sep 17 00:00:00 2001
-From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
-Date: Fri, 1 Dec 2023 18:03:35 +0100
-Subject: [PATCH 2/4] Fix libxml2 2.12 build due to API breaks
-
-See https://github.com/php/php-src/actions/runs/7062192818/job/19225478601
----
- ext/libxml/libxml.c | 14 ++++++++++----
- ext/soap/php_sdl.c | 2 +-
- 2 files changed, 11 insertions(+), 5 deletions(-)
-
-diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
-index 73486ae253..5700492f0a 100644
---- a/ext/libxml/libxml.c
-+++ b/ext/libxml/libxml.c
-@@ -481,7 +481,11 @@ static void _php_libxml_free_error(void *ptr)
- xmlResetError((xmlErrorPtr) ptr);
- }
-
--static void _php_list_set_error_structure(xmlErrorPtr error, const char *msg)
-+#if LIBXML_VERSION >= 21200
-+static void _php_list_set_error_structure(const xmlError *error, const char *msg)
-+#else
-+static void _php_list_set_error_structure(xmlError *error, const char *msg)
-+#endif
- {
- xmlError error_copy;
- int ret;
-@@ -732,7 +736,11 @@ PHP_LIBXML_API void php_libxml_ctx_warning(void *ctx, const char *msg, ...)
- va_end(args);
- }
-
-+#if LIBXML_VERSION >= 21200
-+PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, const xmlError *error)
-+#else
- PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, xmlErrorPtr error)
-+#endif
- {
- _php_list_set_error_structure(error, NULL);
-
-@@ -1035,11 +1043,9 @@ PHP_FUNCTION(libxml_use_internal_errors)
- /* {{{ Retrieve last error from libxml */
- PHP_FUNCTION(libxml_get_last_error)
- {
-- xmlErrorPtr error;
--
- ZEND_PARSE_PARAMETERS_NONE();
-
-- error = xmlGetLastError();
-+ const xmlError *error = xmlGetLastError();
-
- if (error) {
- object_init_ex(return_value, libxmlerror_class_entry);
-diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
-index e5e7f2f955..6060f63450 100644
---- a/ext/soap/php_sdl.c
-+++ b/ext/soap/php_sdl.c
-@@ -331,7 +331,7 @@ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
- sdl_restore_uri_credentials(ctx);
-
- if (!wsdl) {
-- xmlErrorPtr xmlErrorPtr = xmlGetLastError();
-+ const xmlError *xmlErrorPtr = xmlGetLastError();
-
- if (xmlErrorPtr) {
- soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
---
-2.43.0
-
-From 8e1a378b5e4d01c99c4654114e4cf4c0953b5b5a Mon Sep 17 00:00:00 2001
-From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
-Date: Sat, 29 Apr 2023 21:07:50 +0200
-Subject: [PATCH 3/4] Fix GH-11160: Few tests failed building with new libxml
- 2.11.0
-
-It's possible to categorise the failures into 2 categories:
- - Changed error message. In this case we either duplicate the test and
- modify the error message. Or if the change in error message is
- small, we use the EXPECTF matchers to make the test compatible with both
- old and new versions of libxml2.
- - Missing warnings. This is caused by a change in libxml2 where the
- parser started using SAX APIs internally [1]. In this case the
- error_type passed to php_libxml_internal_error_handler() changed from
- PHP_LIBXML_ERROR to PHP_LIBXML_CTX_WARNING because it internally
- started to use the SAX handlers instead of the generic handlers.
- However, for the SAX handlers the current input stack is empty, so
- nothing is actually printed. I fixed this by falling back to a
- regular warning without a filename & line number reference, which
- mimicks the old behaviour. Furthermore, this change now also shows
- an additional warning in a test which was previously hidden.
-
-[1] https://gitlab.gnome.org/GNOME/libxml2/-/commit/9a82b94a94bd310db426edd453b0f38c6c8f69f5
-
-Closes GH-11162.
----
- .../DOMDocument_loadXML_error2_gte2_11.phpt | 34 +++++++
- ...> DOMDocument_loadXML_error2_pre2_11.phpt} | 4 +
- .../DOMDocument_load_error2_gte2_11.phpt | 34 +++++++
- ...t => DOMDocument_load_error2_pre2_11.phpt} | 4 +
- ext/libxml/libxml.c | 2 +
- ext/libxml/tests/bug61367-read_2.phpt | 2 +-
- .../tests/libxml_disable_entity_loader_2.phpt | 2 +-
- ...set_external_entity_loader_variation2.phpt | 2 +
- ext/xml/tests/bug26614_libxml_gte2_11.phpt | 95 +++++++++++++++++++
- ...bxml.phpt => bug26614_libxml_pre2_11.phpt} | 1 +
- 10 files changed, 178 insertions(+), 2 deletions(-)
- create mode 100644 ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
- rename ext/dom/tests/{DOMDocument_loadXML_error2.phpt => DOMDocument_loadXML_error2_pre2_11.phpt} (90%)
- create mode 100644 ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
- rename ext/dom/tests/{DOMDocument_load_error2.phpt => DOMDocument_load_error2_pre2_11.phpt} (90%)
- create mode 100644 ext/xml/tests/bug26614_libxml_gte2_11.phpt
- rename ext/xml/tests/{bug26614_libxml.phpt => bug26614_libxml_pre2_11.phpt} (96%)
-
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
-new file mode 100644
-index 0000000000..ff5ceb3fbe
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
-@@ -0,0 +1,34 @@
-+--TEST--
-+Test DOMDocument::loadXML() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects attributes values not closed between " or '
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--INI--
-+assert.bail=true
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed2.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentloadxml_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): Opening and ending tag mismatch: books line 3 and book in Entity, line: 7 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): Extra content at the end of the document in Entity, line: 8 in %s on line %d
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error2.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
-similarity index 90%
-rename from ext/dom/tests/DOMDocument_loadXML_error2.phpt
-rename to ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
-index 6d56a317ed..0e36d20905 100644
---- a/ext/dom/tests/DOMDocument_loadXML_error2.phpt
-+++ b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
-@@ -1,5 +1,9 @@
- --TEST--
- Test DOMDocument::loadXML() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
-+?>
- --DESCRIPTION--
- This test verifies the method detects attributes values not closed between " or '
- Environment variables used in the test:
-diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
-new file mode 100644
-index 0000000000..32b6bf1611
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
-@@ -0,0 +1,34 @@
-+--TEST--
-+Test DOMDocument::load() detects not-well formed
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects attributes values not closed between " or '
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--INI--
-+assert.bail=true
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed2.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentload_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d
-+
-+Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d
-+
-+Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d
-+
-+Warning: DOMDocument::load(): Opening and ending tag mismatch: books line 3 and book in %s on line %d
-+
-+Warning: DOMDocument::load(): Extra content at the end of the document in %s on line %d
-diff --git a/ext/dom/tests/DOMDocument_load_error2.phpt b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
-similarity index 90%
-rename from ext/dom/tests/DOMDocument_load_error2.phpt
-rename to ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
-index f450cf1654..b97fff9d2f 100644
---- a/ext/dom/tests/DOMDocument_load_error2.phpt
-+++ b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
-@@ -1,5 +1,9 @@
- --TEST--
- Test DOMDocument::load() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
-+?>
- --DESCRIPTION--
- This test verifies the method detects attributes values not closed between " or '
- Environment variables used in the test:
-diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
-index 5700492f0a..554fcc34ff 100644
---- a/ext/libxml/libxml.c
-+++ b/ext/libxml/libxml.c
-@@ -529,6 +529,8 @@ static void php_libxml_ctx_error_level(int level, void *ctx, const char *msg)
- } else {
- php_error_docref(NULL, level, "%s in Entity, line: %d", msg, parser->input->line);
- }
-+ } else {
-+ php_error_docref(NULL, E_WARNING, "%s", msg);
- }
- }
-
-diff --git a/ext/libxml/tests/bug61367-read_2.phpt b/ext/libxml/tests/bug61367-read_2.phpt
-index ed6576aa75..b935261cb2 100644
---- a/ext/libxml/tests/bug61367-read_2.phpt
-+++ b/ext/libxml/tests/bug61367-read_2.phpt
-@@ -55,6 +55,6 @@ bool(true)
- int(4)
- bool(true)
-
--Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d
-+Warning: DOMDocument::loadXML(): %Sfailed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d
-
- Warning: Attempt to read property "nodeValue" on null in %s on line %d
-diff --git a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
-index caa7356ad3..d90f909ac2 100644
---- a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
-+++ b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
-@@ -38,6 +38,6 @@ bool(true)
- Deprecated: Function libxml_disable_entity_loader() is deprecated in %s on line %d
- bool(false)
-
--Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "%s" in %s on line %d
-+Warning: DOMDocument::loadXML(): %Sfailed to load external entity "%s" in %s on line %d
- bool(true)
- Done
-diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
-index 87894bcb91..ddaf9bfa50 100644
---- a/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
-+++ b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
-@@ -39,6 +39,8 @@ echo "Done.\n";
- string(10) "-//FOO/BAR"
- string(%d) "%sfoobar.dtd"
-
-+Warning: DOMDocument::validate(): Failed to load external entity "-//FOO/BAR" in %s on line %d
-+
- Warning: DOMDocument::validate(): Could not load the external subset "foobar.dtd" in %s on line %d
- bool(false)
- bool(true)
-diff --git a/ext/xml/tests/bug26614_libxml_gte2_11.phpt b/ext/xml/tests/bug26614_libxml_gte2_11.phpt
-new file mode 100644
-index 0000000000..9a81b67686
---- /dev/null
-+++ b/ext/xml/tests/bug26614_libxml_gte2_11.phpt
-@@ -0,0 +1,95 @@
-+--TEST--
-+Bug #26614 (CDATA sections skipped on line count)
-+--EXTENSIONS--
-+xml
-+--SKIPIF--
-+<?php
-+if (!defined("LIBXML_VERSION")) die('skip libxml2 test');
-+if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
-+?>
-+--FILE--
-+<?php
-+/*
-+this test works fine with Expat but fails with libxml
-+which we now use as default
-+
-+further investigation has shown that not only line count
-+is skipped on CDATA sections but that libxml does also
-+show different column numbers and byte positions depending
-+on context and in opposition to what one would expect to
-+see and what good old Expat reported just fine ...
-+*/
-+
-+$xmls = array();
-+
-+// Case 1: CDATA Sections
-+$xmls["CDATA"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
-+<data>
-+<![CDATA[
-+multi
-+line
-+CDATA
-+block
-+]]>
-+</data>';
-+
-+// Case 2: replace some characters so that we get comments instead
-+$xmls["Comment"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
-+<data>
-+<!-- ATA[
-+multi
-+line
-+CDATA
-+block
-+-->
-+</data>';
-+
-+// Case 3: replace even more characters so that only textual data is left
-+$xmls["Text"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
-+<data>
-+-!-- ATA[
-+multi
-+line
-+CDATA
-+block
-+---
-+</data>';
-+
-+function startElement($parser, $name, $attrs) {
-+ printf("<$name> at line %d, col %d (byte %d)\n",
-+ xml_get_current_line_number($parser),
-+ xml_get_current_column_number($parser),
-+ xml_get_current_byte_index($parser));
-+}
-+
-+function endElement($parser, $name) {
-+ printf("</$name> at line %d, col %d (byte %d)\n",
-+ xml_get_current_line_number($parser),
-+ xml_get_current_column_number($parser),
-+ xml_get_current_byte_index($parser));
-+}
-+
-+function characterData($parser, $data) {
-+ // dummy
-+}
-+
-+foreach ($xmls as $desc => $xml) {
-+ echo "$desc\n";
-+ $xml_parser = xml_parser_create();
-+ xml_set_element_handler($xml_parser, "startElement", "endElement");
-+ xml_set_character_data_handler($xml_parser, "characterData");
-+ if (!xml_parse($xml_parser, $xml, true))
-+ echo "Error: ".xml_error_string(xml_get_error_code($xml_parser))."\n";
-+ xml_parser_free($xml_parser);
-+}
-+?>
-+--EXPECTF--
-+CDATA
-+<DATA> at line 2, col %d (byte 50)
-+</DATA> at line 9, col %d (byte 96)
-+Comment
-+<DATA> at line 2, col %d (byte 50)
-+</DATA> at line 9, col %d (byte 96)
-+Text
-+<DATA> at line 2, col %d (byte 50)
-+</DATA> at line 9, col %d (byte 96)
-diff --git a/ext/xml/tests/bug26614_libxml.phpt b/ext/xml/tests/bug26614_libxml_pre2_11.phpt
-similarity index 96%
-rename from ext/xml/tests/bug26614_libxml.phpt
-rename to ext/xml/tests/bug26614_libxml_pre2_11.phpt
-index b6c0b87581..90283850d2 100644
---- a/ext/xml/tests/bug26614_libxml.phpt
-+++ b/ext/xml/tests/bug26614_libxml_pre2_11.phpt
-@@ -4,6 +4,7 @@ Bug #26614 (CDATA sections skipped on line count)
- <?php
- require_once("skipif.inc");
- if (!defined("LIBXML_VERSION")) die('skip libxml2 test');
-+if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
- ?>
- --FILE--
- <?php
---
-2.43.0
-
-From 09f3b08ff356e9408dce778567e7592af6b970f2 Mon Sep 17 00:00:00 2001
-From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
-Date: Wed, 29 Nov 2023 20:49:29 +0100
-Subject: [PATCH 4/4] Test fixes for libxml2 2.12.0
-
----
- ext/dom/tests/DOMDocument_loadXML_error1.phpt | 4 +++
- .../DOMDocument_loadXML_error1_gte2_12.phpt | 26 ++++++++++++++++
- .../DOMDocument_loadXML_error2_gte2_11.phpt | 2 +-
- .../DOMDocument_loadXML_error2_gte2_12.phpt | 30 +++++++++++++++++++
- ext/dom/tests/DOMDocument_load_error1.phpt | 4 +++
- .../DOMDocument_load_error1_gte2_12.phpt | 26 ++++++++++++++++
- .../DOMDocument_load_error2_gte2_11.phpt | 2 +-
- .../DOMDocument_load_error2_gte2_12.phpt | 30 +++++++++++++++++++
- ext/xml/tests/bug81351.phpt | 4 +--
- ext/xml/tests/xml_error_string_basic.phpt | 6 ++--
- 10 files changed, 127 insertions(+), 7 deletions(-)
- create mode 100644 ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt
- create mode 100644 ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt
- create mode 100644 ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt
- create mode 100644 ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt
-
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error1.phpt b/ext/dom/tests/DOMDocument_loadXML_error1.phpt
-index 4d3b81db79..0549d67630 100644
---- a/ext/dom/tests/DOMDocument_loadXML_error1.phpt
-+++ b/ext/dom/tests/DOMDocument_loadXML_error1.phpt
-@@ -1,5 +1,9 @@
- --TEST--
- Test DOMDocument::loadXML() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version < 2.12');
-+?>
- --DESCRIPTION--
- This test verifies the method detects an opening and ending tag mismatch
- Environment variables used in the test:
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt b/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt
-new file mode 100644
-index 0000000000..e1ded0ffad
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt
-@@ -0,0 +1,26 @@
-+--TEST--
-+Test DOMDocument::loadXML() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21200) die('skip libxml2 test variant for version >= 2.12');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects an opening and ending tag mismatch
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentloadxml_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::load%r(XML){0,1}%r(): Opening and ending tag mismatch: title line 5 and book %s
-+
-+Warning: DOMDocument::load%r(XML){0,1}%r(): %rexpected '>'|Opening and ending tag mismatch: book line (4|5) and books%r %s
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
-index ff5ceb3fbe..f52d334813 100644
---- a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
-+++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
-@@ -2,7 +2,7 @@
- Test DOMDocument::loadXML() detects not-well formed XML
- --SKIPIF--
- <?php
--if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
-+if (LIBXML_VERSION < 21100 || LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version >= 2.11 && <= 2.12');
- ?>
- --DESCRIPTION--
- This test verifies the method detects attributes values not closed between " or '
-diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt
-new file mode 100644
-index 0000000000..6a3ff5841f
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt
-@@ -0,0 +1,30 @@
-+--TEST--
-+Test DOMDocument::loadXML() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21200) die('skip libxml2 test variant for version >= 2.12');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects attributes values not closed between " or '
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed2.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentloadxml_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d
-+
-+Warning: DOMDocument::loadXML(): Opening and ending tag mismatch: books line 3 and book in Entity, line: 7 in %s on line %d
-diff --git a/ext/dom/tests/DOMDocument_load_error1.phpt b/ext/dom/tests/DOMDocument_load_error1.phpt
-index 8ac181d769..4416f5f6fe 100644
---- a/ext/dom/tests/DOMDocument_load_error1.phpt
-+++ b/ext/dom/tests/DOMDocument_load_error1.phpt
-@@ -1,5 +1,9 @@
- --TEST--
- Test DOMDocument::load() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version < 2.12');
-+?>
- --DESCRIPTION--
- This test verifies the method detects an opening and ending tag mismatch
- Environment variables used in the test:
-diff --git a/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt b/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt
-new file mode 100644
-index 0000000000..183c8406fd
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt
-@@ -0,0 +1,26 @@
-+--TEST--
-+Test DOMDocument::load() detects not-well formed XML
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21200) die('skip libxml2 test variant for version >= 2.12');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects an opening and ending tag mismatch
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentload_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::load%r(XML){0,1}%r(): Opening and ending tag mismatch: title line 5 and book %s
-+
-+Warning: DOMDocument::load%r(XML){0,1}%r(): %rexpected '>'|Opening and ending tag mismatch: book line (4|5) and books%r %s
-diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
-index 32b6bf1611..4d9f992b3b 100644
---- a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
-+++ b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
-@@ -2,7 +2,7 @@
- Test DOMDocument::load() detects not-well formed
- --SKIPIF--
- <?php
--if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
-+if (LIBXML_VERSION < 21100 || LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version >= 2.11 && <= 2.12');
- ?>
- --DESCRIPTION--
- This test verifies the method detects attributes values not closed between " or '
-diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt
-new file mode 100644
-index 0000000000..4fadf41736
---- /dev/null
-+++ b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt
-@@ -0,0 +1,30 @@
-+--TEST--
-+Test DOMDocument::load() detects not-well formed
-+--SKIPIF--
-+<?php
-+if (LIBXML_VERSION < 21200) die('skip libxml2 test variant for version >= 2.12');
-+?>
-+--DESCRIPTION--
-+This test verifies the method detects attributes values not closed between " or '
-+Environment variables used in the test:
-+- XML_FILE: the xml file to load
-+- LOAD_OPTIONS: the second parameter to pass to the method
-+- EXPECTED_RESULT: the expected result
-+--CREDITS--
-+Antonio Diaz Ruiz <dejalatele@gmail.com>
-+--EXTENSIONS--
-+dom
-+--ENV--
-+XML_FILE=/not_well_formed2.xml
-+LOAD_OPTIONS=0
-+EXPECTED_RESULT=0
-+--FILE_EXTERNAL--
-+domdocumentload_test_method.inc
-+--EXPECTF--
-+Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d
-+
-+Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d
-+
-+Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d
-+
-+Warning: DOMDocument::load(): Opening and ending tag mismatch: books line 3 and book in %s on line %d
-diff --git a/ext/xml/tests/bug81351.phpt b/ext/xml/tests/bug81351.phpt
-index 19e4ca590b..dc934001be 100644
---- a/ext/xml/tests/bug81351.phpt
-+++ b/ext/xml/tests/bug81351.phpt
-@@ -23,6 +23,6 @@ $code = xml_get_error_code($parser);
- $error = xml_error_string($code);
- echo "xml_parse returned $success, xml_get_error_code = $code, xml_error_string = $error\r\n";
- ?>
----EXPECT--
-+--EXPECTF--
- xml_parse returned 1, xml_get_error_code = 0, xml_error_string = No error
--xml_parse returned 0, xml_get_error_code = 5, xml_error_string = Invalid document end
-+%rxml_parse returned 0, xml_get_error_code = 5, xml_error_string = Invalid document end|xml_parse returned 0, xml_get_error_code = 77, xml_error_string = Tag not finished%r
-diff --git a/ext/xml/tests/xml_error_string_basic.phpt b/ext/xml/tests/xml_error_string_basic.phpt
-index e72fa68bd1..9020415f1f 100644
---- a/ext/xml/tests/xml_error_string_basic.phpt
-+++ b/ext/xml/tests/xml_error_string_basic.phpt
-@@ -25,9 +25,9 @@ foreach ($xmls as $xml) {
- xml_parser_free($xml_parser);
- }
- ?>
----EXPECT--
--int(5)
--string(20) "Invalid document end"
-+--EXPECTF--
-+int(%r5|77%r)
-+string(%d) %r"Invalid document end"|"Tag not finished"%r
- int(47)
- string(35) "Processing Instruction not finished"
- int(57)
---
-2.43.0
-
diff --git a/php-8.0.30-pcretests.patch b/php-8.0.30-pcretests.patch
new file mode 100644
index 0000000..c226661
--- /dev/null
+++ b/php-8.0.30-pcretests.patch
@@ -0,0 +1,43 @@
+From c3150fcc89825f50d476b1b1971870aeb71f167d Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 12 Mar 2025 07:48:05 +0100
+Subject: [PATCH 1/2] Relax test expectation for pcre2lib 10.45 Using
+ e92848789acd8aa5cf32fedb519ba9378ac64e02
+
+---
+ ext/pcre/tests/bug75457.phpt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/pcre/tests/bug75457.phpt b/ext/pcre/tests/bug75457.phpt
+index ee5ab162f8a6c..87dc12a1ad056 100644
+--- a/ext/pcre/tests/bug75457.phpt
++++ b/ext/pcre/tests/bug75457.phpt
+@@ -6,5 +6,5 @@ $pattern = "/(((?(?C)0?=))(?!()0|.(?0)0)())/";
+ var_dump(preg_match($pattern, "hello"));
+ ?>
+ --EXPECTF--
+-Warning: preg_match(): Compilation failed: assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d
++Warning: preg_match(): Compilation failed: %r(atomic|)%r assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d
+ bool(false)
+
+From 126095700a02b9aa1f33764a63c93a70e8373ad8 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@famillecollet.com>
+Date: Wed, 12 Mar 2025 09:36:33 +0100
+Subject: [PATCH 2/2] Update ext/pcre/tests/bug75457.phpt
+
+Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+---
+ ext/pcre/tests/bug75457.phpt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/pcre/tests/bug75457.phpt b/ext/pcre/tests/bug75457.phpt
+index 87dc12a1ad056..1401b25ff6fb7 100644
+--- a/ext/pcre/tests/bug75457.phpt
++++ b/ext/pcre/tests/bug75457.phpt
+@@ -6,5 +6,5 @@ $pattern = "/(((?(?C)0?=))(?!()0|.(?0)0)())/";
+ var_dump(preg_match($pattern, "hello"));
+ ?>
+ --EXPECTF--
+-Warning: preg_match(): Compilation failed: %r(atomic|)%r assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d
++Warning: preg_match(): Compilation failed:%r( atomic|)%r assertion expected after (?( or (?(?C) at offset 8 in %sbug75457.php on line %d
+ bool(false)
diff --git a/php-8.0.30-proto.patch b/php-8.0.30-proto.patch
new file mode 100644
index 0000000..1e63c23
--- /dev/null
+++ b/php-8.0.30-proto.patch
@@ -0,0 +1,341 @@
+From f566cba0bb6bd53b1d44d5097e68201412b00f7a Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@php.net>
+Date: Thu, 25 Nov 2021 13:16:26 +0100
+Subject: [PATCH] fix [-Wstrict-prototypes] build warnings in ext/gd
+
+---
+ ext/gd/config.m4 | 2 --
+ ext/gd/gd.c | 58 ++++++++++++++++++++++++------------------------
+ 2 files changed, 29 insertions(+), 31 deletions(-)
+
+diff --git a/ext/gd/gd.c b/ext/gd/gd.c
+index 166e82b4321c9..ebd3c6c9c3d01 100644
+--- a/ext/gd/gd.c
++++ b/ext/gd/gd.c
+@@ -142,16 +142,16 @@ static void php_image_filter_pixelate(IN
+ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS);
+
+ /* End Section filters declarations */
+-static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)());
+-static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)());
+-static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)());
++static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
++static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(FILE *), gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
++static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn);
+ static gdIOCtx *create_stream_context_from_zval(zval *to_zval);
+ static gdIOCtx *create_stream_context(php_stream *stream, int close_stream);
+ static gdIOCtx *create_output_context();
+ static int _php_image_type(char data[12]);
+
+ /* output streaming (formerly gd_ctx.c) */
+-static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)());
++static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn);
+
+ /*********************************************************
+ *
+@@ -1464,7 +1464,7 @@ static int _php_image_type (char data[12
+ /* }}} */
+
+ /* {{{ _php_image_create_from_string */
+-gdImagePtr _php_image_create_from_string(zend_string *data, char *tn, gdImagePtr (*ioctx_func_p)())
++gdImagePtr _php_image_create_from_string(zend_string *data, char *tn, gdImagePtr (*ioctx_func_p)(gdIOCtxPtr))
+ {
+ gdImagePtr im;
+ gdIOCtx *io_ctx;
+@@ -1569,7 +1569,7 @@ PHP_FUNCTION(imagecreatefromstring)
+ /* }}} */
+
+ /* {{{ _php_image_create_from */
+-static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)())
++static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(FILE *), gdImagePtr (*ioctx_func_p)(gdIOCtxPtr))
+ {
+ char *file;
+ size_t file_len;
+@@ -1613,7 +1613,7 @@ static void _php_image_create_from(INTER
+ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
+ goto out_err;
+ }
+- } else if (ioctx_func_p) {
++ } else if (ioctx_func_p || image_type == PHP_GDIMG_TYPE_GD2PART) {
+ /* we can create an io context */
+ gdIOCtx* io_ctx;
+ zend_string *buff;
+@@ -1637,7 +1637,7 @@ static void _php_image_create_from(INTER
+ }
+
+ if (image_type == PHP_GDIMG_TYPE_GD2PART) {
+- im = (*ioctx_func_p)(io_ctx, srcx, srcy, width, height);
++ im = gdImageCreateFromGd2PartCtx(io_ctx, srcx, srcy, width, height);
+ } else {
+ im = (*ioctx_func_p)(io_ctx);
+ }
+@@ -1655,7 +1655,7 @@ static void _php_image_create_from(INTER
+ if (!im && fp) {
+ switch (image_type) {
+ case PHP_GDIMG_TYPE_GD2PART:
+- im = (*func_p)(fp, srcx, srcy, width, height);
++ im = gdImageCreateFromGd2Part(fp, srcx, srcy, width, height);
+ break;
+ #ifdef HAVE_GD_XPM
+ case PHP_GDIMG_TYPE_XPM:
+@@ -1738,7 +1738,7 @@ PHP_FUNCTION(imagecreatefromxbm)
+ /* {{{ Create a new image from XPM file or URL */
+ PHP_FUNCTION(imagecreatefromxpm)
+ {
+- _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XPM, "XPM", gdImageCreateFromXpm, NULL);
++ _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XPM, "XPM", NULL, NULL);
+ }
+ /* }}} */
+ #endif
+@@ -1767,7 +1767,7 @@ PHP_FUNCTION(imagecreatefromgd2)
+ /* {{{ Create a new image from a given part of GD2 file or URL */
+ PHP_FUNCTION(imagecreatefromgd2part)
+ {
+- _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2PART, "GD2", gdImageCreateFromGd2Part, gdImageCreateFromGd2PartCtx);
++ _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2PART, "GD2", NULL, NULL);
+ }
+ /* }}} */
+
+@@ -1790,7 +1790,7 @@ PHP_FUNCTION(imagecreatefromtga)
+ #endif
+
+ /* {{{ _php_image_output */
+-static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
++static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn)
+ {
+ zval *imgind;
+ char *file = NULL;
+@@ -1837,13 +1837,13 @@ static void _php_image_output(INTERNAL_F
+
+ switch (image_type) {
+ case PHP_GDIMG_TYPE_GD:
+- (*func_p)(im, fp);
++ gdImageGd(im, fp);
+ break;
+ case PHP_GDIMG_TYPE_GD2:
+ if (q == -1) {
+ q = 128;
+ }
+- (*func_p)(im, fp, q, t);
++ gdImageGd2(im, fp, q, t);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+@@ -1863,13 +1863,13 @@ static void _php_image_output(INTERNAL_F
+
+ switch (image_type) {
+ case PHP_GDIMG_TYPE_GD:
+- (*func_p)(im, tmp);
++ gdImageGd(im, tmp);
+ break;
+ case PHP_GDIMG_TYPE_GD2:
+ if (q == -1) {
+ q = 128;
+ }
+- (*func_p)(im, tmp, q, t);
++ gdImageGd2(im, tmp, q, t);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+@@ -1939,7 +1939,7 @@ PHP_FUNCTION(imagexbm)
+ /* {{{ Output GIF image to browser or file */
+ PHP_FUNCTION(imagegif)
+ {
+- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
++ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF");
+ }
+ /* }}} */
+
+@@ -1947,7 +1947,7 @@ PHP_FUNCTION(imagegif)
+ /* {{{ Output PNG image to browser or file */
+ PHP_FUNCTION(imagepng)
+ {
+- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx);
++ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG");
+ }
+ /* }}} */
+ #endif /* HAVE_GD_PNG */
+@@ -1956,7 +1956,7 @@ PHP_FUNCTION(imagepng)
+ /* {{{ Output WEBP image to browser or file */
+ PHP_FUNCTION(imagewebp)
+ {
+- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageWebpCtx);
++ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP");
+ }
+ /* }}} */
+ #endif /* HAVE_GD_WEBP */
+@@ -1965,7 +1965,7 @@ PHP_FUNCTION(imagewebp)
+ /* {{{ Output JPEG image to browser or file */
+ PHP_FUNCTION(imagejpeg)
+ {
+- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx);
++ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG");
+ }
+ /* }}} */
+ #endif /* HAVE_GD_JPG */
+@@ -2017,14 +2017,14 @@ PHP_FUNCTION(imagewbmp)
+ /* {{{ Output GD image to browser or file */
+ PHP_FUNCTION(imagegd)
+ {
+- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageGd);
++ _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD");
+ }
+ /* }}} */
+
+ /* {{{ Output GD2 image to browser or file */
+ PHP_FUNCTION(imagegd2)
+ {
+- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageGd2);
++ _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2");
+ }
+ /* }}} */
+
+@@ -4154,7 +4154,7 @@ static gdIOCtx *create_output_context()
+ return ctx;
+ }
+
+-static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
++static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn)
+ {
+ zval *imgind;
+ zend_long quality = -1, basefilter = -1;
+@@ -4189,13 +4189,13 @@ static void _php_image_output_ctx(INTERN
+
+ switch (image_type) {
+ case PHP_GDIMG_TYPE_JPG:
+- (*func_p)(im, ctx, (int) quality);
++ gdImageJpegCtx(im, ctx, (int) quality);
+ break;
+ case PHP_GDIMG_TYPE_WEBP:
+ if (quality == -1) {
+ quality = 80;
+ }
+- (*func_p)(im, ctx, (int) quality);
++ gdImageWebpCtx(im, ctx, (int) quality);
+ break;
+ #ifdef HAVE_GD_PNG
+ case PHP_GDIMG_TYPE_PNG:
+@@ -4207,7 +4207,7 @@ static void _php_image_output_ctx(INTERN
+ break;
+ #endif
+ case PHP_GDIMG_TYPE_GIF:
+- (*func_p)(im, ctx);
++ gdImageGifCtx(im, ctx);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+
+From b7356692f69f4ac0a07ea54e83debdd04b426dcb Mon Sep 17 00:00:00 2001
+From: George Peter Banyard <girgias@php.net>
+Date: Wed, 12 May 2021 14:41:11 +0100
+Subject: [PATCH] Specify function pointer signature for scanf implementation
+
+Fix [-Wstrict-prototypes] warnings in standard/scanf.c
+---
+ ext/standard/scanf.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c
+index f58b4195cc599..78ecc1642cf92 100644
+--- a/ext/standard/scanf.c
++++ b/ext/standard/scanf.c
+@@ -106,6 +106,8 @@ typedef struct CharSet {
+ } *ranges;
+ } CharSet;
+
++typedef zend_long (*int_string_formater)(const char*, char**, int);
++
+ /*
+ * Declarations for functions used only in this file.
+ */
+@@ -583,7 +585,7 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
+ int base = 0;
+ int underflow = 0;
+ size_t width;
+- zend_long (*fn)() = NULL;
++ int_string_formater fn = NULL;
+ char *ch, sch;
+ int flags;
+ char buf[64]; /* Temporary buffer to hold scanned number
+@@ -740,29 +742,29 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
+ case 'D':
+ op = 'i';
+ base = 10;
+- fn = (zend_long (*)())ZEND_STRTOL_PTR;
++ fn = (int_string_formater)ZEND_STRTOL_PTR;
+ break;
+ case 'i':
+ op = 'i';
+ base = 0;
+- fn = (zend_long (*)())ZEND_STRTOL_PTR;
++ fn = (int_string_formater)ZEND_STRTOL_PTR;
+ break;
+ case 'o':
+ op = 'i';
+ base = 8;
+- fn = (zend_long (*)())ZEND_STRTOL_PTR;
++ fn = (int_string_formater)ZEND_STRTOL_PTR;
+ break;
+ case 'x':
+ case 'X':
+ op = 'i';
+ base = 16;
+- fn = (zend_long (*)())ZEND_STRTOL_PTR;
++ fn = (int_string_formater)ZEND_STRTOL_PTR;
+ break;
+ case 'u':
+ op = 'i';
+ base = 10;
+ flags |= SCAN_UNSIGNED;
+- fn = (zend_long (*)())ZEND_STRTOUL_PTR;
++ fn = (int_string_formater)ZEND_STRTOUL_PTR;
+ break;
+
+ case 'f':
+From 2068d230d981d7b06b41b87ebc37ab2581b79852 Mon Sep 17 00:00:00 2001
+From: George Peter Banyard <girgias@php.net>
+Date: Wed, 12 May 2021 18:54:57 +0100
+Subject: [PATCH] Fix [-Wstrict-prototypes] warning in PCNTL extension
+
+To achieve this we need to introduce a new wrapper function with
+dummy arguments which calls pcntl_signal_dispatch() to respect
+the function pointer signature for a tick function.
+---
+ ext/pcntl/pcntl.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
+index 1e8690ae75144..c116eff7d034a 100644
+--- a/ext/pcntl/pcntl.c
++++ b/ext/pcntl/pcntl.c
+@@ -89,7 +89,8 @@ static void pcntl_siginfo_to_zval(int, siginfo_t*, zval*);
+ #else
+ static void pcntl_signal_handler(int);
+ #endif
+-static void pcntl_signal_dispatch();
++static void pcntl_signal_dispatch(void);
++static void pcntl_signal_dispatch_tick_function(int dummy_int, void *dummy_pointer);
+ static void pcntl_interrupt_function(zend_execute_data *execute_data);
+
+ void php_register_signal_constants(INIT_FUNC_ARGS)
+@@ -424,7 +425,7 @@ static PHP_GINIT_FUNCTION(pcntl)
+
+ PHP_RINIT_FUNCTION(pcntl)
+ {
+- php_add_tick_function(pcntl_signal_dispatch, NULL);
++ php_add_tick_function(pcntl_signal_dispatch_tick_function, NULL);
+ zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
+ PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
+ PCNTL_G(async_signals) = 0;
+@@ -1385,6 +1386,11 @@ void pcntl_signal_dispatch()
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+ }
+
++static void pcntl_signal_dispatch_tick_function(int dummy_int, void *dummy_pointer)
++{
++ return pcntl_signal_dispatch();
++}
++
+ /* {{{ Enable/disable asynchronous signal handling and return the old setting. */
+ PHP_FUNCTION(pcntl_async_signals)
+ {
diff --git a/php-cve-2024-11233.patch b/php-cve-2024-11233.patch
new file mode 100644
index 0000000..d372560
--- /dev/null
+++ b/php-cve-2024-11233.patch
@@ -0,0 +1,67 @@
+From 2cee10a1206f5bc7724232d3988be2cfcb0bc9df Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 8 Nov 2024 22:04:21 +0100
+Subject: [PATCH 5/8] Fix GHSA-r977-prxv-hc43
+
+Move the bound check upwards. Since this doesn't generate output we can
+check the bound first.
+
+(cherry picked from commit 81030c9bbb5cd2e740b8398bb7212df9709f0274)
+---
+ ext/standard/filters.c | 7 ++++---
+ ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt | 12 ++++++++++++
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+ create mode 100644 ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt
+
+diff --git a/ext/standard/filters.c b/ext/standard/filters.c
+index d5e65644439..ff0bda0cbcd 100644
+--- a/ext/standard/filters.c
++++ b/ext/standard/filters.c
+@@ -996,6 +996,9 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
+ } break;
+
+ case 5: {
++ if (icnt == 0) {
++ goto out;
++ }
+ if (!inst->lbchars && lb_cnt == 1 && *ps == '\n') {
+ /* auto-detect soft line breaks, found network line break */
+ lb_cnt = lb_ptr = 0;
+@@ -1009,15 +1012,13 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
+ /* soft line break */
+ lb_cnt = lb_ptr = 0;
+ scan_stat = 0;
+- } else if (icnt > 0) {
++ } else {
+ if (*ps == (unsigned char)inst->lbchars[lb_cnt]) {
+ lb_cnt++;
+ ps++, icnt--;
+ } else {
+ scan_stat = 6; /* no break for short-cut */
+ }
+- } else {
+- goto out;
+ }
+ } break;
+
+diff --git a/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt b/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt
+new file mode 100644
+index 00000000000..8fdcce8ff22
+--- /dev/null
++++ b/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt
+@@ -0,0 +1,12 @@
++--TEST--
++GHSA-r977-prxv-hc43: Single byte overread with convert.quoted-printable-decode filter
++--FILE--
++<?php
++
++$input_data = str_repeat('A', 8189)."X=\r";
++$filter_url = "php://filter/convert.quoted-printable-decode/resource=data:," . urlencode($input_data);
++var_dump(file_get_contents($filter_url));
++
++?>
++--EXPECT--
++string(8190) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX"
+--
+2.47.0
+
diff --git a/php-cve-2024-11234.patch b/php-cve-2024-11234.patch
new file mode 100644
index 0000000..59afbcc
--- /dev/null
+++ b/php-cve-2024-11234.patch
@@ -0,0 +1,118 @@
+From bc1f192102dd8cbda028e40aa31604c4885d387c Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Fri, 8 Nov 2024 23:43:47 +0100
+Subject: [PATCH 3/8] Fix GHSA-c5f2-jwm7-mmq2: stream HTTP fulluri CRLF
+ injection
+
+(cherry picked from commit 426a6d4539ebee34879ac5de857036bb6ff0e732)
+---
+ ext/standard/http_fopen_wrapper.c | 18 ++++++++----
+ .../tests/http/ghsa-c5f2-jwm7-mmq2.phpt | 28 +++++++++++++++++++
+ 2 files changed, 40 insertions(+), 6 deletions(-)
+ create mode 100644 ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index 45677c396ac..6859a4e5181 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -184,6 +184,11 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ return NULL;
+ }
+
++ /* Should we send the entire path in the request line, default to no. */
++ if (context && (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) {
++ request_fulluri = zend_is_true(tmpzval);
++ }
++
+ use_ssl = resource->scheme && (ZSTR_LEN(resource->scheme) > 4) && ZSTR_VAL(resource->scheme)[4] == 's';
+ /* choose default ports */
+ if (use_ssl && resource->port == 0)
+@@ -203,6 +208,13 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ }
+ }
+
++ if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) {
++ php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters");
++ php_url_free(resource);
++ zend_string_release(transport_string);
++ return NULL;
++ }
++
+ if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) {
+ double d = zval_get_double(tmpzval);
+ #ifndef PHP_WIN32
+@@ -383,12 +395,6 @@ finish:
+ smart_str_appends(&req_buf, "GET ");
+ }
+
+- /* Should we send the entire path in the request line, default to no. */
+- if (!request_fulluri && context &&
+- (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) {
+- request_fulluri = zend_is_true(tmpzval);
+- }
+-
+ if (request_fulluri) {
+ /* Ask for everything */
+ smart_str_appends(&req_buf, path);
+diff --git a/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt b/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt
+new file mode 100644
+index 00000000000..e7dd194dbbe
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt
+@@ -0,0 +1,28 @@
++--TEST--
++GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context might allow for CRLF injection in URIs)
++--INI--
++allow_url_fopen=1
++--CONFLICTS--
++server
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++echo $_SERVER['REQUEST_URI'];
++CODE;
++
++include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";
++php_cli_server_start($serverCode, null, []);
++
++$host = PHP_CLI_SERVER_ADDRESS;
++$userinput = "index.php HTTP/1.1\r\nHost: $host\r\n\r\nGET /index2.php HTTP/1.1\r\nHost: $host\r\n\r\nGET /index.php";
++$context = stream_context_create(['http' => ['proxy' => 'tcp://' . $host, 'request_fulluri' => true]]);
++echo file_get_contents("http://$host/$userinput", false, $context);
++?>
++--EXPECTF--
++Warning: file_get_contents(http://localhost:%d/index.php HTTP/1.1
++Host: localhost:%d
++
++GET /index2.php HTTP/1.1
++Host: localhost:%d
++
++GET /index.php): Failed to open stream: HTTP wrapper full URI path does not allow CR or LF characters in %s on line %d
+--
+2.47.0
+
+From 8d130e16fbfda7d154fedfa0f1ff1d5ad5e26815 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Fri, 22 Nov 2024 09:41:12 +0100
+Subject: [PATCH 8/8] fix transport_string release
+
+---
+ ext/standard/http_fopen_wrapper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index 6859a4e5181..40e6f3dd4c3 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -211,7 +211,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) {
+ php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters");
+ php_url_free(resource);
+- zend_string_release(transport_string);
++ efree(transport_string);
+ return NULL;
+ }
+
+--
+2.47.0
+
diff --git a/php-cve-2024-11236.patch b/php-cve-2024-11236.patch
new file mode 100644
index 0000000..d793ed6
--- /dev/null
+++ b/php-cve-2024-11236.patch
@@ -0,0 +1,117 @@
+From 5d9e54065ed18c51e4f25d8900635f90810c7394 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Thu, 24 Oct 2024 22:02:17 +0200
+Subject: [PATCH 1/8] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the dblib
+ quoter causing OOB writes
+
+(cherry picked from commit d9baa9fed8c3ba692a36b388c0c7762e5102e2e0)
+---
+ ext/pdo_dblib/dblib_driver.c | 8 ++++++-
+ ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt | 24 ++++++++++++++++++++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+ create mode 100644 ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
+
+diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
+index 7f160a402f7..d7d0901ea1a 100644
+--- a/ext/pdo_dblib/dblib_driver.c
++++ b/ext/pdo_dblib/dblib_driver.c
+@@ -152,6 +152,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
+
+ size_t i;
+ char * q;
++ size_t extralen = 0;
+ *quotedlen = 0;
+
+ if (H->assume_national_character_set_strings) {
+@@ -166,7 +167,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
+
+ /* Detect quoted length, adding extra char for doubled single quotes */
+ for (i = 0; i < unquotedlen; i++) {
+- if (unquoted[i] == '\'') ++*quotedlen;
++ if (unquoted[i] == '\'') ++extralen;
+ ++*quotedlen;
+ }
+
+@@ -174,6 +175,11 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
+ if (use_national_character_set) {
+ ++*quotedlen; /* N prefix */
+ }
++ if (UNEXPECTED(*quotedlen > ZSTR_MAX_LEN - extralen)) {
++ return 0;
++ }
++
++ *quotedlen += extralen;
+ q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
+ if (use_national_character_set) {
+ *q++ = 'N';
+diff --git a/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
+new file mode 100644
+index 00000000000..431c61951ee
+--- /dev/null
++++ b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
+@@ -0,0 +1,24 @@
++--TEST--
++GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing OOB writes)
++--EXTENSIONS--
++pdo_dblib
++--SKIPIF--
++<?php
++if (PHP_INT_SIZE != 4) die("skip for 32bit platforms only");
++if (PHP_OS_FAMILY === "Windows") die("skip not for Windows because the virtual address space for application is only 2GiB");
++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
++require __DIR__ . '/config.inc';
++getDbConnection();
++?>
++--INI--
++memory_limit=-1
++--FILE--
++<?php
++
++require __DIR__ . '/config.inc';
++$db = getDbConnection();
++var_dump($db->quote(str_repeat("'", 2147483646)));
++
++?>
++--EXPECT--
++bool(false)
+--
+2.47.0
+
+From b4f73be75dbdde970a18cc7a636898b10400fb3f Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Thu, 24 Oct 2024 22:02:36 +0200
+Subject: [PATCH 2/8] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the firebird
+ quoter causing OOB writes
+
+(cherry picked from commit 69c5f68fdc3deed9ebce2cc44b4bf5e0c47cd28f)
+---
+ ext/pdo_firebird/firebird_driver.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index e0a424c56ab..fb697978503 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -663,7 +663,7 @@ free_statement:
+ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, /* {{{ */
+ char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
+ {
+- int qcount = 0;
++ size_t qcount = 0;
+ char const *co, *l, *r;
+ char *c;
+
+@@ -678,6 +678,10 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t u
+ /* count the number of ' characters */
+ for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++);
+
++ if (UNEXPECTED(unquotedlen + 2 > ZSTR_MAX_LEN - qcount)) {
++ return 0;
++ }
++
+ *quotedlen = unquotedlen + qcount + 2;
+ *quoted = c = emalloc(*quotedlen+1);
+ *c++ = '\'';
+--
+2.47.0
+
diff --git a/php-cve-2024-8929.patch b/php-cve-2024-8929.patch
new file mode 100644
index 0000000..82768c7
--- /dev/null
+++ b/php-cve-2024-8929.patch
@@ -0,0 +1,2301 @@
+From 0d3ccf4cc54d3844bc9d1c8f6bdcd36180752a2c Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Tue, 8 Oct 2024 16:17:53 +0100
+Subject: [PATCH 1/6] Fix GHSA-h35g-vwh6-m678: Mysqlnd - various heap buffer
+ over-reads
+
+This fixes issues causing buffer over-read that leak heap content:
+- RESP packet field default left over for COM_LIST
+- RESP packet upsert filename
+- OK packet message
+- RESP packet for stmt row data
+ - ps_fetch_from_1_to_8_bytes
+ - ps_fetch_float
+ - ps_fetch_double
+ - ps_fetch_time
+ - ps_fetch_date
+ - ps_fetch_datetime
+ - ps_fetch_string
+ - ps_fetch_bit
+- RESP packet for query row data (just possible overflow on 32bit)
+
+It also adds various protocol tests using a new fake server.
+
+(cherry picked from commit 2f5aa9f9d150ca56e356f3ca9acf9d530108cb08)
+---
+ ext/mysqli/tests/fake_server.inc | 856 ++++++++++++++++++
+ .../ghsa-h35g-vwh6-m678-auth-message.phpt | 38 +
+ ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt | 47 +
+ .../tests/ghsa-h35g-vwh6-m678-filename.phpt | 43 +
+ ...hsa-h35g-vwh6-m678-query-len-overflow.phpt | 48 +
+ .../ghsa-h35g-vwh6-m678-stmt-row-bit.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-date.phpt | 53 ++
+ ...ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-double.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-float.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-int.phpt | 53 ++
+ ...ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-string.phpt | 53 ++
+ .../ghsa-h35g-vwh6-m678-stmt-row-time.phpt | 53 ++
+ .../tests/protocol_query_row_fetch_data.phpt | 74 ++
+ .../tests/protocol_stmt_row_fetch_data.phpt | 91 ++
+ ext/mysqlnd/mysqlnd_ps_codec.c | 69 ++
+ ext/mysqlnd/mysqlnd_result.c | 2 +-
+ ext/mysqlnd/mysqlnd_wireprotocol.c | 71 +-
+ 19 files changed, 1794 insertions(+), 22 deletions(-)
+ create mode 100644 ext/mysqli/tests/fake_server.inc
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt
+ create mode 100644 ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt
+ create mode 100644 ext/mysqli/tests/protocol_query_row_fetch_data.phpt
+ create mode 100644 ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt
+
+diff --git a/ext/mysqli/tests/fake_server.inc b/ext/mysqli/tests/fake_server.inc
+new file mode 100644
+index 00000000000..b02fabc584c
+--- /dev/null
++++ b/ext/mysqli/tests/fake_server.inc
+@@ -0,0 +1,856 @@
++<?php
++
++function my_mysqli_data_fields(): array
++{
++ return [
++ 'intval' => [
++ 'type' => '03',
++ 'charset' => '3f00',
++ 'length' => '0b000000',
++ 'flags' => '0110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '080000',
++ 'query_data_value' => '023134',
++ 'stmt_data_packet_length' => '0b0000',
++ 'stmt_data_value' => '0e000000'
++ ],
++ 'fltval' => [
++ 'type' => '04',
++ 'charset' => '3f00',
++ 'length' => '0c000000',
++ 'flags' => '0110',
++ 'decimal' => '1f',
++ 'query_data_packet_length' => '090000',
++ 'query_data_value' => '03322e33',
++ 'stmt_data_packet_length' => '0b0000',
++ 'stmt_data_value' => '33331340',
++ ],
++ 'dblval' => [
++ 'type' => '05',
++ 'charset' => '3f00',
++ 'length' => '16000000',
++ 'flags' => '0110',
++ 'decimal' => '1f',
++ 'query_data_packet_length' => '090000',
++ 'query_data_value' => '03312e32',
++ 'stmt_data_packet_length' => '0f0000',
++ 'stmt_data_value' => '333333333333f33f'
++ ],
++ 'datval' => [
++ 'type' => '0a',
++ 'charset' => '3f00',
++ 'length' => '0a000000',
++ 'flags' => '8110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '100000',
++ 'query_data_value' => '0a323031342d31322d3135',
++ 'stmt_data_packet_length' => '0c0000',
++ 'stmt_data_value' => '04de070c0f'
++ ],
++ 'timval' => [
++ 'type' => '0b',
++ 'charset' => '3f00',
++ 'length' => '0a000000',
++ 'flags' => '8110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '0e0000',
++ 'query_data_value' => '0831333a30303a3032',
++ 'stmt_data_packet_length' => '100000',
++ 'stmt_data_value' => '080000000000150801'
++ ],
++ 'dtival' => [
++ 'type' => '0c',
++ 'charset' => '3f00',
++ 'length' => '13000000',
++ 'flags' => '8110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '190000',
++ 'query_data_value' => '13323031342d31322d31362031333a30303a3031',
++ 'stmt_data_packet_length' => '0f0000',
++ 'stmt_data_value' => '07de070c100d0001'
++ ],
++ 'bitval' => [
++ 'type' => '10',
++ 'charset' => '3f00',
++ 'length' => '40000000',
++ 'flags' => '2110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '0e0000',
++ 'query_data_value' => '080808080808080808',
++ 'stmt_data_packet_length' => '100000',
++ 'stmt_data_value' => '080808080808080808'
++ ],
++ 'strval' => [
++ 'type' => 'fd',
++ 'charset' => 'e000',
++ 'length' => 'c8000000',
++ 'flags' => '0110',
++ 'decimal' => '00',
++ 'query_data_packet_length' => '0a0000',
++ 'query_data_value' => '0474657374',
++ 'stmt_data_packet_length' => '0c0000',
++ 'stmt_data_value' => '0474657374'
++ ],
++ ];
++}
++
++function my_mysqli_data_field(string $field): array
++{
++ $fields = my_mysqli_data_fields();
++ if (!isset($fields[$field])) {
++ throw new Exception("Unknown field $field");
++ }
++ return $fields[$field];
++}
++
++
++
++class my_mysqli_fake_packet_item
++{
++ public function __construct(public string|null $name, public string $value, public bool $is_hex = true)
++ {
++ }
++}
++
++class my_mysqli_fake_packet
++{
++ private array $data = array();
++
++ public function __get(string $name)
++ {
++ foreach ($this->data as $item) {
++ if ($item->name === $name) {
++ return $item->value;
++ }
++ }
++ return null;
++ }
++
++ public function __set(string $name, string|my_mysqli_fake_packet_item $value)
++ {
++ if ($value instanceof my_mysqli_fake_packet_item) {
++ if ($value->name === null) {
++ $value->name = $name;
++ }
++ } else {
++ $value = new my_mysqli_fake_packet_item($name, $value, true);
++ }
++
++ for ($i = 0; $i < count($this->data); $i++) {
++ if ($this->data[$i]->name === $name) {
++ $this->data[$i] = $value;
++ return;
++ }
++ }
++
++ $this->data[] = $value;
++ }
++
++ public function to_bytes(): string
++ {
++ $bytes = '';
++ foreach ($this->data as $item) {
++ $bytes .= $item->is_hex ? hex2bin($item->value) : $item->value;
++ }
++ return $bytes;
++ }
++}
++
++class my_mysqli_fake_packet_generator
++{
++ public static function create_packet_item(int|string $value, bool $is_hex = false, string $format = 'v'): my_mysqli_fake_packet_item
++ {
++ if (is_string($value)) {
++ $packed_value = $value;
++ } else {
++ $packed_value = pack($format, $value);
++ }
++ return new my_mysqli_fake_packet_item(null, $packed_value, $is_hex);
++ }
++
++ public function server_ok(): my_mysqli_fake_packet
++ {
++ $packet = new my_mysqli_fake_packet();
++ $packet->packet_length = "070000";
++ $packet->packet_number = "02";
++ $packet->header = "00"; // OK
++ $packet->affected_rows = "00";
++ $packet->last_insert_id = "00";
++ $packet->server_status = "0200";
++ $packet->warning_count = "0000";
++ return $packet;
++ }
++
++ public function server_greetings(): my_mysqli_fake_packet
++ {
++ $packet = new my_mysqli_fake_packet();
++ $packet->packet_length = "580000";
++ $packet->packet_number = "00";
++ $packet->proto_version = "0a";
++ $packet->version = self::create_packet_item('5.5.5-10.5.18-MariaDB' . chr(0));
++ $packet->thread_id = "03000000";
++ $packet->salt = "473e3f6047257c67";
++ $packet->filler = "00";
++ $packet->server_capabilities = self::create_packet_item(0b1111011111111110);
++ $packet->server_character_set = "08";
++ $packet->server_status = self::create_packet_item(0b000000000000010);
++ $packet->extended_server_capabilities = self::create_packet_item(0b1000000111111111);
++ $packet->auth_plugin = "15";
++ $packet->unused = "000000000000";
++ $packet->mariadb_extended_server_capabilities = self::create_packet_item(0b1111, false, 'V');
++ $packet->mariadb_extended_server_capabilities_salt = "6c6b55463f49335f686c643100";
++ $packet->mariadb_extended_server_capabilities_auth_plugin = self::create_packet_item('mysql_native_password');
++
++ return $packet;
++ }
++
++ public function server_tabular_query_response(): array
++ {
++ $qr1 = new my_mysqli_fake_packet();
++ $qr1->packet_length = "010000";
++ $qr1->packet_number = "01";
++ $qr1->field_count = "01";
++
++ $qr2 = new my_mysqli_fake_packet();
++ $qr2->packet_length = "190000";
++ $qr2->packet_number = "02";
++ $qr2->catalog_length_plus_name = "0164";
++ $qr2->db_length_plus_name = "0164";
++ $qr2->table_length_plus_name = "0164";
++ $qr2->original_t = "0164";
++ $qr2->name_length_plus_name = "0164";
++ $qr2->original_n = "0164";
++ $qr2->canary = "0c";
++ $qr2->charset = "3f00";
++ $qr2->length = "0b000000";
++ $qr2->type = "03";
++ $qr2->flags = "0350";
++ $qr2->decimals = "000000";
++
++ $qr3 = new my_mysqli_fake_packet();
++ $qr3->full = "05000003fe00002200";
++
++ $qr4 = new my_mysqli_fake_packet();
++ $qr4->full = "0400000401350174";
++
++ $qr5 = new my_mysqli_fake_packet();
++ $qr5->full = "05000005fe00002200";
++
++ return [$qr1, $qr2, $qr3, $qr4, $qr5];
++ }
++
++ public function server_upsert_query_response(): array
++ {
++ $qr1 = new my_mysqli_fake_packet();
++ $qr1->packet_length = "010000";
++ $qr1->packet_number = "01";
++ $qr1->field_count = "00"; // UPSERT
++ $qr1->affected_rows = "00";
++ $qr1->affected_rows = "00";
++ $qr1->last_insert_id = "00";
++ $qr1->server_status = "0000";
++ $qr1->warning_count = "0000";
++ $qr1->len = "01";
++ $qr1->filename = "65";
++ $qr1->packet_length = sprintf("%02x0000", strlen($qr1->to_bytes())-4);
++
++ return [$qr1];
++ }
++
++ public function server_stmt_prepare_response_start($num_field): my_mysqli_fake_packet
++ {
++ $pr1 = new my_mysqli_fake_packet();
++ $pr1->packet_length = "0c0000";
++ $pr1->packet_number = "01";
++ $pr1->response_code = '00'; // OK
++ $pr1->statement_id = '01000000';
++ $pr1->num_fields = $num_field;
++ $pr1->num_params = '0000';
++ $pr1->filler = '00';
++ $pr1->warnings = '0000';
++
++ return $pr1;
++ }
++
++ public function server_stmt_prepare_response_end($packer_number): my_mysqli_fake_packet
++ {
++ $pr3 = new my_mysqli_fake_packet();
++ $pr3->packet_length = "050000";
++ $pr3->packet_number = $packer_number;
++ $pr3->packet_type = 'fe'; // EOF
++ $pr3->warnings = '0000';
++ $pr3->server_status = '0200';
++
++ return $pr3;
++ }
++
++ public function server_stmt_prepare_items_response(): array
++ {
++ $pr1 = $this->server_stmt_prepare_response_start('0100');
++
++ $pr2 = new my_mysqli_fake_packet();
++ $pr2->packet_length = "300000";
++ $pr2->packet_number = "02";
++ $pr2->catalogue_len = '03';
++ $pr2->catalogue = '646566'; // def
++ $pr2->db_len = '08';
++ $pr2->db = '7068705f74657374'; // php_test
++ $pr2->table_len = '05';
++ $pr2->table = '6974656d73'; // items
++ $pr2->orig_table_len = '05';
++ $pr2->orig_table = '6974656d73'; // items
++ $pr2->name_len = '04';
++ $pr2->name = '6974656d';
++ $pr2->orig_name_len = '04';
++ $pr2->orig_name = '6974656d';
++ $pr2->something = '0c';
++ $pr2->charset = 'e000';
++ $pr2->length = 'c8000000';
++ $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING
++ $pr2->flags = '0110';
++ $pr2->decimal = '00';
++ $pr2->padding = '0000';
++
++ $pr3 = $this->server_stmt_prepare_response_end('03');
++
++ return [$pr1, $pr2, $pr3];
++ }
++
++ public function server_stmt_prepare_data_response_field($packet_number, $field_name): my_mysqli_fake_packet
++ {
++ if (strlen($field_name) != 6) {
++ throw new Exception("Invalid field length - only 6 is allowed");
++ }
++
++ $field = my_mysqli_data_field($field_name);
++
++ $pr = new my_mysqli_fake_packet();
++ $pr->packet_length = "320000";
++ $pr->packet_number = $packet_number;
++ $pr->catalogue_len = '03';
++ $pr->catalogue = bin2hex('def');
++ $pr->db_len = '08';
++ $pr->db = bin2hex('php_test');
++ $pr->table_len = '04';
++ $pr->table = bin2hex('data');
++ $pr->orig_table_len = '04';
++ $pr->orig_table = bin2hex('data');
++ $pr->name_len = '06';
++ $pr->name = bin2hex($field_name);
++ $pr->orig_name_len = '06';
++ $pr->orig_name = bin2hex($field_name);
++ $pr->something = '0c';
++ $pr->charset = $field['charset'];
++ $pr->length = $field['length'];
++ $pr->field_type = $field['type'];
++ $pr->flags = $field['flags'];
++ $pr->decimal = $field['decimal'];
++ $pr->padding = '0000';
++
++ return $pr;
++ }
++
++ public function server_stmt_prepare_data_response(string $field_name): array
++ {
++ $pr1 = $this->server_stmt_prepare_response_start('0200');
++
++ $pr2 = $this->server_stmt_prepare_data_response_field('02', 'strval');
++ $pr3 = $this->server_stmt_prepare_data_response_field('03', $field_name);
++
++ $pr4 = $this->server_stmt_prepare_response_end('04');
++
++ return [$pr1, $pr2, $pr3, $pr4];
++ }
++
++ public function server_stmt_execute_items_response(): array
++ {
++ $pr1 = new my_mysqli_fake_packet();
++ $pr1->packet_length = "010000";
++ $pr1->packet_number = "01";
++ $pr1->num_fields = '01';
++
++ $pr2 = new my_mysqli_fake_packet();
++ $pr2->packet_length = "300000";
++ $pr2->packet_number = "02";
++ $pr2->catalogue_len = '03';
++ $pr2->catalogue = '646566'; // def
++ $pr2->db_len = '08';
++ $pr2->db = '7068705f74657374'; // php_test
++ $pr2->table_len = '05';
++ $pr2->table = '6974656d73'; // items
++ $pr2->orig_table_len = '05';
++ $pr2->orig_table = '6974656d73'; // items
++ $pr2->name_len = '04';
++ $pr2->name = '6974656d';
++ $pr2->orig_name_len = '04';
++ $pr2->orig_name = '6974656d';
++ $pr2->something = '0c';
++ $pr2->charset = 'e000';
++ $pr2->length = 'c8000000';
++ $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING
++ $pr2->flags = '0110';
++ $pr2->decimal = '00';
++ $pr2->padding = '0000';
++
++ $pr3 = new my_mysqli_fake_packet();
++ $pr3->packet_length = "050000";
++ $pr3->packet_number = "03";
++ $pr3->packet_type = 'fe'; // EOF
++ $pr3->warnings = '0000';
++ $pr3->server_status = '2200';
++
++ $pr4 = new my_mysqli_fake_packet();
++ $pr4->packet_length = "070000";
++ $pr4->packet_number = "04";
++ $pr4->packet_type = '00'; // OK
++ $pr4->affected_rows = '00';
++ $pr4->row_data_len = '04';
++ $pr4->row_data = '74657374'; // item
++
++ $pr5 = new my_mysqli_fake_packet();
++ $pr5->full = '05000005fe00002200';
++
++ return [$pr1, $pr2, $pr3, $pr4, $pr5];
++ }
++
++ private function server_execute_data_response_start(string $field_name): array
++ {
++ $pr1 = new my_mysqli_fake_packet();
++ $pr1->packet_length = "010000";
++ $pr1->packet_number = "01";
++ $pr1->num_fields = '02';
++
++ $pr2 = new my_mysqli_fake_packet();
++ $pr2->packet_length = "320000";
++ $pr2->packet_number = "02";
++ $pr2->catalogue_len = '03';
++ $pr2->catalogue = '646566'; // def
++ $pr2->db_len = '08';
++ $pr2->db = '7068705f74657374'; // php_test
++ $pr2->table_len = '04';
++ $pr2->table = bin2hex('data');
++ $pr2->orig_table_len = '04';
++ $pr2->orig_table = bin2hex('data');
++ $pr2->name_len = '06';
++ $pr2->name = bin2hex('strval');
++ $pr2->orig_name_len = '06';
++ $pr2->orig_name = bin2hex('strval');
++ $pr2->something = '0c';
++ $pr2->charset = 'e000';
++ $pr2->length = 'c8000000';
++ $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING
++ $pr2->flags = '0110';
++ $pr2->decimal = '00';
++ $pr2->padding = '0000';
++
++ $field = my_mysqli_data_field($field_name);
++
++ $pr3 = new my_mysqli_fake_packet();
++ $pr3->packet_length = "320000";
++ $pr3->packet_number = "03";
++ $pr3->catalogue_len = '03';
++ $pr3->catalogue = '646566'; // def
++ $pr3->db_len = '08';
++ $pr3->db = '7068705f74657374'; // php_test
++ $pr3->table_len = '04';
++ $pr3->table = bin2hex('data');
++ $pr3->orig_table_len = '04';
++ $pr3->orig_table = bin2hex('data');
++ $pr3->name_len = '06';
++ $pr3->name = bin2hex($field_name);
++ $pr3->orig_name_len = '06';
++ $pr3->orig_name = bin2hex($field_name);
++ $pr3->something = '0c';
++ $pr3->charset = $field['charset'];
++ $pr3->length = $field['length'];
++ $pr3->field_type = $field['type'];
++ $pr3->flags = $field['flags'];
++ $pr3->decimal = $field['decimal'];
++ $pr3->padding = '0000';
++
++ $pr4 = new my_mysqli_fake_packet();
++ $pr4->packet_length = "050000";
++ $pr4->packet_number = "04";
++ $pr4->packet_type = 'fe'; // EOF
++ $pr4->warnings = '0000';
++ $pr4->server_status = '2200';
++
++ return [$field, $pr1, $pr2, $pr3, $pr4];
++ }
++
++ private function server_execute_data_response_end(): my_mysqli_fake_packet
++ {
++ $pr6 = new my_mysqli_fake_packet();
++ $pr6->packet_length = '050000';
++ $pr6->packet_number = "06";
++ $pr6->packet_type = 'fe'; // EOF
++ $pr6->warnings = '0000';
++ $pr6->server_status = '2200';
++
++ return $pr6;
++ }
++
++ public function server_stmt_execute_data_response(string $field_name): array
++ {
++ [$field, $pr1, $pr2, $pr3, $pr4] = $this->server_execute_data_response_start($field_name);
++
++ $pr5 = new my_mysqli_fake_packet();
++ $pr5->packet_length = $field['stmt_data_packet_length'];
++ $pr5->packet_number = "05";
++ $pr5->packet_type = '00'; // OK
++ $pr5->affected_rows = '00';
++ $pr5->row_field1_len = '04';
++ $pr5->row_field1_data = '74657374'; // test
++ $pr5->row_field2 = $field['stmt_data_value'];
++
++ return [$pr1, $pr2, $pr3, $pr4, $pr5, $this->server_execute_data_response_end()];
++ }
++
++ public function server_query_execute_data_response(string $field_name): array
++ {
++ [$field, $pr1, $pr2, $pr3, $pr4] = $this->server_execute_data_response_start($field_name);
++
++ $pr5 = new my_mysqli_fake_packet();
++ $pr5->packet_length = $field['query_data_packet_length'];
++ $pr5->packet_number = "05";
++ $pr5->row_field1_len = '04';
++ $pr5->row_field1_data = '74657374'; // test
++ $pr5->row_field2 = $field['query_data_value'];
++
++ return [$pr1, $pr2, $pr3, $pr4, $pr5, $this->server_execute_data_response_end()];
++ }
++}
++
++class my_mysqli_fake_server_conn
++{
++ private $conn;
++ public $packet_generator;
++
++ public function __construct($socket)
++ {
++ $this->packet_generator = new my_mysqli_fake_packet_generator();
++ $this->conn = stream_socket_accept($socket);
++ if ($this->conn) {
++ fprintf(STDERR, "[*] Connection established\n");
++ } else {
++ fprintf(STDERR, "[*] Failed to establish connection\n");
++ }
++ }
++
++ public function packets_to_bytes(array $packets): string
++ {
++ return implode('', array_map(fn($s) => $s->to_bytes(), $packets));
++ }
++
++ public function send($payload, $message = null): void
++ {
++ if ($message) {
++ fprintf(STDERR, "[*] Sending - %s: %s\n", $message, bin2hex($payload));
++ }
++ fwrite($this->conn, $payload);
++ }
++
++ public function read($bytes_len = 1024)
++ {
++ // wait 10ms to fill the buffer
++ usleep(10000);
++ $data = fread($this->conn, $bytes_len);
++ if ($data) {
++ fprintf(STDERR, "[*] Received: %s\n", bin2hex($data));
++ }
++ }
++
++ public function close()
++ {
++ fclose($this->conn);
++ }
++
++ public function send_server_greetings()
++ {
++ $this->send($this->packet_generator->server_greetings()->to_bytes(), "Server Greeting");
++ }
++
++ public function send_server_ok()
++ {
++ $this->send($this->packet_generator->server_ok()->to_bytes(), "Server OK");
++ }
++
++ public function send_server_tabular_query_response(): void
++ {
++ $packets = $this->packet_generator->server_tabular_query_response();
++ $this->send($this->packets_to_bytes($packets), "Tabular response");
++ }
++
++ public function send_server_stmt_prepare_items_response(): void
++ {
++ $packets = $this->packet_generator->server_stmt_prepare_items_response();
++ $this->send($this->packets_to_bytes($packets), "Stmt prepare items");
++ }
++
++
++ public function send_server_stmt_prepare_data_response(string $field_name): void
++ {
++ $packets = $this->packet_generator->server_stmt_prepare_data_response($field_name);
++ $this->send($this->packets_to_bytes($packets), "Stmt prepare data $field_name");
++ }
++
++ public function send_server_stmt_execute_items_response(): void
++ {
++ $packets = $this->packet_generator->server_stmt_execute_items_response();
++ $this->send($this->packets_to_bytes($packets), "Stmt execute items");
++ }
++
++ public function send_server_stmt_execute_data_response(string $field_name): void
++ {
++ $packets = $this->packet_generator->server_stmt_execute_data_response($field_name);
++ $this->send($this->packets_to_bytes($packets), "Stmt execute data $field_name");
++ }
++
++ public function send_server_query_execute_data_response(string $field_name): void
++ {
++ $packets = $this->packet_generator->server_query_execute_data_response($field_name);
++ $this->send($this->packets_to_bytes($packets), "Query execute data $field_name");
++ }
++}
++
++class my_mysqli_fake_server_process
++{
++ public function __construct(private $process, private array $pipes) {}
++
++ public function terminate(bool $wait = false)
++ {
++ if ($wait) {
++ $this->wait();
++ }
++ proc_terminate($this->process);
++ }
++
++ public function wait()
++ {
++ echo fgets($this->pipes[1]);
++ }
++}
++
++function my_mysqli_test_tabular_response_def_over_read(my_mysqli_fake_server_conn $conn): void
++{
++ $rh = $conn->packet_generator->server_tabular_query_response();
++
++ // Length of the packet is modified to include the next added data
++ $rh[1]->packet_length = "1e0000";
++
++ // We add a length field encoded on 4 bytes which evaluates to 65536. If the process crashes because
++ // the heap has been overread, lower this value.
++ $rh[1]->extra_def_size = "fd000001"; # 65536
++
++ // Filler
++ $rh[1]->extra_def_data = "aa";
++
++ $trrh = $conn->packets_to_bytes($rh);
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $conn->send($trrh, "Malicious Tabular Response [Extract heap through buffer over-read]");
++ $conn->read(65536);
++}
++
++function my_mysqli_test_upsert_response_filename_over_read(my_mysqli_fake_server_conn $conn): void
++{
++ $rh = $conn->packet_generator->server_upsert_query_response();
++
++ // Set extra length to overread
++ $rh[0]->len = "fa";
++
++ $trrh = $conn->packets_to_bytes($rh);
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $conn->send($trrh, "Malicious Tabular Response [Extract heap through buffer over-read]");
++ $conn->read(65536);
++}
++
++function my_mysqli_test_auth_response_message_over_read(my_mysqli_fake_server_conn $conn): void
++{
++ $p = $conn->packet_generator->server_ok();
++ $p->packet_length = "090000";
++ $p->message_len = "fcff";
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send($p->to_bytes(), "Malicious OK Auth Response [Extract heap through buffer over-read]");
++ $conn->read();
++}
++
++function my_mysqli_test_stmt_response_row_over_read_string(my_mysqli_fake_server_conn $conn): void
++{
++ $rh = $conn->packet_generator->server_stmt_execute_items_response();
++
++ // Set extra length to overread
++ $rh[3]->row_data_len = "fa";
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $conn->send_server_stmt_prepare_items_response();
++ $conn->read();
++ $conn->send($conn->packets_to_bytes($rh), "Malicious Stmt Response for items [Extract heap through buffer over-read]");
++ $conn->read(65536);
++}
++
++function my_mysqli_test_stmt_response_row_over_read_two_fields(
++ my_mysqli_fake_server_conn $conn,
++ string $field_name,
++ string $row_field1_len = '06'
++): void {
++ $rh = $conn->packet_generator->server_stmt_execute_data_response($field_name);
++
++ // Set extra length to overread by two bytes
++ $rh[4]->row_field1_len = $row_field1_len;
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $conn->send_server_stmt_prepare_data_response($field_name);
++ $conn->read();
++ $conn->send(
++ $conn->packets_to_bytes($rh),
++ "Malicious Stmt Response for data $field_name [Extract heap through buffer over-read]"
++ );
++ $conn->read(65536);
++}
++
++function my_mysqli_test_stmt_response_row_over_read_int(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'intval');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_float(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'fltval');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_double(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'dblval');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_date(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'datval');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_time(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'timval', '0c');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_datetime(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'dtival');
++}
++
++function my_mysqli_test_stmt_response_row_no_space(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'strval', '09');
++}
++
++function my_mysqli_test_stmt_response_row_over_read_bit(my_mysqli_fake_server_conn $conn): void
++{
++ my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'bitval');
++}
++
++function my_mysqli_test_stmt_response_row_read_two_fields(my_mysqli_fake_server_conn $conn): void
++{
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $field_names = array_keys(my_mysqli_data_fields());
++ foreach ($field_names as $field_name) {
++ $conn->send_server_stmt_prepare_data_response($field_name);
++ $conn->read(65536);
++ $conn->send_server_stmt_execute_data_response($field_name);
++ $conn->read(65536);
++ }
++}
++
++function my_mysqli_test_query_response_row_length_overflow(my_mysqli_fake_server_conn $conn): void
++{
++ $rh = $conn->packet_generator->server_query_execute_data_response('strval');
++
++ // Set extra length to overread by two bytes
++ $rh[4]->row_field2 = 'fefefefefe';
++
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $conn->send($conn->packets_to_bytes($rh), "Malicious Query Response for data strval field [length overflow]");
++ $conn->read(65536);
++}
++
++function my_mysqli_test_query_response_row_read_two_fields(my_mysqli_fake_server_conn $conn): void
++{
++ $conn->send_server_greetings();
++ $conn->read();
++ $conn->send_server_ok();
++ $conn->read();
++ $field_names = array_keys(my_mysqli_data_fields());
++ foreach ($field_names as $field_name) {
++ $conn->send_server_query_execute_data_response($field_name);
++ $conn->read();
++ }
++}
++
++function run_fake_server(string $test_function, $port = 33305): void
++{
++ $address = '127.0.0.1';
++
++ $socket = @stream_socket_server("tcp://$address:$port", $errno, $errstr);
++ if (!$socket) {
++ die("Failed to create socket: $errstr ($errno)\n");
++ }
++ echo "[*] Server started\n";
++
++ try {
++ $conn = new my_mysqli_fake_server_conn($socket);
++ $test_function_name = 'my_mysqli_test_' . $test_function;
++ call_user_func($test_function_name, $conn);
++ $conn->close();
++ } catch (Exception $e) {
++ fprintf(STDERR, "[!] Exception: " . $e->getMessage() . "\n");
++ }
++
++ fclose($socket);
++
++ echo "[*] Server finished\n";
++}
++
++
++function run_fake_server_in_background($test_function, $port = 33305): my_mysqli_fake_server_process
++{
++ $command = [PHP_BINARY, '-n', __FILE__, 'mysqli_fake_server', $test_function, $port];
++
++ $descriptorspec = array(
++ 0 => array("pipe", "r"),
++ 1 => array("pipe", "w"),
++ 2 => STDERR,
++ );
++
++ $process = proc_open($command, $descriptorspec, $pipes);
++
++ if (is_resource($process)) {
++ return new my_mysqli_fake_server_process($process, $pipes);
++ } else {
++ throw new Exception("Failed to start server process");
++ }
++}
++
++if (isset($argv) && $argc > 2 && $argv[1] == 'mysqli_fake_server') {
++ run_fake_server($argv[2], $argv[3] ?? '33305');
++}
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+new file mode 100644
+index 00000000000..db54a6c0177
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+@@ -0,0 +1,38 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - auth message buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 50001;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('auth_response_message_over_read', $port);
++$process->wait();
++
++try {
++ $conn = new mysqli( $servername, $username, $password, "", $port );
++ $info = mysqli_info($conn);
++ var_dump($info);
++} catch (Exception $e) {
++ echo $e->getMessage() . PHP_EOL;
++}
++
++$process->terminate();
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Malicious OK Auth Response [Extract heap through buffer over-read]: 0900000200000002000000fcff
++
++Warning: mysqli::__construct(): OK packet message length is past the packet size in %s on line %d
++Unknown error while trying to connect via tcp://127.0.0.1:50001
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt
+new file mode 100644
+index 00000000000..77f2232eca6
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt
+@@ -0,0 +1,47 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - tabular default)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('tabular_response_def_over_read', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Running query on the fake server...\n";
++
++$result = $conn->query("SELECT * from users");
++
++if ($result) {
++ $all_fields = $result->fetch_fields();
++ var_dump($result->fetch_all(MYSQLI_ASSOC));
++ var_dump(get_object_vars($all_fields[0])["def"]);
++}
++
++$conn->close();
++
++$process->terminate();
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Running query on the fake server...
++[*] Received: 140000000353454c454354202a2066726f6d207573657273
++[*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 01000001011e0000020164016401640164016401640c3f000b000000030350000000fd000001aa05000003fe00002200040000040135017405000005fe00002200
++
++Warning: mysqli::query(): Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%d) in %s on line %d
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt
+new file mode 100644
+index 00000000000..0b4db8ccece
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt
+@@ -0,0 +1,43 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - upsert filename buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('upsert_response_filename_over_read', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++echo "[*] Running query on the fake server...\n";
++
++$result = $conn->query("SELECT * from users");
++$info = mysqli_info($conn);
++
++var_dump($info);
++
++$process->terminate();
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Running query on the fake server...
++[*] Received: 140000000353454c454354202a2066726f6d207573657273
++[*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 0900000100000000000000fa65
++
++Warning: mysqli::query(): RSET_HEADER packet additional data length is past 249 bytes the packet size in %s on line %d
++
++Warning: mysqli::query(): Error reading result set's header in %s on line %d
++NULL
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt
+new file mode 100644
+index 00000000000..f141a79bdaa
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt
+@@ -0,0 +1,48 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row no space for the field)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('query_response_row_length_overflow', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Query the fake server...\n";
++$sql = "SELECT strval, strval FROM data";
++
++$result = $conn->query($sql);
++
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row['strval']);
++ }
++}
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Query the fake server...
++[*] Received: 200000000353454c4543542073747276616c2c2073747276616c2046524f4d2064617461
++[*] Sending - Malicious Query Response for data strval field [length overflow]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000a0000050474657374fefefefefe05000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after end of packet in %s on line %d
++[*] Received: 0100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt
+new file mode 100644
+index 00000000000..e43518217eb
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row bit buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_bit', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT bitval, timval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["bitval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542062697476616c2c2074696d76616c2046524f4d2064617461
++[*] Sending - Stmt prepare data bitval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data bitval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00002200100000050000067465737408080808080808080805000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt
+new file mode 100644
+index 00000000000..76158e940d0
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row date buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_date', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, datval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["datval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c2064617476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data datval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data datval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022000c0000050000067465737404de070c0f05000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt
+new file mode 100644
+index 00000000000..f53d5b83bd4
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row datetime buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_datetime', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, dtival FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["dtival"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c2064746976616c2046524f4d2064617461
++[*] Sending - Stmt prepare data dtival: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data dtival [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe000022000f0000050000067465737407de070c100d000105000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt
+new file mode 100644
+index 00000000000..03c9b045d73
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row double buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_double', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, dblval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["dblval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c2064626c76616c2046524f4d2064617461
++[*] Sending - Stmt prepare data dblval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data dblval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe000022000f00000500000674657374333333333333f33f05000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt
+new file mode 100644
+index 00000000000..b1ec9aa51ec
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row int buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_float', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, fltval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["fltval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c20666c7476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data fltval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data fltval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe000022000b000005000006746573743333134005000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt
+new file mode 100644
+index 00000000000..426d9ea7b3f
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row int buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_int', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, intval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["intval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c20696e7476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data intval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data intval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe000022000b000005000006746573740e00000005000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt
+new file mode 100644
+index 00000000000..6db6952d42a
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row no space for the field)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_no_space', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, strval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["strval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c2073747276616c2046524f4d2064617461
++[*] Sending - Stmt prepare data strval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data strval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000c00000500000974657374047465737405000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. No packet space left for the field in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt
+new file mode 100644
+index 00000000000..55bad4cc544
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row string buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_string', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT item FROM items");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["item"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 170000001653454c454354206974656d2046524f4d206974656d73
++[*] Sending - Stmt prepare items: 0c0000010001000000010000000000003000000203646566087068705f74657374056974656d73056974656d73046974656d046974656d0ce000c8000000fd011000000005000003fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for items [Extract heap through buffer over-read]: 01000001013000000203646566087068705f74657374056974656d73056974656d73046974656d046974656d0ce000c8000000fd011000000005000003fe00002200070000040000fa7465737405000005fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt
+new file mode 100644
+index 00000000000..06918c375f3
+--- /dev/null
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt
+@@ -0,0 +1,53 @@
++--TEST--
++GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row time buffer over-read)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_over_read_time', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++echo "[*] Preparing statement on the fake server...\n";
++$stmt = $conn->prepare("SELECT strval, timval FROM data");
++
++$stmt->execute();
++$result = $stmt->get_result();
++
++// Fetch and display the results
++if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row["timval"]);
++ }
++}
++$stmt->close();
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECTF--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Preparing statement on the fake server...
++[*] Received: 200000001653454c4543542073747276616c2c2074696d76616c2046524f4d2064617461
++[*] Sending - Stmt prepare data timval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Malicious Stmt Response for data timval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe000022001000000500000c7465737408000000000015080105000006fe00002200
++
++Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/protocol_query_row_fetch_data.phpt b/ext/mysqli/tests/protocol_query_row_fetch_data.phpt
+new file mode 100644
+index 00000000000..524fe5e587c
+--- /dev/null
++++ b/ext/mysqli/tests/protocol_query_row_fetch_data.phpt
+@@ -0,0 +1,74 @@
++--TEST--
++MySQL protocol - statement row data fetch)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('query_response_row_read_two_fields', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++function my_query($conn, $field)
++{
++ $sql = "SELECT strval, $field FROM data";
++
++ $result = $conn->query($sql);
++
++ if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row[$field]);
++ }
++ }
++}
++
++foreach (my_mysqli_data_fields() as $field_name => $field) {
++ my_query($conn, $field_name);
++}
++
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECT--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Received: 200000000353454c4543542073747276616c2c20696e7476616c2046524f4d2064617461
++[*] Sending - Query execute data intval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe0000220008000005047465737402313405000006fe00002200
++string(2) "14"
++[*] Received: 200000000353454c4543542073747276616c2c20666c7476616c2046524f4d2064617461
++[*] Sending - Query execute data fltval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe0000220009000005047465737403322e3305000006fe00002200
++string(3) "2.3"
++[*] Received: 200000000353454c4543542073747276616c2c2064626c76616c2046524f4d2064617461
++[*] Sending - Query execute data dblval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe0000220009000005047465737403312e3205000006fe00002200
++string(3) "1.2"
++[*] Received: 200000000353454c4543542073747276616c2c2064617476616c2046524f4d2064617461
++[*] Sending - Query execute data datval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022001000000504746573740a323031342d31322d313505000006fe00002200
++string(10) "2014-12-15"
++[*] Received: 200000000353454c4543542073747276616c2c2074696d76616c2046524f4d2064617461
++[*] Sending - Query execute data timval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe000022000e00000504746573740831333a30303a303205000006fe00002200
++string(8) "13:00:02"
++[*] Received: 200000000353454c4543542073747276616c2c2064746976616c2046524f4d2064617461
++[*] Sending - Query execute data dtival: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe0000220019000005047465737413323031342d31322d31362031333a30303a303105000006fe00002200
++string(19) "2014-12-16 13:00:01"
++[*] Received: 200000000353454c4543542073747276616c2c2062697476616c2046524f4d2064617461
++[*] Sending - Query execute data bitval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe000022000e000005047465737408080808080808080805000006fe00002200
++string(18) "578721382704613384"
++[*] Received: 200000000353454c4543542073747276616c2c2073747276616c2046524f4d2064617461
++[*] Sending - Query execute data strval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000a0000050474657374047465737405000006fe00002200
++string(4) "test"
++[*] Received: 0100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt b/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt
+new file mode 100644
+index 00000000000..d461ec24b8c
+--- /dev/null
++++ b/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt
+@@ -0,0 +1,91 @@
++--TEST--
++MySQL protocol - statement row data fetch)
++--EXTENSIONS--
++mysqli
++--FILE--
++<?php
++require_once 'fake_server.inc';
++
++$port = 33305;
++$servername = "127.0.0.1";
++$username = "root";
++$password = "";
++
++$process = run_fake_server_in_background('stmt_response_row_read_two_fields', $port);
++$process->wait();
++
++$conn = new mysqli($servername, $username, $password, "", $port);
++
++function my_query($conn, $field)
++{
++ $stmt = $conn->prepare("SELECT strval, $field FROM data");
++
++ $stmt->execute();
++ $result = $stmt->get_result();
++
++ if ($result->num_rows > 0) {
++ while ($row = $result->fetch_assoc()) {
++ var_dump($row[$field]);
++ }
++ }
++}
++
++foreach (my_mysqli_data_fields() as $field_name => $field) {
++ my_query($conn, $field_name);
++}
++
++$conn->close();
++
++$process->terminate(true);
++
++print "done!";
++?>
++--EXPECT--
++[*] Server started
++[*] Connection established
++[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
++[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31
++[*] Sending - Server OK: 0700000200000002000000
++[*] Received: 200000001653454c4543542073747276616c2c20696e7476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data intval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data intval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe000022000b000005000004746573740e00000005000006fe00002200
++int(14)
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c20666c7476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data fltval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data fltval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe000022000b000005000004746573743333134005000006fe00002200
++float(2.3)
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064626c76616c2046524f4d2064617461
++[*] Sending - Stmt prepare data dblval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data dblval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe000022000f00000500000474657374333333333333f33f05000006fe00002200
++float(1.2)
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064617476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data datval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data datval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022000c0000050000047465737404de070c0f05000006fe00002200
++string(10) "2014-12-15"
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2074696d76616c2046524f4d2064617461
++[*] Sending - Stmt prepare data timval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data timval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00002200100000050000047465737408000000000015080105000006fe00002200
++string(8) "21:08:01"
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064746976616c2046524f4d2064617461
++[*] Sending - Stmt prepare data dtival: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data dtival: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe000022000f0000050000047465737407de070c100d000105000006fe00002200
++string(19) "2014-12-16 13:00:01"
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2062697476616c2046524f4d2064617461
++[*] Sending - Stmt prepare data bitval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data bitval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00002200100000050000047465737408080808080808080805000006fe00002200
++int(578721382704613384)
++[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2073747276616c2046524f4d2064617461
++[*] Sending - Stmt prepare data strval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe00000200
++[*] Received: 0a00000017010000000001000000
++[*] Sending - Stmt execute data strval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000c00000500000474657374047465737405000006fe00002200
++string(4) "test"
++[*] Received: 0500000019010000000100000001
++[*] Server finished
++done!
+diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
+index e942f10faca..736d777b43a 100644
+--- a/ext/mysqlnd/mysqlnd_ps_codec.c
++++ b/ext/mysqlnd/mysqlnd_ps_codec.c
+@@ -50,6 +50,37 @@ struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
+ #define MYSQLND_PS_SKIP_RESULT_W_LEN -1
+ #define MYSQLND_PS_SKIP_RESULT_STR -2
+
++static inline void ps_fetch_over_read_error(const zend_uchar ** row)
++{
++ php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing after the end of packet");
++ *row = NULL;
++}
++
++static inline bool ps_fetch_is_packet_over_read_with_variable_length(const unsigned int pack_len,
++ const zend_uchar ** row, const zend_uchar *p, unsigned int length)
++{
++ if (pack_len == 0) {
++ return false;
++ }
++ size_t length_len = *row - p;
++ if (length_len > pack_len || length > pack_len - length_len) {
++ ps_fetch_over_read_error(row);
++ return true;
++ }
++ return false;
++}
++
++static inline bool ps_fetch_is_packet_over_read_with_static_length(const unsigned int pack_len,
++ const zend_uchar ** row, unsigned int length)
++{
++ if (pack_len > 0 && length > pack_len) {
++ ps_fetch_over_read_error(row);
++ return true;
++ }
++ return false;
++}
++
++
+ /* {{{ ps_fetch_from_1_to_8_bytes */
+ void
+ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len,
+@@ -58,6 +89,11 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const u
+ char tmp[22];
+ size_t tmp_len = 0;
+ zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
++
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, byte_count))) {
++ return;
++ }
++
+ DBG_ENTER("ps_fetch_from_1_to_8_bytes");
+ DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count);
+ if (field->flags & UNSIGNED_FLAG) {
+@@ -176,6 +212,11 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, const unsigned int
+ float fval;
+ double dval;
+ DBG_ENTER("ps_fetch_float");
++
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, 4))) {
++ return;
++ }
++
+ float4get(fval, *row);
+ (*row)+= 4;
+ DBG_INF_FMT("value=%f", fval);
+@@ -198,6 +239,11 @@ ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, const unsigned int
+ {
+ double value;
+ DBG_ENTER("ps_fetch_double");
++
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, 8))) {
++ return;
++ }
++
+ float8get(value, *row);
+ ZVAL_DOUBLE(zv, value);
+ (*row)+= 8;
+@@ -214,9 +260,14 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, const unsigned int p
+ struct st_mysqlnd_time t;
+ zend_ulong length; /* First byte encodes the length*/
+ char * value;
++ const zend_uchar *p = *row;
+ DBG_ENTER("ps_fetch_time");
+
+ if ((length = php_mysqlnd_net_field_length(row))) {
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) {
++ return;
++ }
++
+ const zend_uchar * to = *row;
+
+ t.time_type = MYSQLND_TIMESTAMP_TIME;
+@@ -271,9 +322,14 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, const unsigned int p
+ struct st_mysqlnd_time t = {0};
+ zend_ulong length; /* First byte encodes the length*/
+ char * value;
++ const zend_uchar *p = *row;
+ DBG_ENTER("ps_fetch_date");
+
+ if ((length = php_mysqlnd_net_field_length(row))) {
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) {
++ return;
++ }
++
+ const zend_uchar * to = *row;
+
+ t.time_type = MYSQLND_TIMESTAMP_DATE;
+@@ -308,9 +364,14 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, const unsigned i
+ struct st_mysqlnd_time t;
+ zend_ulong length; /* First byte encodes the length*/
+ char * value;
++ const zend_uchar *p = *row;
+ DBG_ENTER("ps_fetch_datetime");
+
+ if ((length = php_mysqlnd_net_field_length(row))) {
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) {
++ return;
++ }
++
+ const zend_uchar * to = *row;
+
+ t.time_type = MYSQLND_TIMESTAMP_DATETIME;
+@@ -369,7 +430,11 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, const unsigned int
+ For now just copy, before we make it possible
+ to write \0 to the row buffer
+ */
++ const zend_uchar *p = *row;
+ const zend_ulong length = php_mysqlnd_net_field_length(row);
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) {
++ return;
++ }
+ DBG_ENTER("ps_fetch_string");
+ DBG_INF_FMT("len = %lu", length);
+ DBG_INF("copying from the row buffer");
+@@ -385,7 +450,11 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, const unsigned int
+ static void
+ ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
+ {
++ const zend_uchar *p = *row;
+ const zend_ulong length = php_mysqlnd_net_field_length(row);
++ if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) {
++ return;
++ }
+ ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length);
+ }
+ /* }}} */
+diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
+index 5b63e09f71e..011ba34cb5e 100644
+--- a/ext/mysqlnd/mysqlnd_result.c
++++ b/ext/mysqlnd/mysqlnd_result.c
+@@ -503,7 +503,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
+ if (FAIL == (ret = result->m.read_result_metadata(result, conn))) {
+ /* For PS, we leave them in Prepared state */
+ if (!stmt && conn->current_result) {
+- mnd_efree(conn->current_result);
++ conn->current_result->m.free_result(conn->current_result, TRUE);
+ conn->current_result = NULL;
+ }
+ DBG_ERR("Error occurred while reading metadata");
+diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
+index 664a993322d..929ea422924 100644
+--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
++++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
+@@ -721,7 +721,14 @@ php_mysqlnd_auth_response_read(MYSQLND_CONN_DATA * conn, void * _packet)
+
+ /* There is a message */
+ if (packet->header.size > (size_t) (p - buf) && (net_len = php_mysqlnd_net_field_length(&p))) {
+- packet->message_len = MIN(net_len, buf_len - (p - begin));
++ /* p can get past packet size when getting field length so it needs to be checked first
++ * and after that it can be checked that the net_len is not greater than the packet size */
++ if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < net_len) {
++ DBG_ERR_FMT("OK packet message length is past the packet size");
++ php_error_docref(NULL, E_WARNING, "OK packet message length is past the packet size");
++ DBG_RETURN(FAIL);
++ }
++ packet->message_len = net_len;
+ packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
+ } else {
+ packet->message = NULL;
+@@ -1110,6 +1117,17 @@ php_mysqlnd_rset_header_read(MYSQLND_CONN_DATA * conn, void * _packet)
+ BAIL_IF_NO_MORE_DATA;
+ /* Check for additional textual data */
+ if (packet->header.size > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
++ /* p can get past packet size when getting field length so it needs to be checked first
++ * and after that it can be checked that the len is not greater than the packet size */
++ if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < len) {
++ size_t local_file_name_over_read = ((p - buf) - packet->header.size) + len;
++ DBG_ERR_FMT("RSET_HEADER packet additional data length is past %zu bytes the packet size",
++ local_file_name_over_read);
++ php_error_docref(NULL, E_WARNING,
++ "RSET_HEADER packet additional data length is past %zu bytes the packet size",
++ local_file_name_over_read);
++ DBG_RETURN(FAIL);
++ }
+ packet->info_or_local_file.s = mnd_emalloc(len + 1);
+ if (packet->info_or_local_file.s) {
+ memcpy(packet->info_or_local_file.s, p, len);
+@@ -1268,23 +1286,16 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
+ meta->flags |= NUM_FLAG;
+ }
+
+-
+- /*
+- def could be empty, thus don't allocate on the root.
+- NULL_LENGTH (0xFB) comes from COM_FIELD_LIST when the default value is NULL.
+- Otherwise the string is length encoded.
+- */
++ /* COM_FIELD_LIST is no longer supported so def should not be present */
+ if (packet->header.size > (size_t) (p - buf) &&
+ (len = php_mysqlnd_net_field_length(&p)) &&
+ len != MYSQLND_NULL_LENGTH)
+ {
+- BAIL_IF_NO_MORE_DATA;
+- DBG_INF_FMT("Def found, length %lu", len);
+- meta->def = packet->memory_pool->get_chunk(packet->memory_pool, len + 1);
+- memcpy(meta->def, p, len);
+- meta->def[len] = '\0';
+- meta->def_length = len;
+- p += len;
++ DBG_ERR_FMT("Protocol error. Server sent default for unsupported field list");
++ php_error_docref(NULL, E_WARNING,
++ "Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%u)",
++ __LINE__);
++ DBG_RETURN(FAIL);
+ }
+
+ root_ptr = meta->root = packet->memory_pool->get_chunk(packet->memory_pool, total_len);
+@@ -1451,8 +1462,10 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fi
+ const unsigned int field_count, const MYSQLND_FIELD * const fields_metadata,
+ const zend_bool as_int_or_float, MYSQLND_STATS * const stats)
+ {
+- unsigned int i;
+- const zend_uchar * p = row_buffer->ptr;
++ unsigned int i, j;
++ size_t rbs = row_buffer->size;
++ const zend_uchar * rbp = row_buffer->ptr;
++ const zend_uchar * p = rbp;
+ const zend_uchar * null_ptr;
+ zend_uchar bit;
+ zval *current_field, *end_field, *start_field;
+@@ -1485,7 +1498,21 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fi
+ statistic = STAT_BINARY_TYPE_FETCHED_NULL;
+ } else {
+ enum_mysqlnd_field_types type = fields_metadata[i].type;
+- mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], 0, &p);
++ size_t row_position = p - rbp;
++ if (rbs <= row_position) {
++ for (j = 0, current_field = start_field; j < i; current_field++, j++) {
++ zval_ptr_dtor(current_field);
++ }
++ php_error_docref(NULL, E_WARNING, "Malformed server packet. No packet space left for the field");
++ DBG_RETURN(FAIL);
++ }
++ mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], rbs - row_position, &p);
++ if (p == NULL) {
++ for (j = 0, current_field = start_field; j < i; current_field++, j++) {
++ zval_ptr_dtor(current_field);
++ }
++ DBG_RETURN(FAIL);
++ }
+
+ if (MYSQLND_G(collect_statistics)) {
+ switch (fields_metadata[i].type) {
+@@ -1542,7 +1569,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
+ unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
+ zend_bool as_int_or_float, MYSQLND_STATS * stats)
+ {
+- unsigned int i;
++ unsigned int i, j;
+ zval *current_field, *end_field, *start_field;
+ zend_uchar * p = row_buffer->ptr;
+ const size_t data_size = row_buffer->size;
+@@ -1563,9 +1590,11 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
+ /* NULL or NOT NULL, this is the question! */
+ if (len == MYSQLND_NULL_LENGTH) {
+ ZVAL_NULL(current_field);
+- } else if ((p + len) > packet_end) {
+- php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing "MYSQLND_SZ_T_SPEC
+- " bytes after end of packet", (p + len) - packet_end - 1);
++ } else if (p > packet_end || len > packet_end - p) {
++ php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing after end of packet");
++ for (j = 0, current_field = start_field; j < i; current_field++, j++) {
++ zval_ptr_dtor(current_field);
++ }
+ DBG_RETURN(FAIL);
+ } else {
+ #ifdef MYSQLND_STRING_TO_INT_CONVERSION
+--
+2.47.0
+
+From d5f9da0d6af72ae21b0a9f4c94c59dfdd409e3e2 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Mon, 18 Nov 2024 15:54:30 +0100
+Subject: [PATCH 2/6] Fix MySQLnd possible buffer over read in auth_protocol
+
+(cherry picked from commit 32f905f1d689aaa8eacd6331a18c0dd45972c3c1)
+---
+ ext/mysqlnd/mysqlnd_wireprotocol.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
+index 929ea422924..5499ebac967 100644
+--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
++++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
+@@ -447,8 +447,31 @@ php_mysqlnd_greet_read(MYSQLND_CONN_DATA * conn, void * _packet)
+ if (packet->server_capabilities & CLIENT_PLUGIN_AUTH) {
+ BAIL_IF_NO_MORE_DATA;
+ /* The server is 5.5.x and supports authentication plugins */
+- packet->auth_protocol = estrdup((char *)p);
+- p+= strlen(packet->auth_protocol) + 1; /* eat the '\0' */
++ size_t remaining_size = packet->header.size - (size_t)(p - buf);
++ if (remaining_size == 0) {
++ /* Might be better to fail but this will fail anyway */
++ packet->auth_protocol = estrdup("");
++ } else {
++ /* Check if NUL present */
++ char *null_terminator = memchr(p, '\0', remaining_size);
++ size_t auth_protocol_len;
++ if (null_terminator) {
++ /* If present, do basically estrdup */
++ auth_protocol_len = null_terminator - (char *)p;
++ } else {
++ /* If not present, copy the rest of the buffer */
++ auth_protocol_len = remaining_size;
++ }
++ char *auth_protocol = emalloc(auth_protocol_len + 1);
++ memcpy(auth_protocol, p, auth_protocol_len);
++ auth_protocol[auth_protocol_len] = '\0';
++ packet->auth_protocol = auth_protocol;
++
++ p += auth_protocol_len;
++ if (null_terminator) {
++ p++;
++ }
++ }
+ }
+
+ DBG_INF_FMT("proto=%u server=%s thread_id=%u",
+--
+2.47.0
+
+From 7e6af9c78d84d15880cfbc7867501f25ab982f5f Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 24 Nov 2024 20:13:47 +0100
+Subject: [PATCH 3/6] Change port for mysqli fake server auth message test
+
+(cherry picked from commit 51f5539914ae62ef8568ea1ed302dceda897c439)
+---
+ ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+index db54a6c0177..279aec6a2cb 100644
+--- a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+@@ -6,7 +6,7 @@ mysqli
+ <?php
+ require_once 'fake_server.inc';
+
+-$port = 50001;
++$port = 33305;
+ $servername = "127.0.0.1";
+ $username = "root";
+ $password = "";
+@@ -34,5 +34,5 @@ print "done!";
+ [*] Sending - Malicious OK Auth Response [Extract heap through buffer over-read]: 0900000200000002000000fcff
+
+ Warning: mysqli::__construct(): OK packet message length is past the packet size in %s on line %d
+-Unknown error while trying to connect via tcp://127.0.0.1:50001
++Unknown error while trying to connect via tcp://127.0.0.1:33305
+ done!
+--
+2.47.0
+
+From cae38b1c749d27dc3a65f7d65fdf238439e2676c Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 24 Nov 2024 23:48:27 +0100
+Subject: [PATCH 4/6] Increase MySQLi fake server read timeout for ASAN job
+
+(cherry picked from commit eb951b3d11109aa16982a2132f8d1fd5129edc9e)
+---
+ ext/mysqli/tests/fake_server.inc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/mysqli/tests/fake_server.inc b/ext/mysqli/tests/fake_server.inc
+index b02fabc584c..1127f6c00e3 100644
+--- a/ext/mysqli/tests/fake_server.inc
++++ b/ext/mysqli/tests/fake_server.inc
+@@ -552,8 +552,8 @@ class my_mysqli_fake_server_conn
+
+ public function read($bytes_len = 1024)
+ {
+- // wait 10ms to fill the buffer
+- usleep(10000);
++ // wait 20ms to fill the buffer
++ usleep(20000);
+ $data = fread($this->conn, $bytes_len);
+ if ($data) {
+ fprintf(STDERR, "[*] Received: %s\n", bin2hex($data));
+--
+2.47.0
+
+From 69853e12b73a989e2383452356cdc07172427ae3 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 27 Nov 2024 10:54:10 +0100
+Subject: [PATCH 5/6] Avoid using uninitialised struct
+
+ (cherry picked from commit 7e7817bc2f82570bbc510a2bf5e4e0ec09dbc774)
+---
+ ext/mysqlnd/mysqlnd_result.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
+index 011ba34cb5e..9dcbd046a43 100644
+--- a/ext/mysqlnd/mysqlnd_result.c
++++ b/ext/mysqlnd/mysqlnd_result.c
+@@ -547,8 +547,8 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
+ }
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic);
+ }
++ PACKET_FREE(&fields_eof);
+ } while (0);
+- PACKET_FREE(&fields_eof);
+ break; /* switch break */
+ }
+ } while (0);
+--
+2.47.0
+
+From 4c5f0e9541f675033aff30be6d08f629c8da01d5 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 27 Nov 2024 11:17:48 +0100
+Subject: [PATCH 6/6] adapt test + NEWS
+
+---
+ NEWS | 4 ++++
+ ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt | 3 +--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 0f82a65a44b..e043901ee96 100644
+--- a/NEWS
++++ b/NEWS
+@@ -11,6 +11,10 @@ Backported from 8.1.31
+ . Fixed bug GHSA-g665-fm4p-vhff (OOB access in ldap_escape). (CVE-2024-8932)
+ (nielsdos)
+
++- MySQLnd:
++ . Fixed bug GHSA-h35g-vwh6-m678 (Leak partial content of the heap through
++ heap buffer over-read). (CVE-2024-8929) (Jakub Zelenka)
++
+ - PDO DBLIB:
+ . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing
+ OOB writes). (CVE-2024-11236) (nielsdos)
+diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+index 279aec6a2cb..161c9a5b8e6 100644
+--- a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
++++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt
+@@ -34,5 +34,4 @@ print "done!";
+ [*] Sending - Malicious OK Auth Response [Extract heap through buffer over-read]: 0900000200000002000000fcff
+
+ Warning: mysqli::__construct(): OK packet message length is past the packet size in %s on line %d
+-Unknown error while trying to connect via tcp://127.0.0.1:33305
+-done!
++%A
+--
+2.47.0
+
diff --git a/php-cve-2024-8932.patch b/php-cve-2024-8932.patch
new file mode 100644
index 0000000..88e2e9f
--- /dev/null
+++ b/php-cve-2024-8932.patch
@@ -0,0 +1,130 @@
+From 9f367d847989b339c33369737daf573e30bab5f1 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Thu, 26 Sep 2024 22:22:27 +0200
+Subject: [PATCH 4/8] Fix GHSA-g665-fm4p-vhff: OOB access in ldap_escape
+
+(cherry picked from commit f9ecf90070a11dad09ca7671a712f81cc2a7d52f)
+---
+ ext/ldap/ldap.c | 20 ++++++++++++++--
+ ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt | 28 ++++++++++++++++++++++
+ ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt | 29 +++++++++++++++++++++++
+ 3 files changed, 75 insertions(+), 2 deletions(-)
+ create mode 100644 ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt
+ create mode 100644 ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt
+
+diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c
+index c4dfe0c5b07..6661310d055 100644
+--- a/ext/ldap/ldap.c
++++ b/ext/ldap/ldap.c
+@@ -3760,13 +3760,23 @@ static zend_string* php_ldap_do_escape(const zend_bool *map, const char *value,
+ zend_string *ret;
+
+ for (i = 0; i < valuelen; i++) {
+- len += (map[(unsigned char) value[i]]) ? 3 : 1;
++ size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1;
++ if (len > ZSTR_MAX_LEN - addend) {
++ return NULL;
++ }
++ len += addend;
+ }
+ /* Per RFC 4514, a leading and trailing space must be escaped */
+ if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) {
++ if (len > ZSTR_MAX_LEN - 2) {
++ return NULL;
++ }
+ len += 2;
+ }
+ if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) {
++ if (len > ZSTR_MAX_LEN - 2) {
++ return NULL;
++ }
+ len += 2;
+ }
+
+@@ -3833,7 +3843,13 @@ PHP_FUNCTION(ldap_escape)
+ php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0);
+ }
+
+- RETURN_NEW_STR(php_ldap_do_escape(map, value, valuelen, flags));
++ zend_string *result = php_ldap_do_escape(map, value, valuelen, flags);
++ if (UNEXPECTED(!result)) {
++ zend_argument_value_error(1, "is too long");
++ RETURN_THROWS();
++ }
++
++ RETURN_NEW_STR(result);
+ }
+
+ #ifdef STR_TRANSLATION
+diff --git a/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt b/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt
+new file mode 100644
+index 00000000000..8e2c4fb160d
+--- /dev/null
++++ b/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt
+@@ -0,0 +1,28 @@
++--TEST--
++GHSA-g665-fm4p-vhff (OOB access in ldap_escape)
++--EXTENSIONS--
++ldap
++--INI--
++memory_limit=-1
++--SKIPIF--
++<?php
++if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
++?>
++--FILE--
++<?php
++try {
++ ldap_escape(' '.str_repeat("#", 1431655758), "", LDAP_ESCAPE_DN);
++} catch (ValueError $e) {
++ echo $e->getMessage(), "\n";
++}
++
++try {
++ ldap_escape(str_repeat("#", 1431655758).' ', "", LDAP_ESCAPE_DN);
++} catch (ValueError $e) {
++ echo $e->getMessage(), "\n";
++}
++?>
++--EXPECT--
++ldap_escape(): Argument #1 ($value) is too long
++ldap_escape(): Argument #1 ($value) is too long
+diff --git a/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt b/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt
+new file mode 100644
+index 00000000000..a69597084be
+--- /dev/null
++++ b/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt
+@@ -0,0 +1,29 @@
++--TEST--
++GHSA-g665-fm4p-vhff (OOB access in ldap_escape)
++--EXTENSIONS--
++ldap
++--INI--
++memory_limit=-1
++--SKIPIF--
++<?php
++if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
++?>
++--FILE--
++<?php
++try {
++ ldap_escape(str_repeat("*", 1431655759), "", LDAP_ESCAPE_FILTER);
++} catch (ValueError $e) {
++ echo $e->getMessage(), "\n";
++}
++
++// would allocate a string of length 2
++try {
++ ldap_escape(str_repeat("*", 1431655766), "", LDAP_ESCAPE_FILTER);
++} catch (ValueError $e) {
++ echo $e->getMessage(), "\n";
++}
++?>
++--EXPECT--
++ldap_escape(): Argument #1 ($value) is too long
++ldap_escape(): Argument #1 ($value) is too long
+--
+2.47.0
+
diff --git a/php-cve-2025-1217.patch b/php-cve-2025-1217.patch
new file mode 100644
index 0000000..1778bae
--- /dev/null
+++ b/php-cve-2025-1217.patch
@@ -0,0 +1,909 @@
+From 4fec08542748c25573063ffc53ea89cd5de1edf0 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Tue, 31 Dec 2024 18:57:02 +0100
+Subject: [PATCH 01/11] Fix GHSA-ghsa-v8xr-gpvj-cx9g: http header folding
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds HTTP header folding support for HTTP wrapper response
+headers.
+
+Reviewed-by: Tim Düsterhus <tim@tideways-gmbh.com>
+(cherry picked from commit d20b4c97a9f883b62b65b82d939c5af9a2028ef1)
+---
+ ext/openssl/tests/ServerClientTestCase.inc | 65 +++-
+ ext/standard/http_fopen_wrapper.c | 343 ++++++++++++------
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt | 49 +++
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt | 51 +++
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt | 49 +++
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt | 48 +++
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt | 48 +++
+ .../tests/http/http_response_header_05.phpt | 30 --
+ 8 files changed, 534 insertions(+), 149 deletions(-)
+ create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
+ delete mode 100644 ext/standard/tests/http/http_response_header_05.phpt
+
+diff --git a/ext/openssl/tests/ServerClientTestCase.inc b/ext/openssl/tests/ServerClientTestCase.inc
+index 753366df6f4..61d45385b62 100644
+--- a/ext/openssl/tests/ServerClientTestCase.inc
++++ b/ext/openssl/tests/ServerClientTestCase.inc
+@@ -4,14 +4,19 @@ const WORKER_ARGV_VALUE = 'RUN_WORKER';
+
+ const WORKER_DEFAULT_NAME = 'server';
+
+-function phpt_notify($worker = WORKER_DEFAULT_NAME)
++function phpt_notify(string $worker = WORKER_DEFAULT_NAME, string $message = ""): void
+ {
+- ServerClientTestCase::getInstance()->notify($worker);
++ ServerClientTestCase::getInstance()->notify($worker, $message);
+ }
+
+-function phpt_wait($worker = WORKER_DEFAULT_NAME, $timeout = null)
++function phpt_wait($worker = WORKER_DEFAULT_NAME, $timeout = null): ?string
+ {
+- ServerClientTestCase::getInstance()->wait($worker, $timeout);
++ return ServerClientTestCase::getInstance()->wait($worker, $timeout);
++}
++
++function phpt_notify_server_start($server): void
++{
++ ServerClientTestCase::getInstance()->notify_server_start($server);
+ }
+
+ function phpt_has_sslv3() {
+@@ -119,43 +124,73 @@ class ServerClientTestCase
+ eval($code);
+ }
+
+- public function run($masterCode, $workerCode)
++ /**
++ * Run client and all workers
++ *
++ * @param string $clientCode The client PHP code
++ * @param string|array $workerCode
++ * @param bool $ephemeral Select whether automatic port selection and automatic awaiting is used
++ * @return void
++ * @throws Exception
++ */
++ public function run(string $clientCode, string|array $workerCode, bool $ephemeral = true): void
+ {
+ if (!is_array($workerCode)) {
+ $workerCode = [WORKER_DEFAULT_NAME => $workerCode];
+ }
+- foreach ($workerCode as $worker => $code) {
++ reset($workerCode);
++ $code = current($workerCode);
++ $worker = key($workerCode);
++ while ($worker != null) {
+ $this->spawnWorkerProcess($worker, $this->stripPhpTagsFromCode($code));
++ $code = next($workerCode);
++ if ($ephemeral) {
++ $addr = trim($this->wait($worker));
++ if (empty($addr)) {
++ throw new \Exception("Failed server start");
++ }
++ if ($code === false) {
++ $clientCode = preg_replace('/{{\s*ADDR\s*}}/', $addr, $clientCode);
++ } else {
++ $code = preg_replace('/{{\s*ADDR\s*}}/', $addr, $code);
++ }
++ }
++ $worker = key($workerCode);
+ }
+- eval($this->stripPhpTagsFromCode($masterCode));
++
++ eval($this->stripPhpTagsFromCode($clientCode));
+ foreach ($workerCode as $worker => $code) {
+ $this->cleanupWorkerProcess($worker);
+ }
+ }
+
+- public function wait($worker, $timeout = null)
++ public function wait($worker, $timeout = null): ?string
+ {
+ $handle = $this->isWorker ? STDIN : $this->workerStdOut[$worker];
+ if ($timeout === null) {
+- fgets($handle);
+- return true;
++ return fgets($handle);
+ }
+
+ stream_set_blocking($handle, false);
+ $read = [$handle];
+ $result = stream_select($read, $write, $except, $timeout);
+ if (!$result) {
+- return false;
++ return null;
+ }
+
+- fgets($handle);
++ $result = fgets($handle);
+ stream_set_blocking($handle, true);
+- return true;
++ return $result;
++ }
++
++ public function notify(string $worker, string $message = ""): void
++ {
++ fwrite($this->isWorker ? STDOUT : $this->workerStdIn[$worker], "$message\n");
+ }
+
+- public function notify($worker)
++ public function notify_server_start($server): void
+ {
+- fwrite($this->isWorker ? STDOUT : $this->workerStdIn[$worker], "\n");
++ echo stream_socket_get_name($server, false) . "\n";
+ }
+ }
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index 40e6f3dd4c3..bfc88a74545 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -114,6 +114,171 @@ static zend_bool check_has_header(const char *headers, const char *header) {
+ return 0;
+ }
+
++typedef struct _php_stream_http_response_header_info {
++ php_stream_filter *transfer_encoding;
++ size_t file_size;
++ bool follow_location;
++ char location[HTTP_HEADER_BLOCK_SIZE];
++} php_stream_http_response_header_info;
++
++static void php_stream_http_response_header_info_init(
++ php_stream_http_response_header_info *header_info)
++{
++ header_info->transfer_encoding = NULL;
++ header_info->file_size = 0;
++ header_info->follow_location = 1;
++ header_info->location[0] = '\0';
++}
++
++/* Trim white spaces from response header line and update its length */
++static bool php_stream_http_response_header_trim(char *http_header_line,
++ size_t *http_header_line_length)
++{
++ char *http_header_line_end = http_header_line + *http_header_line_length - 1;
++ while (http_header_line_end >= http_header_line &&
++ (*http_header_line_end == '\n' || *http_header_line_end == '\r')) {
++ http_header_line_end--;
++ }
++
++ /* The primary definition of an HTTP header in RFC 7230 states:
++ * > Each header field consists of a case-insensitive field name followed
++ * > by a colon (":"), optional leading whitespace, the field value, and
++ * > optional trailing whitespace. */
++
++ /* Strip trailing whitespace */
++ bool space_trim = (*http_header_line_end == ' ' || *http_header_line_end == '\t');
++ if (space_trim) {
++ do {
++ http_header_line_end--;
++ } while (http_header_line_end >= http_header_line &&
++ (*http_header_line_end == ' ' || *http_header_line_end == '\t'));
++ }
++ http_header_line_end++;
++ *http_header_line_end = '\0';
++ *http_header_line_length = http_header_line_end - http_header_line;
++
++ return space_trim;
++}
++
++/* Process folding headers of the current line and if there are none, parse last full response
++ * header line. It returns NULL if the last header is finished, otherwise it returns updated
++ * last header line. */
++static zend_string *php_stream_http_response_headers_parse(php_stream *stream,
++ php_stream_context *context, int options, zend_string *last_header_line_str,
++ char *header_line, size_t *header_line_length, int response_code,
++ zval *response_header, php_stream_http_response_header_info *header_info)
++{
++ char *last_header_line = ZSTR_VAL(last_header_line_str);
++ size_t last_header_line_length = ZSTR_LEN(last_header_line_str);
++ char *last_header_line_end = ZSTR_VAL(last_header_line_str) + ZSTR_LEN(last_header_line_str) - 1;
++
++ /* Process non empty header line. */
++ if (header_line && (*header_line != '\n' && *header_line != '\r')) {
++ /* Removing trailing white spaces. */
++ if (php_stream_http_response_header_trim(header_line, header_line_length) &&
++ *header_line_length == 0) {
++ /* Only spaces so treat as an empty folding header. */
++ return last_header_line_str;
++ }
++
++ /* Process folding headers if starting with a space or a tab. */
++ if (header_line && (*header_line == ' ' || *header_line == '\t')) {
++ char *http_folded_header_line = header_line;
++ size_t http_folded_header_line_length = *header_line_length;
++ /* Remove the leading white spaces. */
++ while (*http_folded_header_line == ' ' || *http_folded_header_line == '\t') {
++ http_folded_header_line++;
++ http_folded_header_line_length--;
++ }
++ /* It has to have some characters because it would get returned after the call
++ * php_stream_http_response_header_trim above. */
++ ZEND_ASSERT(http_folded_header_line_length > 0);
++ /* Concatenate last header line, space and current header line. */
++ zend_string *extended_header_str = zend_string_concat3(
++ last_header_line, last_header_line_length,
++ " ", 1,
++ http_folded_header_line, http_folded_header_line_length);
++ zend_string_efree(last_header_line_str);
++ last_header_line_str = extended_header_str;
++ /* Return new header line. */
++ return last_header_line_str;
++ }
++ }
++
++ /* Find header separator position. */
++ char *last_header_value = memchr(last_header_line, ':', last_header_line_length);
++ if (last_header_value) {
++ last_header_value++; /* Skip ':'. */
++
++ /* Strip leading whitespace. */
++ while (last_header_value < last_header_line_end
++ && (*last_header_value == ' ' || *last_header_value == '\t')) {
++ last_header_value++;
++ }
++ } else {
++ /* There is no colon. Set the value to the end of the header line, which is effectively
++ * an empty string. */
++ last_header_value = last_header_line_end;
++ }
++
++ bool store_header = true;
++ zval *tmpzval = NULL;
++
++ if (!strncasecmp(last_header_line, "Location:", sizeof("Location:")-1)) {
++ /* Check if the location should be followed. */
++ if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) {
++ header_info->follow_location = zval_is_true(tmpzval);
++ } else if (!((response_code >= 300 && response_code < 304)
++ || 307 == response_code || 308 == response_code)) {
++ /* The redirection should not be automatic if follow_location is not set and
++ * response_code not in (300, 301, 302, 303 and 307)
++ * see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1
++ * RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
++ header_info->follow_location = 0;
++ }
++ strlcpy(header_info->location, last_header_value, sizeof(header_info->location));
++ } else if (!strncasecmp(last_header_line, "Content-Type:", sizeof("Content-Type:")-1)) {
++ php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, last_header_value, 0);
++ } else if (!strncasecmp(last_header_line, "Content-Length:", sizeof("Content-Length:")-1)) {
++ header_info->file_size = atoi(last_header_value);
++ php_stream_notify_file_size(context, header_info->file_size, last_header_line, 0);
++ } else if (
++ !strncasecmp(last_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1)
++ && !strncasecmp(last_header_value, "Chunked", sizeof("Chunked")-1)
++ ) {
++ /* Create filter to decode response body. */
++ if (!(options & STREAM_ONLY_GET_HEADERS)) {
++ zend_long decode = 1;
++
++ if (context && (tmpzval = php_stream_context_get_option(context, "http", "auto_decode")) != NULL) {
++ decode = zend_is_true(tmpzval);
++ }
++ if (decode) {
++ if (header_info->transfer_encoding != NULL) {
++ /* Prevent a memory leak in case there are more transfer-encoding headers. */
++ php_stream_filter_free(header_info->transfer_encoding);
++ }
++ header_info->transfer_encoding = php_stream_filter_create(
++ "dechunk", NULL, php_stream_is_persistent(stream));
++ if (header_info->transfer_encoding != NULL) {
++ /* Do not store transfer-encoding header. */
++ store_header = false;
++ }
++ }
++ }
++ }
++
++ if (store_header) {
++ zval http_header;
++ ZVAL_NEW_STR(&http_header, last_header_line_str);
++ zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header);
++ } else {
++ zend_string_efree(last_header_line_str);
++ }
++
++ return NULL;
++}
++
+ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ const char *path, const char *mode, int options, zend_string **opened_path,
+ php_stream_context *context, int redirect_max, int flags,
+@@ -126,11 +291,12 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ zend_string *tmp = NULL;
+ char *ua_str = NULL;
+ zval *ua_zval = NULL, *tmpzval = NULL, ssl_proxy_peer_name;
+- char location[HTTP_HEADER_BLOCK_SIZE];
+ int reqok = 0;
+ char *http_header_line = NULL;
++ zend_string *last_header_line_str = NULL;
++ php_stream_http_response_header_info header_info;
+ char tmp_line[128];
+- size_t chunk_size = 0, file_size = 0;
++ size_t chunk_size = 0;
+ int eol_detect = 0;
+ char *transport_string;
+ zend_string *errstr = NULL;
+@@ -141,8 +307,6 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
+ char *user_headers = NULL;
+ int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0);
+ int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0);
+- zend_bool follow_location = 1;
+- php_stream_filter *transfer_encoding = NULL;
+ int response_code;
+ smart_str req_buf = {0};
+ zend_bool custom_request_method;
+@@ -655,8 +819,6 @@ finish:
+ /* send it */
+ php_stream_write(stream, ZSTR_VAL(req_buf.s), ZSTR_LEN(req_buf.s));
+
+- location[0] = '\0';
+-
+ if (Z_ISUNDEF_P(response_header)) {
+ array_init(response_header);
+ }
+@@ -738,130 +900,101 @@ finish:
+ }
+ }
+
+- /* read past HTTP headers */
++ php_stream_http_response_header_info_init(&header_info);
+
++ /* read past HTTP headers */
+ while (!php_stream_eof(stream)) {
+ size_t http_header_line_length;
+
+ if (http_header_line != NULL) {
+ efree(http_header_line);
+ }
+- if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') {
+- char *e = http_header_line + http_header_line_length - 1;
+- char *http_header_value;
+-
+- while (e >= http_header_line && (*e == '\n' || *e == '\r')) {
+- e--;
+- }
+-
+- /* The primary definition of an HTTP header in RFC 7230 states:
+- * > Each header field consists of a case-insensitive field name followed
+- * > by a colon (":"), optional leading whitespace, the field value, and
+- * > optional trailing whitespace. */
+-
+- /* Strip trailing whitespace */
+- while (e >= http_header_line && (*e == ' ' || *e == '\t')) {
+- e--;
+- }
+-
+- /* Terminate header line */
+- e++;
+- *e = '\0';
+- http_header_line_length = e - http_header_line;
+-
+- http_header_value = memchr(http_header_line, ':', http_header_line_length);
+- if (http_header_value) {
+- http_header_value++; /* Skip ':' */
+-
+- /* Strip leading whitespace */
+- while (http_header_value < e
+- && (*http_header_value == ' ' || *http_header_value == '\t')) {
+- http_header_value++;
++ if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length))) {
++ bool last_line;
++ if (*http_header_line == '\r') {
++ if (http_header_line[1] != '\n') {
++ php_stream_close(stream);
++ stream = NULL;
++ php_stream_wrapper_log_error(wrapper, options,
++ "HTTP invalid header name (cannot start with CR character)!");
++ goto out;
+ }
++ last_line = true;
++ } else if (*http_header_line == '\n') {
++ last_line = true;
+ } else {
+- /* There is no colon. Set the value to the end of the header line, which is
+- * effectively an empty string. */
+- http_header_value = e;
++ last_line = false;
+ }
+-
+- if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) {
+- if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) {
+- follow_location = zval_is_true(tmpzval);
+- } else if (!((response_code >= 300 && response_code < 304)
+- || 307 == response_code || 308 == response_code)) {
+- /* we shouldn't redirect automatically
+- if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307)
+- see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1
+- RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
+- follow_location = 0;
++
++ if (last_header_line_str != NULL) {
++ /* Parse last header line. */
++ last_header_line_str = php_stream_http_response_headers_parse(stream, context,
++ options, last_header_line_str, http_header_line, &http_header_line_length,
++ response_code, response_header, &header_info);
++ if (last_header_line_str != NULL) {
++ /* Folding header present so continue. */
++ continue;
+ }
+- strlcpy(location, http_header_value, sizeof(location));
+- } else if (!strncasecmp(http_header_line, "Content-Type:", sizeof("Content-Type:")-1)) {
+- php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_value, 0);
+- } else if (!strncasecmp(http_header_line, "Content-Length:", sizeof("Content-Length:")-1)) {
+- file_size = atoi(http_header_value);
+- php_stream_notify_file_size(context, file_size, http_header_line, 0);
+- } else if (
+- !strncasecmp(http_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1)
+- && !strncasecmp(http_header_value, "Chunked", sizeof("Chunked")-1)
+- ) {
+-
+- /* create filter to decode response body */
+- if (!(options & STREAM_ONLY_GET_HEADERS)) {
+- zend_long decode = 1;
+-
+- if (context && (tmpzval = php_stream_context_get_option(context, "http", "auto_decode")) != NULL) {
+- decode = zend_is_true(tmpzval);
+- }
+- if (decode) {
+- transfer_encoding = php_stream_filter_create("dechunk", NULL, php_stream_is_persistent(stream));
+- if (transfer_encoding) {
+- /* don't store transfer-encodeing header */
+- continue;
+- }
+- }
++ } else if (!last_line) {
++ /* The first line cannot start with spaces. */
++ if (*http_header_line == ' ' || *http_header_line == '\t') {
++ php_stream_close(stream);
++ stream = NULL;
++ php_stream_wrapper_log_error(wrapper, options,
++ "HTTP invalid response format (folding header at the start)!");
++ goto out;
+ }
++ /* Trim the first line if it is not the last line. */
++ php_stream_http_response_header_trim(http_header_line, &http_header_line_length);
+ }
+-
+- {
+- zval http_header;
+- ZVAL_STRINGL(&http_header, http_header_line, http_header_line_length);
+- zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header);
++ if (last_line) {
++ /* For the last line the last header line must be NULL. */
++ ZEND_ASSERT(last_header_line_str == NULL);
++ break;
+ }
++ /* Save current line as the last line so it gets parsed in the next round. */
++ last_header_line_str = zend_string_init(http_header_line, http_header_line_length, 0);
+ } else {
+ break;
+ }
+ }
+
+- if (!reqok || (location[0] != '\0' && follow_location)) {
+- if (!follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) {
++ /* If the stream was closed early, we still want to process the last line to keep BC. */
++ if (last_header_line_str != NULL) {
++ php_stream_http_response_headers_parse(stream, context, options, last_header_line_str,
++ NULL, NULL, response_code, response_header, &header_info);
++ }
++
++ if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) {
++ if (!header_info.follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) {
+ goto out;
+ }
+
+- if (location[0] != '\0')
+- php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0);
++ if (header_info.location[0] != '\0')
++ php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, header_info.location, 0);
+
+ php_stream_close(stream);
+ stream = NULL;
+
+- if (transfer_encoding) {
+- php_stream_filter_free(transfer_encoding);
+- transfer_encoding = NULL;
++ if (header_info.transfer_encoding) {
++ php_stream_filter_free(header_info.transfer_encoding);
++ header_info.transfer_encoding = NULL;
+ }
+
+- if (location[0] != '\0') {
++ if (header_info.location[0] != '\0') {
+
+ char new_path[HTTP_HEADER_BLOCK_SIZE];
+ char loc_path[HTTP_HEADER_BLOCK_SIZE];
+
+ *new_path='\0';
+- if (strlen(location)<8 || (strncasecmp(location, "http://", sizeof("http://")-1) &&
+- strncasecmp(location, "https://", sizeof("https://")-1) &&
+- strncasecmp(location, "ftp://", sizeof("ftp://")-1) &&
+- strncasecmp(location, "ftps://", sizeof("ftps://")-1)))
++ if (strlen(header_info.location) < 8 ||
++ (strncasecmp(header_info.location, "http://", sizeof("http://")-1) &&
++ strncasecmp(header_info.location, "https://", sizeof("https://")-1) &&
++ strncasecmp(header_info.location, "ftp://", sizeof("ftp://")-1) &&
++ strncasecmp(header_info.location, "ftps://", sizeof("ftps://")-1)))
+ {
+- if (*location != '/') {
+- if (*(location+1) != '\0' && resource->path) {
++ if (*header_info.location != '/') {
++ if (*(header_info.location+1) != '\0' && resource->path) {
+ char *s = strrchr(ZSTR_VAL(resource->path), '/');
+ if (!s) {
+ s = ZSTR_VAL(resource->path);
+@@ -877,15 +1010,17 @@ finish:
+ if (resource->path &&
+ ZSTR_VAL(resource->path)[0] == '/' &&
+ ZSTR_VAL(resource->path)[1] == '\0') {
+- snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", ZSTR_VAL(resource->path), location);
++ snprintf(loc_path, sizeof(loc_path) - 1, "%s%s",
++ ZSTR_VAL(resource->path), header_info.location);
+ } else {
+- snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", ZSTR_VAL(resource->path), location);
++ snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s",
++ ZSTR_VAL(resource->path), header_info.location);
+ }
+ } else {
+- snprintf(loc_path, sizeof(loc_path) - 1, "/%s", location);
++ snprintf(loc_path, sizeof(loc_path) - 1, "/%s", header_info.location);
+ }
+ } else {
+- strlcpy(loc_path, location, sizeof(loc_path));
++ strlcpy(loc_path, header_info.location, sizeof(loc_path));
+ }
+ if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
+ snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path);
+@@ -893,7 +1028,7 @@ finish:
+ snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), loc_path);
+ }
+ } else {
+- strlcpy(new_path, location, sizeof(new_path));
++ strlcpy(new_path, header_info.location, sizeof(new_path));
+ }
+
+ php_url_free(resource);
+@@ -946,7 +1081,7 @@ out:
+ if (header_init) {
+ ZVAL_COPY(&stream->wrapperdata, response_header);
+ }
+- php_stream_notify_progress_init(context, 0, file_size);
++ php_stream_notify_progress_init(context, 0, header_info.file_size);
+
+ /* Restore original chunk size now that we're done with headers */
+ if (options & STREAM_WILL_CAST)
+@@ -962,8 +1097,8 @@ out:
+ /* restore mode */
+ strlcpy(stream->mode, mode, sizeof(stream->mode));
+
+- if (transfer_encoding) {
+- php_stream_filter_append(&stream->readfilters, transfer_encoding);
++ if (header_info.transfer_encoding) {
++ php_stream_filter_append(&stream->readfilters, header_info.transfer_encoding);
+ }
+ }
+
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
+new file mode 100644
+index 00000000000..f935b5a02ca
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
+@@ -0,0 +1,49 @@
++--TEST--
++GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (single)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\n charset=utf-8\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx)));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html; charset=utf-8
++string(4) "body"
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(38) "Content-Type: text/html; charset=utf-8"
++}
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
+new file mode 100644
+index 00000000000..078d605b671
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
+@@ -0,0 +1,51 @@
++--TEST--
++GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (multiple)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\nCustom-Header: somevalue;\r\n param1=value1; \r\n param2=value2\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx)));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html;
++string(4) "body"
++array(3) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(24) "Content-Type: text/html;"
++ [2]=>
++ string(54) "Custom-Header: somevalue; param1=value1; param2=value2"
++}
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
+new file mode 100644
+index 00000000000..ad5ddc879ce
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
+@@ -0,0 +1,49 @@
++--TEST--
++GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (empty)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html;\r\n \r\n charset=utf-8\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx)));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html; charset=utf-8
++string(4) "body"
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(38) "Content-Type: text/html; charset=utf-8"
++}
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
+new file mode 100644
+index 00000000000..d0396e819fb
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
+@@ -0,0 +1,48 @@
++--TEST--
++GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (first line)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\n Content-Type: text/html;\r\n \r\n charset=utf-8\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (folding header at the start)! in %s
++bool(false)
++array(1) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++}
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
+new file mode 100644
+index 00000000000..037d2002cc5
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
+@@ -0,0 +1,48 @@
++--TEST--
++GHSA-v8xr-gpvj-cx9g: Header parser of http stream wrapper does not handle folded headers (CR before header name)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\n\rIgnored: ignored\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid header name (cannot start with CR character)! in %s
++bool(false)
++array(1) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++}
+diff --git a/ext/standard/tests/http/http_response_header_05.phpt b/ext/standard/tests/http/http_response_header_05.phpt
+deleted file mode 100644
+index c5fe60fa612..00000000000
+--- a/ext/standard/tests/http/http_response_header_05.phpt
++++ /dev/null
+@@ -1,30 +0,0 @@
+---TEST--
+-$http_reponse_header (whitespace-only "header")
+---SKIPIF--
+-<?php require 'server.inc'; http_server_skipif(); ?>
+---INI--
+-allow_url_fopen=1
+---FILE--
+-<?php
+-require 'server.inc';
+-
+-$responses = array(
+- "data://text/plain,HTTP/1.0 200 Ok\r\n \r\n\r\nBody",
+-);
+-
+-['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
+-
+-$f = file_get_contents($uri);
+-var_dump($f);
+-var_dump($http_response_header);
+-
+-http_server_kill($pid);
+-
+---EXPECT--
+-string(4) "Body"
+-array(2) {
+- [0]=>
+- string(15) "HTTP/1.0 200 Ok"
+- [1]=>
+- string(0) ""
+-}
+--
+2.48.1
+
diff --git a/php-cve-2025-1219.patch b/php-cve-2025-1219.patch
new file mode 100644
index 0000000..4f1cd52
--- /dev/null
+++ b/php-cve-2025-1219.patch
@@ -0,0 +1,1779 @@
+From 78ae0886bd1a3e42c53c9ba65764b6e6357640b5 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Sat, 29 Apr 2023 21:07:50 +0200
+Subject: [PATCH 05/11] Fix GH-11160: Few tests failed building with new libxml
+ 2.11.0
+
+It's possible to categorise the failures into 2 categories:
+ - Changed error message. In this case we either duplicate the test and
+ modify the error message. Or if the change in error message is
+ small, we use the EXPECTF matchers to make the test compatible with both
+ old and new versions of libxml2.
+ - Missing warnings. This is caused by a change in libxml2 where the
+ parser started using SAX APIs internally [1]. In this case the
+ error_type passed to php_libxml_internal_error_handler() changed from
+ PHP_LIBXML_ERROR to PHP_LIBXML_CTX_WARNING because it internally
+ started to use the SAX handlers instead of the generic handlers.
+ However, for the SAX handlers the current input stack is empty, so
+ nothing is actually printed. I fixed this by falling back to a
+ regular warning without a filename & line number reference, which
+ mimicks the old behaviour. Furthermore, this change now also shows
+ an additional warning in a test which was previously hidden.
+
+[1] https://gitlab.gnome.org/GNOME/libxml2/-/commit/9a82b94a94bd310db426edd453b0f38c6c8f69f5
+
+Closes GH-11162.
+
+(cherry picked from commit 7c0dfc5cf58d3c445b935fa14ea8f5f13568c419)
+---
+ .../DOMDocument_loadXML_error2_gte2_11.phpt | 34 +++
+ ...> DOMDocument_loadXML_error2_pre2_11.phpt} | 4 +
+ .../DOMDocument_load_error2_gte2_11.phpt | 34 +++
+ ...t => DOMDocument_load_error2_pre2_11.phpt} | 4 +
+ ext/libxml/libxml.c | 2 +
+ ext/libxml/tests/bug61367-read_2.phpt | 2 +-
+ .../tests/libxml_disable_entity_loader_2.phpt | 2 +-
+ ...set_external_entity_loader_variation2.phpt | 2 +
+ ext/openssl/tests/ServerClientTestCase.inc | 65 ++----
+ .../tests/http/ServerClientTestCase.inc | 199 ++++++++++++++++++
+ .../tests/http/ghsa-52jp-hrpf-2jff-001.phpt | 2 +-
+ .../tests/http/ghsa-52jp-hrpf-2jff-002.phpt | 2 +-
+ .../tests/http/ghsa-hgf5-96fm-v528-001.phpt | 2 +-
+ .../tests/http/ghsa-hgf5-96fm-v528-002.phpt | 2 +-
+ .../tests/http/ghsa-hgf5-96fm-v528-003.phpt | 2 +-
+ .../tests/http/ghsa-pcmh-g36c-qc44-001.phpt | 2 +-
+ .../tests/http/ghsa-pcmh-g36c-qc44-002.phpt | 2 +-
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt | 2 +-
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt | 2 +-
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt | 2 +-
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt | 2 +-
+ .../tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt | 2 +-
+ ext/xml/tests/bug26614_libxml_gte2_11.phpt | 95 +++++++++
+ ...bxml.phpt => bug26614_libxml_pre2_11.phpt} | 1 +
+ 24 files changed, 404 insertions(+), 64 deletions(-)
+ create mode 100644 ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
+ rename ext/dom/tests/{DOMDocument_loadXML_error2.phpt => DOMDocument_loadXML_error2_pre2_11.phpt} (90%)
+ create mode 100644 ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
+ rename ext/dom/tests/{DOMDocument_load_error2.phpt => DOMDocument_load_error2_pre2_11.phpt} (90%)
+ create mode 100644 ext/standard/tests/http/ServerClientTestCase.inc
+ create mode 100644 ext/xml/tests/bug26614_libxml_gte2_11.phpt
+ rename ext/xml/tests/{bug26614_libxml.phpt => bug26614_libxml_pre2_11.phpt} (96%)
+
+diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
+new file mode 100644
+index 00000000000..ff5ceb3fbed
+--- /dev/null
++++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt
+@@ -0,0 +1,34 @@
++--TEST--
++Test DOMDocument::loadXML() detects not-well formed XML
++--SKIPIF--
++<?php
++if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
++?>
++--DESCRIPTION--
++This test verifies the method detects attributes values not closed between " or '
++Environment variables used in the test:
++- XML_FILE: the xml file to load
++- LOAD_OPTIONS: the second parameter to pass to the method
++- EXPECTED_RESULT: the expected result
++--CREDITS--
++Antonio Diaz Ruiz <dejalatele@gmail.com>
++--INI--
++assert.bail=true
++--EXTENSIONS--
++dom
++--ENV--
++XML_FILE=/not_well_formed2.xml
++LOAD_OPTIONS=0
++EXPECTED_RESULT=0
++--FILE_EXTERNAL--
++domdocumentloadxml_test_method.inc
++--EXPECTF--
++Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d
++
++Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d
++
++Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d
++
++Warning: DOMDocument::loadXML(): Opening and ending tag mismatch: books line 3 and book in Entity, line: 7 in %s on line %d
++
++Warning: DOMDocument::loadXML(): Extra content at the end of the document in Entity, line: 8 in %s on line %d
+diff --git a/ext/dom/tests/DOMDocument_loadXML_error2.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
+similarity index 90%
+rename from ext/dom/tests/DOMDocument_loadXML_error2.phpt
+rename to ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
+index 6d56a317ed7..0e36d209058 100644
+--- a/ext/dom/tests/DOMDocument_loadXML_error2.phpt
++++ b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
+@@ -1,5 +1,9 @@
+ --TEST--
+ Test DOMDocument::loadXML() detects not-well formed XML
++--SKIPIF--
++<?php
++if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
++?>
+ --DESCRIPTION--
+ This test verifies the method detects attributes values not closed between " or '
+ Environment variables used in the test:
+diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
+new file mode 100644
+index 00000000000..32b6bf16114
+--- /dev/null
++++ b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt
+@@ -0,0 +1,34 @@
++--TEST--
++Test DOMDocument::load() detects not-well formed
++--SKIPIF--
++<?php
++if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
++?>
++--DESCRIPTION--
++This test verifies the method detects attributes values not closed between " or '
++Environment variables used in the test:
++- XML_FILE: the xml file to load
++- LOAD_OPTIONS: the second parameter to pass to the method
++- EXPECTED_RESULT: the expected result
++--CREDITS--
++Antonio Diaz Ruiz <dejalatele@gmail.com>
++--INI--
++assert.bail=true
++--EXTENSIONS--
++dom
++--ENV--
++XML_FILE=/not_well_formed2.xml
++LOAD_OPTIONS=0
++EXPECTED_RESULT=0
++--FILE_EXTERNAL--
++domdocumentload_test_method.inc
++--EXPECTF--
++Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d
++
++Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d
++
++Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d
++
++Warning: DOMDocument::load(): Opening and ending tag mismatch: books line 3 and book in %s on line %d
++
++Warning: DOMDocument::load(): Extra content at the end of the document in %s on line %d
+diff --git a/ext/dom/tests/DOMDocument_load_error2.phpt b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
+similarity index 90%
+rename from ext/dom/tests/DOMDocument_load_error2.phpt
+rename to ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
+index f450cf16545..b97fff9d2f1 100644
+--- a/ext/dom/tests/DOMDocument_load_error2.phpt
++++ b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
+@@ -1,5 +1,9 @@
+ --TEST--
+ Test DOMDocument::load() detects not-well formed XML
++--SKIPIF--
++<?php
++if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
++?>
+ --DESCRIPTION--
+ This test verifies the method detects attributes values not closed between " or '
+ Environment variables used in the test:
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index 73486ae253f..c8bd1be60a4 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -525,6 +525,8 @@ static void php_libxml_ctx_error_level(int level, void *ctx, const char *msg)
+ } else {
+ php_error_docref(NULL, level, "%s in Entity, line: %d", msg, parser->input->line);
+ }
++ } else {
++ php_error_docref(NULL, E_WARNING, "%s", msg);
+ }
+ }
+
+diff --git a/ext/libxml/tests/bug61367-read_2.phpt b/ext/libxml/tests/bug61367-read_2.phpt
+index ed6576aa752..b935261cb2e 100644
+--- a/ext/libxml/tests/bug61367-read_2.phpt
++++ b/ext/libxml/tests/bug61367-read_2.phpt
+@@ -55,6 +55,6 @@ bool(true)
+ int(4)
+ bool(true)
+
+-Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d
++Warning: DOMDocument::loadXML(): %Sfailed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d
+
+ Warning: Attempt to read property "nodeValue" on null in %s on line %d
+diff --git a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
+index caa7356ad30..d90f909ac2b 100644
+--- a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
++++ b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt
+@@ -38,6 +38,6 @@ bool(true)
+ Deprecated: Function libxml_disable_entity_loader() is deprecated in %s on line %d
+ bool(false)
+
+-Warning: DOMDocument::loadXML(): I/O warning : failed to load external entity "%s" in %s on line %d
++Warning: DOMDocument::loadXML(): %Sfailed to load external entity "%s" in %s on line %d
+ bool(true)
+ Done
+diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
+index 87894bcb91a..ddaf9bfa50e 100644
+--- a/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
++++ b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
+@@ -39,6 +39,8 @@ echo "Done.\n";
+ string(10) "-//FOO/BAR"
+ string(%d) "%sfoobar.dtd"
+
++Warning: DOMDocument::validate(): Failed to load external entity "-//FOO/BAR" in %s on line %d
++
+ Warning: DOMDocument::validate(): Could not load the external subset "foobar.dtd" in %s on line %d
+ bool(false)
+ bool(true)
+diff --git a/ext/openssl/tests/ServerClientTestCase.inc b/ext/openssl/tests/ServerClientTestCase.inc
+index 61d45385b62..753366df6f4 100644
+--- a/ext/openssl/tests/ServerClientTestCase.inc
++++ b/ext/openssl/tests/ServerClientTestCase.inc
+@@ -4,19 +4,14 @@ const WORKER_ARGV_VALUE = 'RUN_WORKER';
+
+ const WORKER_DEFAULT_NAME = 'server';
+
+-function phpt_notify(string $worker = WORKER_DEFAULT_NAME, string $message = ""): void
++function phpt_notify($worker = WORKER_DEFAULT_NAME)
+ {
+- ServerClientTestCase::getInstance()->notify($worker, $message);
++ ServerClientTestCase::getInstance()->notify($worker);
+ }
+
+-function phpt_wait($worker = WORKER_DEFAULT_NAME, $timeout = null): ?string
++function phpt_wait($worker = WORKER_DEFAULT_NAME, $timeout = null)
+ {
+- return ServerClientTestCase::getInstance()->wait($worker, $timeout);
+-}
+-
+-function phpt_notify_server_start($server): void
+-{
+- ServerClientTestCase::getInstance()->notify_server_start($server);
++ ServerClientTestCase::getInstance()->wait($worker, $timeout);
+ }
+
+ function phpt_has_sslv3() {
+@@ -124,73 +119,43 @@ class ServerClientTestCase
+ eval($code);
+ }
+
+- /**
+- * Run client and all workers
+- *
+- * @param string $clientCode The client PHP code
+- * @param string|array $workerCode
+- * @param bool $ephemeral Select whether automatic port selection and automatic awaiting is used
+- * @return void
+- * @throws Exception
+- */
+- public function run(string $clientCode, string|array $workerCode, bool $ephemeral = true): void
++ public function run($masterCode, $workerCode)
+ {
+ if (!is_array($workerCode)) {
+ $workerCode = [WORKER_DEFAULT_NAME => $workerCode];
+ }
+- reset($workerCode);
+- $code = current($workerCode);
+- $worker = key($workerCode);
+- while ($worker != null) {
++ foreach ($workerCode as $worker => $code) {
+ $this->spawnWorkerProcess($worker, $this->stripPhpTagsFromCode($code));
+- $code = next($workerCode);
+- if ($ephemeral) {
+- $addr = trim($this->wait($worker));
+- if (empty($addr)) {
+- throw new \Exception("Failed server start");
+- }
+- if ($code === false) {
+- $clientCode = preg_replace('/{{\s*ADDR\s*}}/', $addr, $clientCode);
+- } else {
+- $code = preg_replace('/{{\s*ADDR\s*}}/', $addr, $code);
+- }
+- }
+- $worker = key($workerCode);
+ }
+-
+- eval($this->stripPhpTagsFromCode($clientCode));
++ eval($this->stripPhpTagsFromCode($masterCode));
+ foreach ($workerCode as $worker => $code) {
+ $this->cleanupWorkerProcess($worker);
+ }
+ }
+
+- public function wait($worker, $timeout = null): ?string
++ public function wait($worker, $timeout = null)
+ {
+ $handle = $this->isWorker ? STDIN : $this->workerStdOut[$worker];
+ if ($timeout === null) {
+- return fgets($handle);
++ fgets($handle);
++ return true;
+ }
+
+ stream_set_blocking($handle, false);
+ $read = [$handle];
+ $result = stream_select($read, $write, $except, $timeout);
+ if (!$result) {
+- return null;
++ return false;
+ }
+
+- $result = fgets($handle);
++ fgets($handle);
+ stream_set_blocking($handle, true);
+- return $result;
+- }
+-
+- public function notify(string $worker, string $message = ""): void
+- {
+- fwrite($this->isWorker ? STDOUT : $this->workerStdIn[$worker], "$message\n");
++ return true;
+ }
+
+- public function notify_server_start($server): void
++ public function notify($worker)
+ {
+- echo stream_socket_get_name($server, false) . "\n";
++ fwrite($this->isWorker ? STDOUT : $this->workerStdIn[$worker], "\n");
+ }
+ }
+
+diff --git a/ext/standard/tests/http/ServerClientTestCase.inc b/ext/standard/tests/http/ServerClientTestCase.inc
+new file mode 100644
+index 00000000000..61d45385b62
+--- /dev/null
++++ b/ext/standard/tests/http/ServerClientTestCase.inc
+@@ -0,0 +1,199 @@
++<?php
++
++const WORKER_ARGV_VALUE = 'RUN_WORKER';
++
++const WORKER_DEFAULT_NAME = 'server';
++
++function phpt_notify(string $worker = WORKER_DEFAULT_NAME, string $message = ""): void
++{
++ ServerClientTestCase::getInstance()->notify($worker, $message);
++}
++
++function phpt_wait($worker = WORKER_DEFAULT_NAME, $timeout = null): ?string
++{
++ return ServerClientTestCase::getInstance()->wait($worker, $timeout);
++}
++
++function phpt_notify_server_start($server): void
++{
++ ServerClientTestCase::getInstance()->notify_server_start($server);
++}
++
++function phpt_has_sslv3() {
++ static $result = null;
++ if (!is_null($result)) {
++ return $result;
++ }
++ $server = @stream_socket_server('sslv3://127.0.0.1:10013');
++ if ($result = !!$server) {
++ fclose($server);
++ }
++ return $result;
++}
++
++/**
++ * This is a singleton to let the wait/notify functions work
++ * I know it's horrible, but it's a means to an end
++ */
++class ServerClientTestCase
++{
++ private $isWorker = false;
++
++ private $workerHandle = [];
++
++ private $workerStdIn = [];
++
++ private $workerStdOut = [];
++
++ private static $instance;
++
++ public static function getInstance($isWorker = false)
++ {
++ if (!isset(self::$instance)) {
++ self::$instance = new self($isWorker);
++ }
++
++ return self::$instance;
++ }
++
++ public function __construct($isWorker = false)
++ {
++ if (!isset(self::$instance)) {
++ self::$instance = $this;
++ }
++
++ $this->isWorker = $isWorker;
++ }
++
++ private function spawnWorkerProcess($worker, $code)
++ {
++ if (defined("PHP_WINDOWS_VERSION_MAJOR")) {
++ $ini = php_ini_loaded_file();
++ $cmd = sprintf(
++ '%s %s "%s" %s',
++ PHP_BINARY, $ini ? "-n -c $ini" : "",
++ __FILE__,
++ WORKER_ARGV_VALUE
++ );
++ } else {
++ $cmd = sprintf(
++ '%s "%s" %s %s',
++ PHP_BINARY,
++ __FILE__,
++ WORKER_ARGV_VALUE,
++ $worker
++ );
++ }
++ $this->workerHandle[$worker] = proc_open(
++ $cmd,
++ [['pipe', 'r'], ['pipe', 'w'], STDERR],
++ $pipes
++ );
++ $this->workerStdIn[$worker] = $pipes[0];
++ $this->workerStdOut[$worker] = $pipes[1];
++
++ fwrite($this->workerStdIn[$worker], $code . "\n---\n");
++ }
++
++ private function cleanupWorkerProcess($worker)
++ {
++ fclose($this->workerStdIn[$worker]);
++ fclose($this->workerStdOut[$worker]);
++ proc_close($this->workerHandle[$worker]);
++ }
++
++ private function stripPhpTagsFromCode($code)
++ {
++ return preg_replace('/^\s*<\?(?:php)?|\?>\s*$/i', '', $code);
++ }
++
++ public function runWorker()
++ {
++ $code = '';
++
++ while (1) {
++ $line = fgets(STDIN);
++
++ if (trim($line) === "---") {
++ break;
++ }
++
++ $code .= $line;
++ }
++
++ eval($code);
++ }
++
++ /**
++ * Run client and all workers
++ *
++ * @param string $clientCode The client PHP code
++ * @param string|array $workerCode
++ * @param bool $ephemeral Select whether automatic port selection and automatic awaiting is used
++ * @return void
++ * @throws Exception
++ */
++ public function run(string $clientCode, string|array $workerCode, bool $ephemeral = true): void
++ {
++ if (!is_array($workerCode)) {
++ $workerCode = [WORKER_DEFAULT_NAME => $workerCode];
++ }
++ reset($workerCode);
++ $code = current($workerCode);
++ $worker = key($workerCode);
++ while ($worker != null) {
++ $this->spawnWorkerProcess($worker, $this->stripPhpTagsFromCode($code));
++ $code = next($workerCode);
++ if ($ephemeral) {
++ $addr = trim($this->wait($worker));
++ if (empty($addr)) {
++ throw new \Exception("Failed server start");
++ }
++ if ($code === false) {
++ $clientCode = preg_replace('/{{\s*ADDR\s*}}/', $addr, $clientCode);
++ } else {
++ $code = preg_replace('/{{\s*ADDR\s*}}/', $addr, $code);
++ }
++ }
++ $worker = key($workerCode);
++ }
++
++ eval($this->stripPhpTagsFromCode($clientCode));
++ foreach ($workerCode as $worker => $code) {
++ $this->cleanupWorkerProcess($worker);
++ }
++ }
++
++ public function wait($worker, $timeout = null): ?string
++ {
++ $handle = $this->isWorker ? STDIN : $this->workerStdOut[$worker];
++ if ($timeout === null) {
++ return fgets($handle);
++ }
++
++ stream_set_blocking($handle, false);
++ $read = [$handle];
++ $result = stream_select($read, $write, $except, $timeout);
++ if (!$result) {
++ return null;
++ }
++
++ $result = fgets($handle);
++ stream_set_blocking($handle, true);
++ return $result;
++ }
++
++ public function notify(string $worker, string $message = ""): void
++ {
++ fwrite($this->isWorker ? STDOUT : $this->workerStdIn[$worker], "$message\n");
++ }
++
++ public function notify_server_start($server): void
++ {
++ echo stream_socket_get_name($server, false) . "\n";
++ }
++}
++
++if (isset($argv[1]) && $argv[1] === WORKER_ARGV_VALUE) {
++ ServerClientTestCase::getInstance(true)->runWorker();
++}
+diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
+index 744cff9cc72..461a649b147 100644
+--- a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
++++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
+@@ -39,7 +39,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
+index bc71fd4e411..126b77bae62 100644
+--- a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
++++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
+@@ -39,7 +39,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
+index c40123560ef..0f04f565d6b 100644
+--- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
+@@ -36,7 +36,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
+index 37a47df060a..aa23a96aedc 100644
+--- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
+@@ -36,7 +36,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
+index 6c84679ff63..8ef42b5700f 100644
+--- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
+@@ -36,7 +36,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
+index bb7945ce62d..595f0fd9272 100644
+--- a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
++++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
+index 1d0e4fa70a2..99c8e025f93 100644
+--- a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
++++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
+index f935b5a02ca..945225d9e06 100644
+--- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
+index 078d605b671..6619db3a5dd 100644
+--- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
+index ad5ddc879ce..7eb9015d963 100644
+--- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
+index d0396e819fb..f8f67886634 100644
+--- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
+index 037d2002cc5..671c82e8ee0 100644
+--- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
++++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt
+@@ -35,7 +35,7 @@ $clientCode = <<<'CODE'
+ var_dump($http_response_header);
+ CODE;
+
+-include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++include sprintf("%s/ServerClientTestCase.inc", __DIR__);
+ ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+ ?>
+ --EXPECTF--
+diff --git a/ext/xml/tests/bug26614_libxml_gte2_11.phpt b/ext/xml/tests/bug26614_libxml_gte2_11.phpt
+new file mode 100644
+index 00000000000..9a81b67686d
+--- /dev/null
++++ b/ext/xml/tests/bug26614_libxml_gte2_11.phpt
+@@ -0,0 +1,95 @@
++--TEST--
++Bug #26614 (CDATA sections skipped on line count)
++--EXTENSIONS--
++xml
++--SKIPIF--
++<?php
++if (!defined("LIBXML_VERSION")) die('skip libxml2 test');
++if (LIBXML_VERSION < 21100) die('skip libxml2 test variant for version >= 2.11');
++?>
++--FILE--
++<?php
++/*
++this test works fine with Expat but fails with libxml
++which we now use as default
++
++further investigation has shown that not only line count
++is skipped on CDATA sections but that libxml does also
++show different column numbers and byte positions depending
++on context and in opposition to what one would expect to
++see and what good old Expat reported just fine ...
++*/
++
++$xmls = array();
++
++// Case 1: CDATA Sections
++$xmls["CDATA"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
++<data>
++<![CDATA[
++multi
++line
++CDATA
++block
++]]>
++</data>';
++
++// Case 2: replace some characters so that we get comments instead
++$xmls["Comment"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
++<data>
++<!-- ATA[
++multi
++line
++CDATA
++block
++-->
++</data>';
++
++// Case 3: replace even more characters so that only textual data is left
++$xmls["Text"] ='<?xml version="1.0" encoding="iso-8859-1" ?>
++<data>
++-!-- ATA[
++multi
++line
++CDATA
++block
++---
++</data>';
++
++function startElement($parser, $name, $attrs) {
++ printf("<$name> at line %d, col %d (byte %d)\n",
++ xml_get_current_line_number($parser),
++ xml_get_current_column_number($parser),
++ xml_get_current_byte_index($parser));
++}
++
++function endElement($parser, $name) {
++ printf("</$name> at line %d, col %d (byte %d)\n",
++ xml_get_current_line_number($parser),
++ xml_get_current_column_number($parser),
++ xml_get_current_byte_index($parser));
++}
++
++function characterData($parser, $data) {
++ // dummy
++}
++
++foreach ($xmls as $desc => $xml) {
++ echo "$desc\n";
++ $xml_parser = xml_parser_create();
++ xml_set_element_handler($xml_parser, "startElement", "endElement");
++ xml_set_character_data_handler($xml_parser, "characterData");
++ if (!xml_parse($xml_parser, $xml, true))
++ echo "Error: ".xml_error_string(xml_get_error_code($xml_parser))."\n";
++ xml_parser_free($xml_parser);
++}
++?>
++--EXPECTF--
++CDATA
++<DATA> at line 2, col %d (byte 50)
++</DATA> at line 9, col %d (byte 96)
++Comment
++<DATA> at line 2, col %d (byte 50)
++</DATA> at line 9, col %d (byte 96)
++Text
++<DATA> at line 2, col %d (byte 50)
++</DATA> at line 9, col %d (byte 96)
+diff --git a/ext/xml/tests/bug26614_libxml.phpt b/ext/xml/tests/bug26614_libxml_pre2_11.phpt
+similarity index 96%
+rename from ext/xml/tests/bug26614_libxml.phpt
+rename to ext/xml/tests/bug26614_libxml_pre2_11.phpt
+index b6c0b875818..90283850d24 100644
+--- a/ext/xml/tests/bug26614_libxml.phpt
++++ b/ext/xml/tests/bug26614_libxml_pre2_11.phpt
+@@ -4,6 +4,7 @@ Bug #26614 (CDATA sections skipped on line count)
+ <?php
+ require_once("skipif.inc");
+ if (!defined("LIBXML_VERSION")) die('skip libxml2 test');
++if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
+ ?>
+ --FILE--
+ <?php
+--
+2.48.1
+
+From 6e8e9f558aa0903e9650dd166a0a53c359d9e9e0 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 1 Dec 2023 18:03:35 +0100
+Subject: [PATCH 06/11] Backport 0a39890c: Fix libxml2 2.12 build due to API
+ breaks
+
+See https://github.com/php/php-src/actions/runs/7062192818/job/19225478601
+
+(cherry picked from commit fa6a0f80f644932506666beb7c85e4041c4a4646)
+---
+ ext/libxml/libxml.c | 14 ++++++++++----
+ ext/soap/php_sdl.c | 2 +-
+ 2 files changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index c8bd1be60a4..554fcc34ff2 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -481,7 +481,11 @@ static void _php_libxml_free_error(void *ptr)
+ xmlResetError((xmlErrorPtr) ptr);
+ }
+
+-static void _php_list_set_error_structure(xmlErrorPtr error, const char *msg)
++#if LIBXML_VERSION >= 21200
++static void _php_list_set_error_structure(const xmlError *error, const char *msg)
++#else
++static void _php_list_set_error_structure(xmlError *error, const char *msg)
++#endif
+ {
+ xmlError error_copy;
+ int ret;
+@@ -734,7 +738,11 @@ PHP_LIBXML_API void php_libxml_ctx_warning(void *ctx, const char *msg, ...)
+ va_end(args);
+ }
+
++#if LIBXML_VERSION >= 21200
++PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, const xmlError *error)
++#else
+ PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, xmlErrorPtr error)
++#endif
+ {
+ _php_list_set_error_structure(error, NULL);
+
+@@ -1037,11 +1045,9 @@ PHP_FUNCTION(libxml_use_internal_errors)
+ /* {{{ Retrieve last error from libxml */
+ PHP_FUNCTION(libxml_get_last_error)
+ {
+- xmlErrorPtr error;
+-
+ ZEND_PARSE_PARAMETERS_NONE();
+
+- error = xmlGetLastError();
++ const xmlError *error = xmlGetLastError();
+
+ if (error) {
+ object_init_ex(return_value, libxmlerror_class_entry);
+diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
+index e5e7f2f9554..6060f634508 100644
+--- a/ext/soap/php_sdl.c
++++ b/ext/soap/php_sdl.c
+@@ -331,7 +331,7 @@ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ sdl_restore_uri_credentials(ctx);
+
+ if (!wsdl) {
+- xmlErrorPtr xmlErrorPtr = xmlGetLastError();
++ const xmlError *xmlErrorPtr = xmlGetLastError();
+
+ if (xmlErrorPtr) {
+ soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
+--
+2.48.1
+
+From 6cb68826aaf68ffe8c70c8782450c38970236040 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Thu, 4 Jul 2024 06:29:50 -0700
+Subject: [PATCH 07/11] Backport 4fe82131: Backport libxml2 2.13.2 fixes
+ (#14816)
+
+Backproted from https://github.com/php/php-src/pull/14789
+
+(cherry picked from commit bb46b4b799b583528025a775af45308133bfd4c1)
+---
+ ext/dom/document.c | 6 ++--
+ .../DOMDocument_loadHTMLfile_error1.phpt | 2 +-
+ .../DOMDocument_loadXML_error2_pre2_11.phpt | 3 +-
+ .../DOMDocument_load_error2_pre2_11.phpt | 3 +-
+ .../DOMDocument_relaxNGValidate_error2.phpt | 2 +-
+ .../tests/DOMDocument_saveHTMLFile_basic.phpt | 1 +
+ ...DOMDocument_saveHTMLFile_formatOutput.phpt | 1 +
+ ...nt_saveHTMLFile_formatOutput_gte_2_13.phpt | 32 +++++++++++++++++++
+ .../DOMDocument_saveHTML_basic_gte_2_13.phpt | 31 ++++++++++++++++++
+ .../DOMDocument_schemaValidate_error5.phpt | 2 +-
+ ext/dom/tests/dom_create_element.phpt | 14 +++-----
+ ext/libxml/libxml.c | 4 ++-
+ ext/simplexml/tests/bug79971_1.phpt | 2 +-
+ ext/soap/php_encoding.c | 9 ++++--
+ ext/soap/php_xml.c | 4 ++-
+ ext/soap/tests/bugs/bug42151.phpt | 4 +--
+ ext/xml/compat.c | 3 +-
+ ext/xmlwriter/php_xmlwriter.c | 3 +-
+ 18 files changed, 97 insertions(+), 29 deletions(-)
+ create mode 100644 ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.phpt
+ create mode 100644 ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt
+
+diff --git a/ext/dom/document.c b/ext/dom/document.c
+index 02522b5014f..7735e5d5dc3 100644
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -1253,11 +1253,13 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
+ if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
+ options |= XML_PARSE_NOBLANKS;
+ }
++ if (recover) {
++ options |= XML_PARSE_RECOVER;
++ }
+
+ php_libxml_sanitize_parse_ctxt_options(ctxt);
+ xmlCtxtUseOptions(ctxt, options);
+
+- ctxt->recovery = recover;
+ if (recover) {
+ old_error_reporting = EG(error_reporting);
+ EG(error_reporting) = old_error_reporting | E_WARNING;
+@@ -1267,7 +1269,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
+
+ if (ctxt->wellFormed || recover) {
+ ret = ctxt->myDoc;
+- if (ctxt->recovery) {
++ if (recover) {
+ EG(error_reporting) = old_error_reporting;
+ }
+ /* If loading from memory, set the base reference uri for the document */
+diff --git a/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt b/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt
+index cfb41686e87..fc78273c85f 100644
+--- a/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt
++++ b/ext/dom/tests/DOMDocument_loadHTMLfile_error1.phpt
+@@ -15,4 +15,4 @@ $result = $doc->loadHTMLFile(__DIR__ . "/ffff/test.html");
+ assert($result === false);
+ ?>
+ --EXPECTF--
+-%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O warning : failed to load external entity %s
++%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): I/O %s
+diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
+index 0e36d209058..7e10771fdb7 100644
+--- a/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
++++ b/ext/dom/tests/DOMDocument_loadXML_error2_pre2_11.phpt
+@@ -2,6 +2,7 @@
+ Test DOMDocument::loadXML() detects not-well formed XML
+ --SKIPIF--
+ <?php
++include('skipif.inc');
+ if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
+ ?>
+ --DESCRIPTION--
+@@ -14,8 +15,6 @@ Environment variables used in the test:
+ Antonio Diaz Ruiz <dejalatele@gmail.com>
+ --INI--
+ assert.bail=true
+---SKIPIF--
+-<?php include('skipif.inc'); ?>
+ --ENV--
+ XML_FILE=/not_well_formed2.xml
+ LOAD_OPTIONS=0
+diff --git a/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
+index b97fff9d2f1..74b20c171e0 100644
+--- a/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
++++ b/ext/dom/tests/DOMDocument_load_error2_pre2_11.phpt
+@@ -2,6 +2,7 @@
+ Test DOMDocument::load() detects not-well formed XML
+ --SKIPIF--
+ <?php
++include('skipif.inc');
+ if (LIBXML_VERSION >= 21100) die('skip libxml2 test variant for version < 2.11');
+ ?>
+ --DESCRIPTION--
+@@ -14,8 +15,6 @@ Environment variables used in the test:
+ Antonio Diaz Ruiz <dejalatele@gmail.com>
+ --INI--
+ assert.bail=true
+---SKIPIF--
+-<?php include('skipif.inc'); ?>
+ --ENV--
+ XML_FILE=/not_well_formed2.xml
+ LOAD_OPTIONS=0
+diff --git a/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt b/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt
+index 3aa6a3b3189..bf8d7befa53 100644
+--- a/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt
++++ b/ext/dom/tests/DOMDocument_relaxNGValidate_error2.phpt
+@@ -22,7 +22,7 @@ $result = $doc->relaxNGValidate($rng);
+ var_dump($result);
+ ?>
+ --EXPECTF--
+-Warning: DOMDocument::relaxNGValidate(): I/O warning : failed to load external entity "%s/foo.rng" in %s on line %d
++Warning: DOMDocument::relaxNGValidate(): I/O %s : failed to load %s
+
+ Warning: DOMDocument::relaxNGValidate(): xmlRelaxNGParse: could not load %s/foo.rng in %s on line %d
+
+diff --git a/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt b/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt
+index f71db0c32a3..c51852e120c 100644
+--- a/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt
++++ b/ext/dom/tests/DOMDocument_saveHTMLFile_basic.phpt
+@@ -6,6 +6,7 @@ Knut Urdalen <knut@php.net>
+ --SKIPIF--
+ <?php
+ require_once __DIR__ .'/skipif.inc';
++if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
+ ?>
+ --FILE--
+ <?php
+diff --git a/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt b/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt
+index 376c9a8e323..8d7baa7b7e8 100644
+--- a/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt
++++ b/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput.phpt
+@@ -6,6 +6,7 @@ Knut Urdalen <knut@php.net>
+ --SKIPIF--
+ <?php
+ require_once __DIR__ .'/skipif.inc';
++if (LIBXML_VERSION >= 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
+ ?>
+ --FILE--
+ <?php
+diff --git a/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.phpt b/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.phpt
+new file mode 100644
+index 00000000000..3477edfcf5f
+--- /dev/null
++++ b/ext/dom/tests/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++DOMDocument::saveHTMLFile() should format output on demand
++--CREDITS--
++Knut Urdalen <knut@php.net>
++#PHPTestFest2009 Norway 2009-06-09 \o/
++--EXTENSIONS--
++dom
++--SKIPIF--
++<?php
++if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
++?>
++--FILE--
++<?php
++$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput_gte_2_13.html";
++$doc = new DOMDocument('1.0');
++$doc->formatOutput = true;
++$root = $doc->createElement('html');
++$root = $doc->appendChild($root);
++$head = $doc->createElement('head');
++$head = $root->appendChild($head);
++$title = $doc->createElement('title');
++$title = $head->appendChild($title);
++$text = $doc->createTextNode('This is the title');
++$text = $title->appendChild($text);
++$bytes = $doc->saveHTMLFile($filename);
++var_dump($bytes);
++echo file_get_contents($filename);
++unlink($filename);
++?>
++--EXPECT--
++int(59)
++<html><head><title>This is the title</title></head></html>
+diff --git a/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt b/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt
+new file mode 100644
+index 00000000000..c0be105253d
+--- /dev/null
++++ b/ext/dom/tests/DOMDocument_saveHTML_basic_gte_2_13.phpt
+@@ -0,0 +1,31 @@
++--TEST--
++DOMDocument::saveHTMLFile() should dump the internal document into a file using HTML formatting
++--CREDITS--
++Knut Urdalen <knut@php.net>
++#PHPTestFest2009 Norway 2009-06-09 \o/
++--EXTENSIONS--
++dom
++--SKIPIF--
++<?php
++if (LIBXML_VERSION < 21300) die("skip see https://gitlab.gnome.org/GNOME/libxml2/-/issues/756");
++?>
++--FILE--
++<?php
++$filename = __DIR__."/DOMDocument_saveHTMLFile_basic_gte_2_13.html";
++$doc = new DOMDocument('1.0');
++$root = $doc->createElement('html');
++$root = $doc->appendChild($root);
++$head = $doc->createElement('head');
++$head = $root->appendChild($head);
++$title = $doc->createElement('title');
++$title = $head->appendChild($title);
++$text = $doc->createTextNode('This is the title');
++$text = $title->appendChild($text);
++$bytes = $doc->saveHTMLFile($filename);
++var_dump($bytes);
++echo file_get_contents($filename);
++unlink($filename);
++?>
++--EXPECT--
++int(59)
++<html><head><title>This is the title</title></head></html>
+diff --git a/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt b/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt
+index cb57b55b41a..44ea52c2d06 100644
+--- a/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt
++++ b/ext/dom/tests/DOMDocument_schemaValidate_error5.phpt
+@@ -17,7 +17,7 @@ var_dump($result);
+
+ ?>
+ --EXPECTF--
+-Warning: DOMDocument::schemaValidate(): I/O warning : failed to load external entity "%snon-existent-file" in %s.php on line %d
++Warning: DOMDocument::schemaValidate(): I/O %s : failed to load %s
+
+ Warning: DOMDocument::schemaValidate(): Failed to locate the main schema resource at '%s/non-existent-file'. in %s.php on line %d
+
+diff --git a/ext/dom/tests/dom_create_element.phpt b/ext/dom/tests/dom_create_element.phpt
+index bd2c8f11dae..70ae54a11bb 100644
+--- a/ext/dom/tests/dom_create_element.phpt
++++ b/ext/dom/tests/dom_create_element.phpt
+@@ -251,14 +251,10 @@ try {
+ print $e->getMessage() . "\n";
+ }
+
+-/* This isn't because the xml namespace isn't there and we can't create it */
+-print "29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')\n";
+-try {
+- $element = new DomElement('xml:valid', '', 'http://www.w3.org/XML/1998/namespace');
+- print "valid\n";
+-} catch (Exception $e) {
+- print $e->getMessage() . "\n";
+-}
++/* There used to be a 29 here that tested DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace').
++ * In libxml2 version 2.12 or prior this didn't work because the xml namespace isn't there and you can't create it without
++ * a document. Starting from libxml2 version 2.13 it does actually work because the XML namespace is statically defined.
++ * The behaviour from version 2.13 is actually the desired behaviour anyway. */
+
+
+ /* the qualifiedName or its prefix is "xmlns" and the namespaceURI is
+@@ -378,8 +374,6 @@ Namespace Error
+ Namespace Error
+ 28 DOMDocument::createElementNS('http://www.w3.org/XML/1998/namespace', 'xml:valid')
+ valid
+-29 DOMElement::__construct('xml:valid', '', 'http://www.w3.org/XML/1998/namespace')
+-Namespace Error
+ 30 DOMDocument::createElementNS('http://wrong.namespaceURI.com', 'xmlns:valid')
+ Namespace Error
+ 31 DOMElement::__construct('xmlns:valid', '', 'http://wrong.namespaceURI.com')
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index 554fcc34ff2..28dd86a55c9 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -428,8 +428,10 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
+ static xmlOutputBufferPtr
+ php_libxml_output_buffer_create_filename(const char *URI,
+ xmlCharEncodingHandlerPtr encoder,
+- int compression ATTRIBUTE_UNUSED)
++ int compression)
+ {
++ ZEND_IGNORE_VALUE(compression);
++
+ xmlOutputBufferPtr ret;
+ xmlURIPtr puri;
+ void *context = NULL;
+diff --git a/ext/simplexml/tests/bug79971_1.phpt b/ext/simplexml/tests/bug79971_1.phpt
+index 197776d82d3..2ee24e89f12 100644
+--- a/ext/simplexml/tests/bug79971_1.phpt
++++ b/ext/simplexml/tests/bug79971_1.phpt
+@@ -20,7 +20,7 @@ var_dump($sxe->asXML("$uri.out%00foo"));
+ --EXPECTF--
+ Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d
+
+-Warning: simplexml_load_file(): I/O warning : failed to load external entity "%s/bug79971_1.xml%00foo" in %s on line %d
++Warning: simplexml_load_file(): I/O warning : failed to load %s
+ bool(false)
+
+ Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d
+diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
+index f5723e213a4..2634d2c7db4 100644
+--- a/ext/soap/php_encoding.c
++++ b/ext/soap/php_encoding.c
+@@ -3379,7 +3379,6 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
+ } else {
+ smart_str prefix = {0};
+ int num = ++SOAP_GLOBAL(cur_uniq_ns);
+- xmlChar *enc_ns;
+
+ while (1) {
+ smart_str_appendl(&prefix, "ns", 2);
+@@ -3393,9 +3392,15 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
+ num = ++SOAP_GLOBAL(cur_uniq_ns);
+ }
+
+- enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
++ /* Starting with libxml 2.13, we don't have to do this workaround anymore, otherwise we get double-encoded
++ * entities. See libxml2 commit f506ec66547ef9bac97a2bf306d368ecea8c0c9e. */
++#if LIBXML_VERSION < 21300
++ xmlChar *enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
+ xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
+ xmlFree(enc_ns);
++#else
++ xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
++#endif
+ smart_str_free(&prefix);
+ }
+ }
+diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
+index ed3495c1266..58c176031f9 100644
+--- a/ext/soap/php_xml.c
++++ b/ext/soap/php_xml.c
+@@ -92,13 +92,14 @@ xmlDocPtr soap_xmlParseFile(const char *filename)
+ zend_bool old;
+
+ php_libxml_sanitize_parse_ctxt_options(ctxt);
++ /* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
+ ctxt->keepBlanks = 0;
++ ctxt->options |= XML_PARSE_HUGE;
+ ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
+ ctxt->sax->comment = soap_Comment;
+ ctxt->sax->warning = NULL;
+ ctxt->sax->error = NULL;
+ /*ctxt->sax->fatalError = NULL;*/
+- ctxt->options |= XML_PARSE_HUGE;
+ old = php_libxml_disable_entity_loader(1);
+ xmlParseDocument(ctxt);
+ php_libxml_disable_entity_loader(old);
+@@ -146,6 +147,7 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
+ ctxt->sax->warning = NULL;
+ ctxt->sax->error = NULL;
+ /*ctxt->sax->fatalError = NULL;*/
++ /* TODO: In libxml2 2.14.0 change this to the new options API so we don't rely on deprecated APIs. */
+ ctxt->options |= XML_PARSE_HUGE;
+ old = php_libxml_disable_entity_loader(1);
+ xmlParseDocument(ctxt);
+diff --git a/ext/soap/tests/bugs/bug42151.phpt b/ext/soap/tests/bugs/bug42151.phpt
+index f945a8753e5..dd14d1afb62 100644
+--- a/ext/soap/tests/bugs/bug42151.phpt
++++ b/ext/soap/tests/bugs/bug42151.phpt
+@@ -25,8 +25,8 @@ try {
+ }
+ echo "ok\n";
+ ?>
+---EXPECT--
+-SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load external entity "httpx://"
++--EXPECTF--
++SOAP-ERROR: Parsing WSDL: Couldn't load from 'httpx://' : failed to load %s
+
+ ok
+ I don't get executed either.
+diff --git a/ext/xml/compat.c b/ext/xml/compat.c
+index 3b2a0cdf7fb..4d1f506840a 100644
+--- a/ext/xml/compat.c
++++ b/ext/xml/compat.c
+@@ -714,8 +714,7 @@ XML_GetCurrentByteCount(XML_Parser parser)
+ {
+ /* WARNING: this is identical to ByteIndex; it should probably
+ * be different */
+- return parser->parser->input->consumed +
+- (parser->parser->input->cur - parser->parser->input->base);
++ return XML_GetCurrentByteIndex(parser);
+ }
+
+ PHP_XML_API const XML_Char *XML_ExpatVersion(void)
+diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c
+index 61e4a3a7d95..8a3fa1cea67 100644
+--- a/ext/xmlwriter/php_xmlwriter.c
++++ b/ext/xmlwriter/php_xmlwriter.c
+@@ -1001,7 +1001,8 @@ static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string)
+ }
+ output_bytes = xmlTextWriterFlush(ptr);
+ if (buffer) {
+- RETVAL_STRING((char *) buffer->content);
++ const xmlChar *content = xmlBufferContent(buffer);
++ RETVAL_STRING((const char *) content);
+ if (empty) {
+ xmlBufferEmpty(buffer);
+ }
+--
+2.48.1
+
+From 1196e566681a34564c02173ba234b5a42587ff07 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@tideways-gmbh.com>
+Date: Wed, 20 Nov 2024 10:47:27 +0100
+Subject: [PATCH 08/11] Fix GHSA-p3x9-6h7p-cgfc: libxml streams wrong
+ `content-type` on redirect
+
+libxml streams use wrong content-type header when requesting a
+redirected resource.
+
+(cherry picked from commit b6004a043c16b211d462218fbb3f72db68ec2b18)
+---
+ ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt | 60 +++++++++++++++++
+ ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt | 60 +++++++++++++++++
+ ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt | 60 +++++++++++++++++
+ ext/libxml/libxml.c | 77 ++++++++++++----------
+ 4 files changed, 224 insertions(+), 33 deletions(-)
+ create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt
+ create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt
+ create mode 100644 ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt
+
+diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt
+new file mode 100644
+index 00000000000..47212cb3410
+--- /dev/null
++++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_001.phpt
+@@ -0,0 +1,60 @@
++--TEST--
++GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Basic)
++--EXTENSIONS--
++dom
++--SKIPIF--
++<?php
++if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
++http_server_skipif();
++?>
++--FILE--
++<?php
++require "./ext/standard/tests/http/server.inc";
++
++function genResponses($server) {
++ $uri = 'http://' . stream_socket_get_name($server, false);
++ yield "data://text/plain,HTTP/1.1 302 Moved Temporarily\r\nLocation: $uri/document.xml\r\nContent-Type: text/html;charset=utf-16\r\n\r\n";
++ $xml = <<<'EOT'
++ <!doctype html>
++ <html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8" />
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++ </html>
++ EOT;
++ // Intentionally using non-standard casing for content-type to verify it is matched not case sensitively.
++ yield "data://text/plain,HTTP/1.1 200 OK\r\nconteNt-tyPe: text/html; charset=utf-8\r\n\r\n{$xml}";
++}
++
++['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output);
++$document = new \DOMDocument();
++$document->loadHTMLFile($uri);
++
++$h1 = $document->getElementsByTagName('h1');
++var_dump($h1->length);
++var_dump($document->saveHTML());
++http_server_kill($pid);
++?>
++--EXPECT--
++int(1)
++string(266) "<!DOCTYPE html>
++<html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8">
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++</html>
++"
+diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt
+new file mode 100644
+index 00000000000..a7eff3b9a8b
+--- /dev/null
++++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_002.phpt
+@@ -0,0 +1,60 @@
++--TEST--
++GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Missing content-type)
++--EXTENSIONS--
++dom
++--SKIPIF--
++<?php
++if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
++http_server_skipif();
++?>
++--FILE--
++<?php
++require "./ext/standard/tests/http/server.inc";
++
++function genResponses($server) {
++ $uri = 'http://' . stream_socket_get_name($server, false);
++ yield "data://text/plain,HTTP/1.1 302 Moved Temporarily\r\nLocation: $uri/document.xml\r\nContent-Type: text/html;charset=utf-16\r\n\r\n";
++ $xml = <<<'EOT'
++ <!doctype html>
++ <html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8" />
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++ </html>
++ EOT;
++ // Missing content-type in actual response.
++ yield "data://text/plain,HTTP/1.1 200 OK\r\n\r\n{$xml}";
++}
++
++['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output);
++$document = new \DOMDocument();
++$document->loadHTMLFile($uri);
++
++$h1 = $document->getElementsByTagName('h1');
++var_dump($h1->length);
++var_dump($document->saveHTML());
++http_server_kill($pid);
++?>
++--EXPECT--
++int(1)
++string(266) "<!DOCTYPE html>
++<html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8">
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++</html>
++"
+diff --git a/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt
+new file mode 100644
+index 00000000000..178b35f3525
+--- /dev/null
++++ b/ext/dom/tests/ghsa-p3x9-6h7p-cgfc_003.phpt
+@@ -0,0 +1,60 @@
++--TEST--
++GHSA-p3x9-6h7p-cgfc: libxml streams use wrong `content-type` header when requesting a redirected resource (Reason with colon)
++--EXTENSIONS--
++dom
++--SKIPIF--
++<?php
++if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
++http_server_skipif();
++?>
++--FILE--
++<?php
++require "./ext/standard/tests/http/server.inc";
++
++function genResponses($server) {
++ $uri = 'http://' . stream_socket_get_name($server, false);
++ yield "data://text/plain,HTTP/1.1 302 Moved Temporarily\r\nLocation: $uri/document.xml\r\nContent-Type: text/html;charset=utf-16\r\n\r\n";
++ $xml = <<<'EOT'
++ <!doctype html>
++ <html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8" />
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++ </html>
++ EOT;
++ // Missing content-type in actual response.
++ yield "data://text/plain,HTTP/1.1 200 OK: This is fine\r\n\r\n{$xml}";
++}
++
++['pid' => $pid, 'uri' => $uri] = http_server('genResponses', $output);
++$document = new \DOMDocument();
++$document->loadHTMLFile($uri);
++
++$h1 = $document->getElementsByTagName('h1');
++var_dump($h1->length);
++var_dump($document->saveHTML());
++http_server_kill($pid);
++?>
++--EXPECT--
++int(1)
++string(266) "<!DOCTYPE html>
++<html>
++ <head>
++ <title>GHSA-p3x9-6h7p-cgfc</title>
++
++ <meta charset="utf-8">
++ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
++ </head>
++
++ <body>
++ <h1>GHSA-p3x9-6h7p-cgfc</h1>
++ </body>
++</html>
++"
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index 28dd86a55c9..7886ca79ad9 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -372,42 +372,53 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
+ if (Z_TYPE(s->wrapperdata) == IS_ARRAY) {
+ zval *header;
+
+- ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) {
++ /* Scan backwards: The header array might contain the headers for multiple responses, if
++ * a redirect was followed.
++ */
++ ZEND_HASH_REVERSE_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) {
+ const char buf[] = "Content-Type:";
+- if (Z_TYPE_P(header) == IS_STRING &&
+- !zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) {
+- char *needle = estrdup("charset=");
+- char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header));
+- char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1);
+-
+- if (encoding) {
+- char *end;
+-
+- encoding += sizeof("charset=")-1;
+- if (*encoding == '"') {
+- encoding++;
+- }
+- end = strchr(encoding, ';');
+- if (end == NULL) {
+- end = encoding + strlen(encoding);
+- }
+- end--; /* end == encoding-1 isn't a buffer underrun */
+- while (*end == ' ' || *end == '\t') {
+- end--;
+- }
+- if (*end == '"') {
+- end--;
+- }
+- if (encoding >= end) continue;
+- *(end+1) = '\0';
+- enc = xmlParseCharEncoding(encoding);
+- if (enc <= XML_CHAR_ENCODING_NONE) {
+- enc = XML_CHAR_ENCODING_NONE;
++ if (Z_TYPE_P(header) == IS_STRING) {
++ /* If no colon is found in the header, we assume it's the HTTP status line and bail out. */
++ char *colon = memchr(Z_STRVAL_P(header), ':', Z_STRLEN_P(header));
++ char *space = memchr(Z_STRVAL_P(header), ' ', Z_STRLEN_P(header));
++ if (colon == NULL || space < colon) {
++ break;
++ }
++
++ if (!zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) {
++ char *needle = estrdup("charset=");
++ char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header));
++ char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1);
++
++ if (encoding) {
++ char *end;
++
++ encoding += sizeof("charset=")-1;
++ if (*encoding == '"') {
++ encoding++;
++ }
++ end = strchr(encoding, ';');
++ if (end == NULL) {
++ end = encoding + strlen(encoding);
++ }
++ end--; /* end == encoding-1 isn't a buffer underrun */
++ while (*end == ' ' || *end == '\t') {
++ end--;
++ }
++ if (*end == '"') {
++ end--;
++ }
++ if (encoding >= end) continue;
++ *(end+1) = '\0';
++ enc = xmlParseCharEncoding(encoding);
++ if (enc <= XML_CHAR_ENCODING_NONE) {
++ enc = XML_CHAR_ENCODING_NONE;
++ }
+ }
++ efree(haystack);
++ efree(needle);
++ break; /* found content-type */
+ }
+- efree(haystack);
+- efree(needle);
+- break; /* found content-type */
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+--
+2.48.1
+
+From 294140ee981fda6a38244215e4b16e53b7f5b2a6 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Wed, 18 Dec 2024 18:44:05 +0100
+Subject: [PATCH 09/11] Fix GHSA-wg4p-4hqh-c3g9
+
+(cherry picked from commit 0e715e71d945b68f8ccedd62c5960df747af6625)
+---
+ ext/xml/tests/toffset_bounds.phpt | 42 +++++++++++++++++++++++++++++++
+ ext/xml/xml.c | 12 ++++++---
+ 2 files changed, 50 insertions(+), 4 deletions(-)
+ create mode 100644 ext/xml/tests/toffset_bounds.phpt
+
+diff --git a/ext/xml/tests/toffset_bounds.phpt b/ext/xml/tests/toffset_bounds.phpt
+new file mode 100644
+index 00000000000..5a3fd22f86c
+--- /dev/null
++++ b/ext/xml/tests/toffset_bounds.phpt
+@@ -0,0 +1,42 @@
++--TEST--
++XML_OPTION_SKIP_TAGSTART bounds
++--EXTENSIONS--
++xml
++--FILE--
++<?php
++$sample = "<?xml version=\"1.0\"?><test><child/></test>";
++$parser = xml_parser_create();
++xml_parser_set_option($parser, XML_OPTION_SKIP_TAGSTART, 100);
++$res = xml_parse_into_struct($parser,$sample,$vals,$index);
++var_dump($vals);
++?>
++--EXPECT--
++array(3) {
++ [0]=>
++ array(3) {
++ ["tag"]=>
++ string(0) ""
++ ["type"]=>
++ string(4) "open"
++ ["level"]=>
++ int(1)
++ }
++ [1]=>
++ array(3) {
++ ["tag"]=>
++ string(0) ""
++ ["type"]=>
++ string(8) "complete"
++ ["level"]=>
++ int(2)
++ }
++ [2]=>
++ array(3) {
++ ["tag"]=>
++ string(0) ""
++ ["type"]=>
++ string(5) "close"
++ ["level"]=>
++ int(1)
++ }
++}
+diff --git a/ext/xml/xml.c b/ext/xml/xml.c
+index cc1457d9705..cac86ca7508 100644
+--- a/ext/xml/xml.c
++++ b/ext/xml/xml.c
+@@ -668,9 +668,11 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch
+ array_init(&tag);
+ array_init(&atr);
+
+- _xml_add_to_info(parser, ZSTR_VAL(tag_name) + parser->toffset);
++ char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name));
+
+- add_assoc_string(&tag, "tag", SKIP_TAGSTART(ZSTR_VAL(tag_name))); /* cast to avoid gcc-warning */
++ _xml_add_to_info(parser, skipped_tag_name);
++
++ add_assoc_string(&tag, "tag", skipped_tag_name);
+ add_assoc_string(&tag, "type", "open");
+ add_assoc_long(&tag, "level", parser->level);
+
+@@ -737,9 +739,11 @@ void _xml_endElementHandler(void *userData, const XML_Char *name)
+ } else {
+ array_init(&tag);
+
+- _xml_add_to_info(parser, ZSTR_VAL(tag_name) + parser->toffset);
++ char *skipped_tag_name = SKIP_TAGSTART(ZSTR_VAL(tag_name));
++
++ _xml_add_to_info(parser, skipped_tag_name);
+
+- add_assoc_string(&tag, "tag", SKIP_TAGSTART(ZSTR_VAL(tag_name))); /* cast to avoid gcc-warning */
++ add_assoc_string(&tag, "tag", skipped_tag_name);
+ add_assoc_string(&tag, "type", "close");
+ add_assoc_long(&tag, "level", parser->level);
+
+--
+2.48.1
+
+From d7ab2bb9856d938fca7989575695c14c25892589 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 17 Nov 2023 19:45:40 +0100
+Subject: [PATCH 10/11] Fix GH-12702: libxml2 2.12.0 issue building from src
+
+Fixes GH-12702.
+
+Co-authored-by: nono303 <github@nono303.net>
+(cherry picked from commit 6a76e5d0a2dcf46b4ab74cc3ffcbfeb860c4fdb3)
+---
+ ext/dom/document.c | 1 +
+ ext/libxml/php_libxml.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/ext/dom/document.c b/ext/dom/document.c
+index 7735e5d5dc3..5ef5dc479d6 100644
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -23,6 +23,7 @@
+ #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
+ #include "php_dom.h"
+ #include <libxml/SAX.h>
++#include <libxml/xmlsave.h>
+ #ifdef LIBXML_SCHEMAS_ENABLED
+ #include <libxml/relaxng.h>
+ #include <libxml/xmlschemas.h>
+diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h
+index d0ce7cec714..02717417a71 100644
+--- a/ext/libxml/php_libxml.h
++++ b/ext/libxml/php_libxml.h
+@@ -35,6 +35,7 @@ extern zend_module_entry libxml_module_entry;
+
+ #include "zend_smart_str.h"
+ #include <libxml/tree.h>
++#include <libxml/parser.h>
+
+ #define LIBXML_SAVE_NOEMPTYTAG 1<<2
+
+--
+2.48.1
+
+From adae2b8de8963ac6f92103803bf91a5174172f88 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 13 Mar 2025 09:39:19 +0100
+Subject: [PATCH 11/11] NEWS
+
+---
+ NEWS | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index e043901ee96..7db6f2660d2 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,23 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.32
++
++- LibXML:
++ . Fixed GHSA-wg4p-4hqh-c3g9 (Reocurrence of #72714). (nielsdos)
++ . Fixed GHSA-p3x9-6h7p-cgfc (libxml streams use wrong `content-type` header
++ when requesting a redirected resource). (CVE-2025-1219) (timwolla)
++
++- Streams:
++ . Fixed GHSA-hgf54-96fm-v528 (Stream HTTP wrapper header check might omit
++ basic auth header). (CVE-2025-1736) (Jakub Zelenka)
++ . Fixed GHSA-52jp-hrpf-2jff (Stream HTTP wrapper truncate redirect location
++ to 1024 bytes). (CVE-2025-1861) (Jakub Zelenka)
++ . Fixed GHSA-pcmh-g36c-qc44 (Streams HTTP wrapper does not fail for headers
++ without colon). (CVE-2025-1734) (Jakub Zelenka)
++ . Fixed GHSA-v8xr-gpvj-cx9g (Header parser of `http` stream wrapper does not
++ handle folded headers). (CVE-2025-1217) (Jakub Zelenka)
++
+ Backported from 8.1.31
+
+ - CLI:
+--
+2.48.1
+
diff --git a/php-cve-2025-1220.patch b/php-cve-2025-1220.patch
new file mode 100644
index 0000000..dad45e0
--- /dev/null
+++ b/php-cve-2025-1220.patch
@@ -0,0 +1,153 @@
+From 36150278addd8686a9899559241296094bd57282 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Thu, 10 Apr 2025 15:15:36 +0200
+Subject: [PATCH 2/4] Fix GHSA-3cr5-j632-f35r: Null byte in hostnames
+
+This fixes stream_socket_client() and fsockopen().
+
+Specifically it adds a check to parse_ip_address_ex and it also makes
+sure that the \0 is not ignored in fsockopen() hostname formatting.
+
+(cherry picked from commit cac8f7f1cf4939f55f06b68120040f057682d89c)
+---
+ ext/standard/fsock.c | 27 +++++++++++++++++--
+ .../tests/network/ghsa-3cr5-j632-f35r.phpt | 21 +++++++++++++++
+ .../tests/streams/ghsa-3cr5-j632-f35r.phpt | 26 ++++++++++++++++++
+ main/streams/xp_socket.c | 9 ++++---
+ 4 files changed, 78 insertions(+), 5 deletions(-)
+ create mode 100644 ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt
+ create mode 100644 ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt
+
+diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
+index a9c3cb0bf5d..636dbb6e359 100644
+--- a/ext/standard/fsock.c
++++ b/ext/standard/fsock.c
+@@ -23,6 +23,28 @@
+ #include "php_network.h"
+ #include "file.h"
+
++static size_t php_fsockopen_format_host_port(char **message, const char *prefix, size_t prefix_len,
++ const char *host, size_t host_len, zend_long port)
++{
++ char portbuf[32];
++ int portlen = snprintf(portbuf, sizeof(portbuf), ":" ZEND_LONG_FMT, port);
++ size_t total_len = prefix_len + host_len + portlen;
++
++ char *result = emalloc(total_len + 1);
++
++ if (prefix_len > 0) {
++ memcpy(result, prefix, prefix_len);
++ }
++ memcpy(result + prefix_len, host, host_len);
++ memcpy(result + prefix_len + host_len, portbuf, portlen);
++
++ result[total_len] = '\0';
++
++ *message = result;
++
++ return total_len;
++}
++
+ /* {{{ php_fsockopen() */
+
+ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+@@ -62,11 +84,12 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+ }
+
+ if (persistent) {
+- spprintf(&hashkey, 0, "pfsockopen__%s:" ZEND_LONG_FMT, host, port);
++ php_fsockopen_format_host_port(&hashkey, "pfsockopen__", strlen("pfsockopen__"), host,
++ host_len, port);
+ }
+
+ if (port > 0) {
+- hostname_len = spprintf(&hostname, 0, "%s:" ZEND_LONG_FMT, host, port);
++ hostname_len = php_fsockopen_format_host_port(&hostname, "", 0, host, host_len, port);
+ } else {
+ hostname_len = host_len;
+ hostname = host;
+diff --git a/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt b/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt
+new file mode 100644
+index 00000000000..7556c3be94c
+--- /dev/null
++++ b/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt
+@@ -0,0 +1,21 @@
++--TEST--
++GHSA-3cr5-j632-f35r: Null byte termination in fsockopen()
++--FILE--
++<?php
++
++$server = stream_socket_server("tcp://localhost:0");
++
++if (preg_match('/:(\d+)$/', stream_socket_get_name($server, false), $m)) {
++ $client = fsockopen("localhost\0.example.com", intval($m[1]));
++ var_dump($client);
++ if ($client) {
++ fclose($client);
++ }
++}
++fclose($server);
++
++?>
++--EXPECTF--
++
++Warning: fsockopen(): Unable to connect to localhost:%d (The hostname must not contain null bytes) in %s
++bool(false)
+diff --git a/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt b/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt
+new file mode 100644
+index 00000000000..52f9263c99a
+--- /dev/null
++++ b/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt
+@@ -0,0 +1,26 @@
++--TEST--
++GHSA-3cr5-j632-f35r: Null byte termination in stream_socket_client()
++--FILE--
++<?php
++
++$server = stream_socket_server("tcp://localhost:0");
++$socket_name = stream_socket_get_name($server, false);
++
++if (preg_match('/:(\d+)$/', $socket_name, $m)) {
++ $port = $m[1];
++ $client = stream_socket_client("tcp://localhost\0.example.com:$port");
++ var_dump($client);
++ if ($client) {
++ fclose($client);
++ }
++} else {
++ echo "Could not extract port from socket name: $socket_name\n";
++}
++
++fclose($server);
++
++?>
++--EXPECTF--
++
++Warning: stream_socket_client(): Unable to connect to tcp://localhost\0.example.com:%d (The hostname must not contain null bytes) in %s
++bool(false)
+diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c
+index 68df3366340..47f1bdd4b1d 100644
+--- a/main/streams/xp_socket.c
++++ b/main/streams/xp_socket.c
+@@ -580,12 +580,15 @@ static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *po
+ char *colon;
+ char *host = NULL;
+
+-#ifdef HAVE_IPV6
+- char *p;
++ if (memchr(str, '\0', str_len)) {
++ *err = strpprintf(0, "The hostname must not contain null bytes");
++ return NULL;
++ }
+
++#ifdef HAVE_IPV6
+ if (*(str) == '[' && str_len > 1) {
+ /* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */
+- p = memchr(str + 1, ']', str_len - 2);
++ char *p = memchr(str + 1, ']', str_len - 2);
+ if (!p || *(p + 1) != ':') {
+ if (get_err) {
+ *err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str);
+--
+2.50.0
+
diff --git a/php-cve-2025-1734.patch b/php-cve-2025-1734.patch
new file mode 100644
index 0000000..b7705f2
--- /dev/null
+++ b/php-cve-2025-1734.patch
@@ -0,0 +1,300 @@
+From e81d0cd14bfeb17e899c73e3aece4991bbda76af Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 19 Jan 2025 17:49:53 +0100
+Subject: [PATCH 02/11] Fix GHSA-pcmh-g36c-qc44: http headers without colon
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The header line must contain colon otherwise it is invalid and it needs
+to fail.
+
+Reviewed-by: Tim Düsterhus <tim@tideways-gmbh.com>
+(cherry picked from commit 0548c4c1756724a89ef8310709419b08aadb2b3b)
+---
+ ext/standard/http_fopen_wrapper.c | 51 ++++++++++++++-----
+ ext/standard/tests/http/bug47021.phpt | 22 ++++----
+ ext/standard/tests/http/bug75535.phpt | 4 +-
+ .../tests/http/ghsa-pcmh-g36c-qc44-001.phpt | 51 +++++++++++++++++++
+ .../tests/http/ghsa-pcmh-g36c-qc44-002.phpt | 51 +++++++++++++++++++
+ 5 files changed, 154 insertions(+), 25 deletions(-)
+ create mode 100644 ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index bfc88a74545..7ee22b85f88 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -117,6 +117,7 @@ static zend_bool check_has_header(const char *headers, const char *header) {
+ typedef struct _php_stream_http_response_header_info {
+ php_stream_filter *transfer_encoding;
+ size_t file_size;
++ bool error;
+ bool follow_location;
+ char location[HTTP_HEADER_BLOCK_SIZE];
+ } php_stream_http_response_header_info;
+@@ -126,6 +127,7 @@ static void php_stream_http_response_header_info_init(
+ {
+ header_info->transfer_encoding = NULL;
+ header_info->file_size = 0;
++ header_info->error = false;
+ header_info->follow_location = 1;
+ header_info->location[0] = '\0';
+ }
+@@ -163,10 +165,11 @@ static bool php_stream_http_response_header_trim(char *http_header_line,
+ /* Process folding headers of the current line and if there are none, parse last full response
+ * header line. It returns NULL if the last header is finished, otherwise it returns updated
+ * last header line. */
+-static zend_string *php_stream_http_response_headers_parse(php_stream *stream,
+- php_stream_context *context, int options, zend_string *last_header_line_str,
+- char *header_line, size_t *header_line_length, int response_code,
+- zval *response_header, php_stream_http_response_header_info *header_info)
++static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *wrapper,
++ php_stream *stream, php_stream_context *context, int options,
++ zend_string *last_header_line_str, char *header_line, size_t *header_line_length,
++ int response_code, zval *response_header,
++ php_stream_http_response_header_info *header_info)
+ {
+ char *last_header_line = ZSTR_VAL(last_header_line_str);
+ size_t last_header_line_length = ZSTR_LEN(last_header_line_str);
+@@ -208,6 +211,19 @@ static zend_string *php_stream_http_response_headers_parse(php_stream *stream,
+ /* Find header separator position. */
+ char *last_header_value = memchr(last_header_line, ':', last_header_line_length);
+ if (last_header_value) {
++ /* Verify there is no space in header name */
++ char *last_header_name = last_header_line + 1;
++ while (last_header_name < last_header_value) {
++ if (*last_header_name == ' ' || *last_header_name == '\t') {
++ header_info->error = true;
++ php_stream_wrapper_log_error(wrapper, options,
++ "HTTP invalid response format (space in header name)!");
++ zend_string_efree(last_header_line_str);
++ return NULL;
++ }
++ ++last_header_name;
++ }
++
+ last_header_value++; /* Skip ':'. */
+
+ /* Strip leading whitespace. */
+@@ -216,9 +232,12 @@ static zend_string *php_stream_http_response_headers_parse(php_stream *stream,
+ last_header_value++;
+ }
+ } else {
+- /* There is no colon. Set the value to the end of the header line, which is effectively
+- * an empty string. */
+- last_header_value = last_header_line_end;
++ /* There is no colon which means invalid response so error. */
++ header_info->error = true;
++ php_stream_wrapper_log_error(wrapper, options,
++ "HTTP invalid response format (no colon in header line)!");
++ zend_string_efree(last_header_line_str);
++ return NULL;
+ }
+
+ bool store_header = true;
+@@ -928,10 +947,16 @@ finish:
+
+ if (last_header_line_str != NULL) {
+ /* Parse last header line. */
+- last_header_line_str = php_stream_http_response_headers_parse(stream, context,
+- options, last_header_line_str, http_header_line, &http_header_line_length,
+- response_code, response_header, &header_info);
+- if (last_header_line_str != NULL) {
++ last_header_line_str = php_stream_http_response_headers_parse(wrapper, stream,
++ context, options, last_header_line_str, http_header_line,
++ &http_header_line_length, response_code, response_header, &header_info);
++ if (EXPECTED(last_header_line_str == NULL)) {
++ if (UNEXPECTED(header_info.error)) {
++ php_stream_close(stream);
++ stream = NULL;
++ goto out;
++ }
++ } else {
+ /* Folding header present so continue. */
+ continue;
+ }
+@@ -961,8 +986,8 @@ finish:
+
+ /* If the stream was closed early, we still want to process the last line to keep BC. */
+ if (last_header_line_str != NULL) {
+- php_stream_http_response_headers_parse(stream, context, options, last_header_line_str,
+- NULL, NULL, response_code, response_header, &header_info);
++ php_stream_http_response_headers_parse(wrapper, stream, context, options,
++ last_header_line_str, NULL, NULL, response_code, response_header, &header_info);
+ }
+
+ if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) {
+diff --git a/ext/standard/tests/http/bug47021.phpt b/ext/standard/tests/http/bug47021.phpt
+index 326eceb687a..168721f4ec1 100644
+--- a/ext/standard/tests/http/bug47021.phpt
++++ b/ext/standard/tests/http/bug47021.phpt
+@@ -70,23 +70,27 @@ do_test(1, true);
+ echo "\n";
+
+ ?>
+---EXPECT--
++--EXPECTF--
++
+ Type='text/plain'
+ Hello
+-Size=5
+-World
++
++Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s
++
+
+ Type='text/plain'
+ Hello
+-Size=5
+-World
++
++Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s
++
+
+ Type='text/plain'
+ Hello
+-Size=5
+-World
++
++Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s
++
+
+ Type='text/plain'
+ Hello
+-Size=5
+-World
++
++Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s
+diff --git a/ext/standard/tests/http/bug75535.phpt b/ext/standard/tests/http/bug75535.phpt
+index 7b015890d2f..94348d1a027 100644
+--- a/ext/standard/tests/http/bug75535.phpt
++++ b/ext/standard/tests/http/bug75535.phpt
+@@ -21,9 +21,7 @@ http_server_kill($pid);
+
+ --EXPECT--
+ string(0) ""
+-array(2) {
++array(1) {
+ [0]=>
+ string(15) "HTTP/1.0 200 Ok"
+- [1]=>
+- string(14) "Content-Length"
+ }
+diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
+new file mode 100644
+index 00000000000..bb7945ce62d
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt
+@@ -0,0 +1,51 @@
++--TEST--
++GHSA-pcmh-g36c-qc44: Header parser of http stream wrapper does not verify header name and colon (colon)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html\r\nWrong-Header\r\nGood-Header: test\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (no colon in header line)! in %s
++bool(false)
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(23) "Content-Type: text/html"
++}
+diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
+new file mode 100644
+index 00000000000..1d0e4fa70a2
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt
+@@ -0,0 +1,51 @@
++--TEST--
++GHSA-pcmh-g36c-qc44: Header parser of http stream wrapper does not verify header name and colon (name)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html\r\nWrong-Header : test\r\nGood-Header: test\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP invalid response format (space in header name)! in %s
++bool(false)
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(23) "Content-Type: text/html"
++}
+--
+2.48.1
+
diff --git a/php-cve-2025-1735.patch b/php-cve-2025-1735.patch
new file mode 100644
index 0000000..60e7e2e
--- /dev/null
+++ b/php-cve-2025-1735.patch
@@ -0,0 +1,490 @@
+From 7633d987cc11ee2601223e73cfdb8b31fed5980f Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Tue, 4 Mar 2025 17:23:01 +0100
+Subject: [PATCH 3/4] Fix GHSA-hrwm-9436-5mv3: pgsql escaping no error checks
+
+This adds error checks for escape function is pgsql and pdo_pgsql
+extensions. It prevents possibility of storing not properly escaped
+data which could potentially lead to some security issues.
+
+(cherry picked from commit 9376aeef9f8ff81f2705b8016237ec3e30bdee44)
+---
+ ext/pdo_pgsql/pgsql_driver.c | 10 +-
+ ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt | 22 ++++
+ ext/pgsql/pgsql.c | 129 +++++++++++++++----
+ ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt | 64 +++++++++
+ 4 files changed, 202 insertions(+), 23 deletions(-)
+ create mode 100644 ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+ create mode 100644 ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+
+diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
+index c90ef468907..218a306fa3c 100644
+--- a/ext/pdo_pgsql/pgsql_driver.c
++++ b/ext/pdo_pgsql/pgsql_driver.c
+@@ -354,11 +354,15 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
+ unsigned char *escaped;
+ pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
+ size_t tmp_len;
++ int err;
+
+ switch (paramtype) {
+ case PDO_PARAM_LOB:
+ /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */
+ escaped = PQescapeByteaConn(H->server, (unsigned char *)unquoted, unquotedlen, &tmp_len);
++ if (escaped == NULL) {
++ return 0;
++ }
+ *quotedlen = tmp_len + 1;
+ *quoted = emalloc(*quotedlen + 1);
+ memcpy((*quoted)+1, escaped, *quotedlen-2);
+@@ -370,7 +374,11 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
+ default:
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ (*quoted)[0] = '\'';
+- *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, unquotedlen, NULL);
++ *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, unquotedlen, &err);
++ if (err) {
++ efree(*quoted);
++ return 0;
++ }
+ (*quoted)[*quotedlen + 1] = '\'';
+ (*quoted)[*quotedlen + 2] = '\0';
+ *quotedlen += 2;
+diff --git a/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt b/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+new file mode 100644
+index 00000000000..60e13613d04
+--- /dev/null
++++ b/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+@@ -0,0 +1,22 @@
++--TEST--
++#GHSA-hrwm-9436-5mv3: pdo_pgsql extension does not check for errors during escaping
++--SKIPIF--
++<?php
++if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
++require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
++require_once dirname(__FILE__) . '/config.inc';
++PDOTest::skip();
++?>
++--FILE--
++<?php
++require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
++require_once dirname(__FILE__) . '/config.inc';
++$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
++$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
++
++$invalid = "ABC\xff\x30';";
++var_dump($db->quote($invalid));
++
++?>
++--EXPECT--
++bool(false)
+diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
+index 588f481a498..e9a68a8555f 100644
+--- a/ext/pgsql/pgsql.c
++++ b/ext/pgsql/pgsql.c
+@@ -3298,10 +3298,16 @@ PHP_FUNCTION(pg_escape_string)
+
+ to = zend_string_safe_alloc(ZSTR_LEN(from), 2, 0, 0);
+ if (link) {
++ int err;
+ if ((pgsql = (PGconn *)zend_fetch_resource2(link, "PostgreSQL link", le_link, le_plink)) == NULL) {
+ RETURN_THROWS();
+ }
+- ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), NULL);
++ ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), &err);
++ if (err) {
++ zend_argument_value_error(ZEND_NUM_ARGS(), "Escaping string failed");
++ zend_string_efree(to);
++ RETURN_THROWS();
++ }
+ } else
+ {
+ ZSTR_LEN(to) = PQescapeString(ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from));
+@@ -3344,6 +3350,10 @@ PHP_FUNCTION(pg_escape_bytea)
+ to = (char *)PQescapeByteaConn(pgsql, (unsigned char *)from, (size_t)from_len, &to_len);
+ } else
+ to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
++ if (to == NULL) {
++ zend_argument_value_error(ZEND_NUM_ARGS(), "Escape failure");
++ RETURN_THROWS();
++ }
+
+ RETVAL_STRINGL(to, to_len-1); /* to_len includes additional '\0' */
+ PQfreemem(to);
+@@ -4251,7 +4261,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
+ char *escaped;
+ smart_str querystr = {0};
+ size_t new_len;
+- int i, num_rows;
++ int i, num_rows, err;
+ zval elem;
+
+ ZEND_ASSERT(*table_name);
+@@ -4290,7 +4300,14 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
+ "WHERE a.attnum > 0 AND c.relname = '");
+ }
+ escaped = (char *)safe_emalloc(strlen(tmp_name2), 2, 1);
+- new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, strlen(tmp_name2), NULL);
++ new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, strlen(tmp_name2), &err);
++ if (err) {
++ php_error_docref(NULL, E_WARNING, "Escaping table name '%s' failed", table_name);
++ efree(src);
++ efree(escaped);
++ smart_str_free(&querystr);
++ return FAILURE;
++ }
+ if (new_len) {
+ smart_str_appendl(&querystr, escaped, new_len);
+ }
+@@ -4298,7 +4315,14 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
+
+ smart_str_appends(&querystr, "' AND n.nspname = '");
+ escaped = (char *)safe_emalloc(strlen(tmp_name), 2, 1);
+- new_len = PQescapeStringConn(pg_link, escaped, tmp_name, strlen(tmp_name), NULL);
++ new_len = PQescapeStringConn(pg_link, escaped, tmp_name, strlen(tmp_name), &err);
++ if (err) {
++ php_error_docref(NULL, E_WARNING, "Escaping table namespace '%s' failed", table_name);
++ efree(src);
++ efree(escaped);
++ smart_str_free(&querystr);
++ return FAILURE;
++ }
+ if (new_len) {
+ smart_str_appendl(&querystr, escaped, new_len);
+ }
+@@ -4575,7 +4599,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
+ {
+ zend_string *field = NULL;
+ zval meta, *def, *type, *not_null, *has_default, *is_enum, *val, new_val;
+- int err = 0, skip_field;
++ int err = 0, escape_err = 0, skip_field;
+ php_pgsql_data_type data_type;
+
+ ZEND_ASSERT(pg_link != NULL);
+@@ -4829,10 +4853,14 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
+ /* PostgreSQL ignores \0 */
+ str = zend_string_alloc(Z_STRLEN_P(val) * 2, 0);
+ /* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
+- ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str), Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
+- str = zend_string_truncate(str, ZSTR_LEN(str), 0);
+- ZVAL_NEW_STR(&new_val, str);
+- php_pgsql_add_quotes(&new_val, 1);
++ ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str), Z_STRVAL_P(val), Z_STRLEN_P(val), &escape_err);
++ if (escape_err) {
++ err = 1;
++ } else {
++ str = zend_string_truncate(str, ZSTR_LEN(str), 0);
++ ZVAL_NEW_STR(&new_val, str);
++ php_pgsql_add_quotes(&new_val, 1);
++ }
+ }
+ break;
+
+@@ -4854,7 +4882,15 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
+ }
+ PGSQL_CONV_CHECK_IGNORE();
+ if (err) {
+- php_error_docref(NULL, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_P(type), ZSTR_VAL(field));
++ if (escape_err) {
++ php_error_docref(NULL, E_NOTICE,
++ "String value escaping failed for PostgreSQL '%s' (%s)",
++ Z_STRVAL_P(type), ZSTR_VAL(field));
++ } else {
++ php_error_docref(NULL, E_NOTICE,
++ "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)",
++ Z_STRVAL_P(type), ZSTR_VAL(field));
++ }
+ }
+ break;
+
+@@ -5129,6 +5165,11 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
+ size_t to_len;
+ smart_str s = {0};
+ tmp = PQescapeByteaConn(pg_link, (unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val), &to_len);
++ if (tmp == NULL) {
++ php_error_docref(NULL, E_NOTICE, "Escaping value failed for %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field));
++ err = 1;
++ break;
++ }
+ ZVAL_STRINGL(&new_val, (char *)tmp, to_len - 1); /* PQescapeBytea's to_len includes additional '\0' */
+ PQfreemem(tmp);
+ php_pgsql_add_quotes(&new_val, 1);
+@@ -5210,6 +5251,12 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
+ zend_hash_update(Z_ARRVAL_P(result), field, &new_val);
+ } else {
+ char *escaped = PQescapeIdentifier(pg_link, ZSTR_VAL(field), ZSTR_LEN(field));
++ if (escaped == NULL) {
++ /* This cannot fail because of invalid string but only due to failed memory allocation */
++ php_error_docref(NULL, E_NOTICE, "Escaping field '%s' failed", ZSTR_VAL(field));
++ err = 1;
++ break;
++ }
+ add_assoc_zval(result, escaped, &new_val);
+ PQfreemem(escaped);
+ }
+@@ -5290,7 +5337,7 @@ static int do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link,
+ }
+ /* }}} */
+
+-static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const char *table) /* {{{ */
++static inline zend_result build_tablename(smart_str *querystr, PGconn *pg_link, const char *table) /* {{{ */
+ {
+ size_t table_len = strlen(table);
+
+@@ -5301,6 +5348,10 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const c
+ smart_str_appendl(querystr, table, len);
+ } else {
+ char *escaped = PQescapeIdentifier(pg_link, table, len);
++ if (escaped == NULL) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", table);
++ return FAILURE;
++ }
+ smart_str_appends(querystr, escaped);
+ PQfreemem(escaped);
+ }
+@@ -5313,11 +5364,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const c
+ smart_str_appendl(querystr, after_dot, len);
+ } else {
+ char *escaped = PQescapeIdentifier(pg_link, after_dot, len);
++ if (escaped == NULL) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", table);
++ return FAILURE;
++ }
+ smart_str_appendc(querystr, '.');
+ smart_str_appends(querystr, escaped);
+ PQfreemem(escaped);
+ }
+ }
++
++ return SUCCESS;
+ }
+ /* }}} */
+
+@@ -5338,7 +5395,9 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var
+ ZVAL_UNDEF(&converted);
+ if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) {
+ smart_str_appends(&querystr, "INSERT INTO ");
+- build_tablename(&querystr, pg_link, table);
++ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, " DEFAULT VALUES");
+
+ goto no_values;
+@@ -5354,7 +5413,9 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var
+ }
+
+ smart_str_appends(&querystr, "INSERT INTO ");
+- build_tablename(&querystr, pg_link, table);
++ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, " (");
+
+ ZEND_HASH_FOREACH_STR_KEY(Z_ARRVAL_P(var_array), fld) {
+@@ -5364,6 +5425,10 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var
+ }
+ if (opt & PGSQL_DML_ESCAPE) {
+ tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1);
++ if (tmp == NULL) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld));
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, tmp);
+ PQfreemem(tmp);
+ } else {
+@@ -5375,15 +5440,19 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var
+ smart_str_appends(&querystr, ") VALUES (");
+
+ /* make values string */
+- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(var_array), val) {
++ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(var_array), fld, val) {
+ /* we can avoid the key_type check here, because we tested it in the other loop */
+ switch (Z_TYPE_P(val)) {
+ case IS_STRING:
+ if (opt & PGSQL_DML_ESCAPE) {
+- size_t new_len;
+- char *tmp;
+- tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1);
+- new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
++ int error;
++ char *tmp = safe_emalloc(Z_STRLEN_P(val), 2, 1);
++ size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error);
++ if (error) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld));
++ efree(tmp);
++ goto cleanup;
++ }
+ smart_str_appendc(&querystr, '\'');
+ smart_str_appendl(&querystr, tmp, new_len);
+ smart_str_appendc(&querystr, '\'');
+@@ -5537,6 +5606,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
+ }
+ if (opt & PGSQL_DML_ESCAPE) {
+ char *tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1);
++ if (tmp == NULL) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld));
++ return -1;
++ }
+ smart_str_appends(querystr, tmp);
+ PQfreemem(tmp);
+ } else {
+@@ -5551,8 +5624,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr,
+ switch (Z_TYPE_P(val)) {
+ case IS_STRING:
+ if (opt & PGSQL_DML_ESCAPE) {
++ int error;
+ char *tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1);
+- size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL);
++ size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error);
++ if (error) {
++ php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld));
++ efree(tmp);
++ return -1;
++ }
+ smart_str_appendc(querystr, '\'');
+ smart_str_appendl(querystr, tmp, new_len);
+ smart_str_appendc(querystr, '\'');
+@@ -5620,7 +5699,9 @@ PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var
+ }
+
+ smart_str_appends(&querystr, "UPDATE ");
+- build_tablename(&querystr, pg_link, table);
++ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, " SET ");
+
+ if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(var_array), 0, ",", 1, opt))
+@@ -5722,7 +5803,9 @@ PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids
+ }
+
+ smart_str_appends(&querystr, "DELETE FROM ");
+- build_tablename(&querystr, pg_link, table);
++ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, " WHERE ");
+
+ if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt))
+@@ -5860,7 +5943,9 @@ PHP_PGSQL_API void php_pgsql_result2array(PGresult *pg_result, zval *ret_array,
+ }
+
+ smart_str_appends(&querystr, "SELECT * FROM ");
+- build_tablename(&querystr, pg_link, table);
++ if (build_tablename(&querystr, pg_link, table) == FAILURE) {
++ goto cleanup;
++ }
+ smart_str_appends(&querystr, " WHERE ");
+
+ if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt))
+diff --git a/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt b/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+new file mode 100644
+index 00000000000..c1c5e05dce6
+--- /dev/null
++++ b/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt
+@@ -0,0 +1,64 @@
++--TEST--
++#GHSA-hrwm-9436-5mv3: pgsql extension does not check for errors during escaping
++--EXTENSIONS--
++pgsql
++--SKIPIF--
++<?php include("skipif.inc"); ?>
++--FILE--
++<?php
++
++include 'config.inc';
++define('FILE_NAME', __DIR__ . '/php.gif');
++
++$db = pg_connect($conn_str);
++pg_query($db, "DROP TABLE IF EXISTS ghsa_hrmw_9436_5mv3");
++pg_query($db, "CREATE TABLE ghsa_hrmw_9436_5mv3 (bar text);");
++
++// pg_escape_literal/pg_escape_identifier
++
++$invalid = "ABC\xff\x30';";
++$flags = PGSQL_DML_NO_CONV | PGSQL_DML_ESCAPE;
++
++var_dump(pg_insert($db, $invalid, ['bar' => 'test'])); // table name str escape in php_pgsql_meta_data
++var_dump(pg_insert($db, "$invalid.tbl", ['bar' => 'test'])); // schema name str escape in php_pgsql_meta_data
++var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', ['bar' => $invalid])); // converted value str escape in php_pgsql_convert
++var_dump(pg_insert($db, $invalid, [])); // ident escape in build_tablename
++var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', [$invalid => 'foo'], $flags)); // ident escape for field php_pgsql_insert
++var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', ['bar' => $invalid], $flags)); // str escape for field value in php_pgsql_insert
++var_dump(pg_update($db, 'ghsa_hrmw_9436_5mv3', ['bar' => 'val'], [$invalid => 'test'], $flags)); // ident escape in build_assignment_string
++var_dump(pg_update($db, 'ghsa_hrmw_9436_5mv3', ['bar' => 'val'], ['bar' => $invalid], $flags)); // invalid str escape in build_assignment_string
++var_dump(pg_escape_literal($db, $invalid)); // pg_escape_literal escape
++var_dump(pg_escape_identifier($db, $invalid)); // pg_escape_identifier escape
++
++?>
++--EXPECTF--
++
++Warning: pg_insert(): Escaping table name 'ABC%s';' failed in %s on line %d
++bool(false)
++
++Warning: pg_insert(): Escaping table namespace 'ABC%s';.tbl' failed in %s on line %d
++bool(false)
++
++Notice: pg_insert(): String value escaping failed for PostgreSQL 'text' (bar) in %s on line %d
++bool(false)
++
++Notice: pg_insert(): Failed to escape table name 'ABC%s';' in %s on line %d
++bool(false)
++
++Notice: pg_insert(): Failed to escape field 'ABC%s';' in %s on line %d
++bool(false)
++
++Notice: pg_insert(): Failed to escape field 'bar' value in %s on line %d
++bool(false)
++
++Notice: pg_update(): Failed to escape field 'ABC%s';' in %s on line %d
++bool(false)
++
++Notice: pg_update(): Failed to escape field 'bar' value in %s on line %d
++bool(false)
++
++Warning: pg_escape_literal(): Failed to escape in %s on line %d
++bool(false)
++
++Warning: pg_escape_identifier(): Failed to escape in %s on line %d
++bool(false)
+--
+2.50.0
+
+From 970548b94b7f23be32154d05a9545b10c98bfd62 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 3 Jul 2025 09:32:25 +0200
+Subject: [PATCH 4/4] NEWS
+
+---
+ NEWS | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 7db6f2660d2..c813f4f357a 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,20 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.33
++
++- PGSQL:
++ . Fixed GHSA-hrwm-9436-5mv3 (pgsql extension does not check for errors during
++ escaping). (CVE-2025-1735) (Jakub Zelenka)
++
++- SOAP:
++ . Fixed GHSA-453j-q27h-5p8x (NULL Pointer Dereference in PHP SOAP Extension
++ via Large XML Namespace Prefix). (CVE-2025-6491) (Lekssays, nielsdos)
++
++- Standard:
++ . Fixed GHSA-3cr5-j632-f35r (Null byte termination in hostnames).
++ (CVE-2025-1220) (Jakub Zelenka)
++
+ Backported from 8.1.32
+
+ - LibXML:
+--
+2.50.0
+
diff --git a/php-cve-2025-1736.patch b/php-cve-2025-1736.patch
new file mode 100644
index 0000000..134269d
--- /dev/null
+++ b/php-cve-2025-1736.patch
@@ -0,0 +1,241 @@
+From 8f65ef50929f6781f4973325f9b619f02cce19d8 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Fri, 14 Feb 2025 19:17:22 +0100
+Subject: [PATCH 04/11] Fix GHSA-hgf5-96fm-v528: http user header check of crlf
+
+(cherry picked from commit 41d49abbd99dab06cdae4834db664435f8177174)
+---
+ ext/standard/http_fopen_wrapper.c | 2 +-
+ .../tests/http/ghsa-hgf5-96fm-v528-001.phpt | 65 +++++++++++++++++++
+ .../tests/http/ghsa-hgf5-96fm-v528-002.phpt | 62 ++++++++++++++++++
+ .../tests/http/ghsa-hgf5-96fm-v528-003.phpt | 64 ++++++++++++++++++
+ 4 files changed, 192 insertions(+), 1 deletion(-)
+ create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index e9b2486a7c9..64703c2f56b 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -107,7 +107,7 @@ static inline void strip_header(char *header_bag, char *lc_header_bag,
+ static zend_bool check_has_header(const char *headers, const char *header) {
+ const char *s = headers;
+ while ((s = strstr(s, header))) {
+- if (s == headers || *(s-1) == '\n') {
++ if (s == headers || (*(s-1) == '\n' && *(s-2) == '\r')) {
+ return 1;
+ }
+ s++;
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
+new file mode 100644
+index 00000000000..c40123560ef
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt
+@@ -0,0 +1,65 @@
++--TEST--
++GHSA-hgf5-96fm-v528: Stream HTTP wrapper header check might omit basic auth header (incorrect inside pos)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ $result = fread($conn, 1024);
++ $encoded_result = base64_encode($result);
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n");
++
++CODE;
++
++$clientCode = <<<'CODE'
++ $opts = [
++ "http" => [
++ "method" => "GET",
++ "header" => "Cookie: foo=bar\nauthorization:x\r\n"
++ ]
++ ];
++ $ctx = stream_context_create($opts);
++ var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx))));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++array(7) {
++ [0]=>
++ string(14) "GET / HTTP/1.1"
++ [1]=>
++ string(33) "Authorization: Basic dXNlcjpwd2Q="
++ [2]=>
++ string(21) "Host: 127.0.0.1:%d"
++ [3]=>
++ string(17) "Connection: close"
++ [4]=>
++ string(31) "Cookie: foo=bar
++authorization:x"
++ [5]=>
++ string(0) ""
++ [6]=>
++ string(0) ""
++}
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(38) "Content-Type: text/html; charset=utf-8"
++}
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
+new file mode 100644
+index 00000000000..37a47df060a
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt
+@@ -0,0 +1,62 @@
++--TEST--
++GHSA-hgf5-96fm-v528: Header parser of http stream wrapper does not handle folded headers (correct start pos)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ $result = fread($conn, 1024);
++ $encoded_result = base64_encode($result);
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n");
++
++CODE;
++
++$clientCode = <<<'CODE'
++ $opts = [
++ "http" => [
++ "method" => "GET",
++ "header" => "Authorization: Bearer x\r\n"
++ ]
++ ];
++ $ctx = stream_context_create($opts);
++ var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx))));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++array(6) {
++ [0]=>
++ string(14) "GET / HTTP/1.1"
++ [1]=>
++ string(21) "Host: 127.0.0.1:%d"
++ [2]=>
++ string(17) "Connection: close"
++ [3]=>
++ string(23) "Authorization: Bearer x"
++ [4]=>
++ string(0) ""
++ [5]=>
++ string(0) ""
++}
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(38) "Content-Type: text/html; charset=utf-8"
++}
+diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
+new file mode 100644
+index 00000000000..6c84679ff63
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt
+@@ -0,0 +1,64 @@
++--TEST--
++GHSA-hgf5-96fm-v528: Header parser of http stream wrapper does not handle folded headers (correct middle pos)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++ $ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ $result = fread($conn, 1024);
++ $encoded_result = base64_encode($result);
++
++ fwrite($conn, "HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=utf-8\r\n\r\n$encoded_result\r\n");
++
++CODE;
++
++$clientCode = <<<'CODE'
++ $opts = [
++ "http" => [
++ "method" => "GET",
++ "header" => "Cookie: x=y\r\nAuthorization: Bearer x\r\n"
++ ]
++ ];
++ $ctx = stream_context_create($opts);
++ var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx))));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++array(7) {
++ [0]=>
++ string(14) "GET / HTTP/1.1"
++ [1]=>
++ string(21) "Host: 127.0.0.1:%d"
++ [2]=>
++ string(17) "Connection: close"
++ [3]=>
++ string(11) "Cookie: x=y"
++ [4]=>
++ string(23) "Authorization: Bearer x"
++ [5]=>
++ string(0) ""
++ [6]=>
++ string(0) ""
++}
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 200 Ok"
++ [1]=>
++ string(38) "Content-Type: text/html; charset=utf-8"
++}
+--
+2.48.1
+
diff --git a/php-cve-2025-1861.patch b/php-cve-2025-1861.patch
new file mode 100644
index 0000000..856d9be
--- /dev/null
+++ b/php-cve-2025-1861.patch
@@ -0,0 +1,348 @@
+From adc7e9f20c9a9aab9cd23ca47ec3fb96287898ae Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Tue, 4 Mar 2025 09:01:34 +0100
+Subject: [PATCH 03/11] Fix GHSA-52jp-hrpf-2jff: http redirect location
+ truncation
+
+It converts the allocation of location to be on heap instead of stack
+and errors if the location length is greater than 8086 bytes.
+
+(cherry picked from commit ac1a054bb3eb5994a199e8b18cca28cbabf5943e)
+---
+ ext/standard/http_fopen_wrapper.c | 87 ++++++++++++-------
+ .../tests/http/ghsa-52jp-hrpf-2jff-001.phpt | 58 +++++++++++++
+ .../tests/http/ghsa-52jp-hrpf-2jff-002.phpt | 55 ++++++++++++
+ 3 files changed, 168 insertions(+), 32 deletions(-)
+ create mode 100644 ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
+ create mode 100644 ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
+
+diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
+index 7ee22b85f88..e9b2486a7c9 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -67,15 +67,16 @@
+
+ #include "php_fopen_wrappers.h"
+
+-#define HTTP_HEADER_BLOCK_SIZE 1024
+-#define PHP_URL_REDIRECT_MAX 20
+-#define HTTP_HEADER_USER_AGENT 1
+-#define HTTP_HEADER_HOST 2
+-#define HTTP_HEADER_AUTH 4
+-#define HTTP_HEADER_FROM 8
+-#define HTTP_HEADER_CONTENT_LENGTH 16
+-#define HTTP_HEADER_TYPE 32
+-#define HTTP_HEADER_CONNECTION 64
++#define HTTP_HEADER_BLOCK_SIZE 1024
++#define HTTP_HEADER_MAX_LOCATION_SIZE 8182 /* 8192 - 10 (size of "Location: ") */
++#define PHP_URL_REDIRECT_MAX 20
++#define HTTP_HEADER_USER_AGENT 1
++#define HTTP_HEADER_HOST 2
++#define HTTP_HEADER_AUTH 4
++#define HTTP_HEADER_FROM 8
++#define HTTP_HEADER_CONTENT_LENGTH 16
++#define HTTP_HEADER_TYPE 32
++#define HTTP_HEADER_CONNECTION 64
+
+ #define HTTP_WRAPPER_HEADER_INIT 1
+ #define HTTP_WRAPPER_REDIRECTED 2
+@@ -119,17 +120,15 @@ typedef struct _php_stream_http_response_header_info {
+ size_t file_size;
+ bool error;
+ bool follow_location;
+- char location[HTTP_HEADER_BLOCK_SIZE];
++ char *location;
++ size_t location_len;
+ } php_stream_http_response_header_info;
+
+ static void php_stream_http_response_header_info_init(
+ php_stream_http_response_header_info *header_info)
+ {
+- header_info->transfer_encoding = NULL;
+- header_info->file_size = 0;
+- header_info->error = false;
++ memset(header_info, 0, sizeof(php_stream_http_response_header_info));
+ header_info->follow_location = 1;
+- header_info->location[0] = '\0';
+ }
+
+ /* Trim white spaces from response header line and update its length */
+@@ -255,7 +254,22 @@ static zend_string *php_stream_http_response_headers_parse(php_stream_wrapper *w
+ * RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
+ header_info->follow_location = 0;
+ }
+- strlcpy(header_info->location, last_header_value, sizeof(header_info->location));
++ size_t last_header_value_len = strlen(last_header_value);
++ if (last_header_value_len > HTTP_HEADER_MAX_LOCATION_SIZE) {
++ header_info->error = true;
++ php_stream_wrapper_log_error(wrapper, options,
++ "HTTP Location header size is over the limit of %d bytes",
++ HTTP_HEADER_MAX_LOCATION_SIZE);
++ zend_string_efree(last_header_line_str);
++ return NULL;
++ }
++ if (header_info->location_len == 0) {
++ header_info->location = emalloc(last_header_value_len + 1);
++ } else if (header_info->location_len <= last_header_value_len) {
++ header_info->location = erealloc(header_info->location, last_header_value_len + 1);
++ }
++ header_info->location_len = last_header_value_len;
++ memcpy(header_info->location, last_header_value, last_header_value_len + 1);
+ } else if (!strncasecmp(last_header_line, "Content-Type:", sizeof("Content-Type:")-1)) {
+ php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, last_header_value, 0);
+ } else if (!strncasecmp(last_header_line, "Content-Length:", sizeof("Content-Length:")-1)) {
+@@ -538,6 +552,8 @@ finish:
+ }
+ }
+
++ php_stream_http_response_header_info_init(&header_info);
++
+ if (stream == NULL)
+ goto out;
+
+@@ -919,8 +935,6 @@ finish:
+ }
+ }
+
+- php_stream_http_response_header_info_init(&header_info);
+-
+ /* read past HTTP headers */
+ while (!php_stream_eof(stream)) {
+ size_t http_header_line_length;
+@@ -990,12 +1004,12 @@ finish:
+ last_header_line_str, NULL, NULL, response_code, response_header, &header_info);
+ }
+
+- if (!reqok || (header_info.location[0] != '\0' && header_info.follow_location)) {
++ if (!reqok || (header_info.location != NULL && header_info.follow_location)) {
+ if (!header_info.follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) {
+ goto out;
+ }
+
+- if (header_info.location[0] != '\0')
++ if (header_info.location != NULL)
+ php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, header_info.location, 0);
+
+ php_stream_close(stream);
+@@ -1006,18 +1020,17 @@ finish:
+ header_info.transfer_encoding = NULL;
+ }
+
+- if (header_info.location[0] != '\0') {
++ if (header_info.location != NULL) {
+
+- char new_path[HTTP_HEADER_BLOCK_SIZE];
+- char loc_path[HTTP_HEADER_BLOCK_SIZE];
++ char *new_path = NULL;
+
+- *new_path='\0';
+ if (strlen(header_info.location) < 8 ||
+ (strncasecmp(header_info.location, "http://", sizeof("http://")-1) &&
+ strncasecmp(header_info.location, "https://", sizeof("https://")-1) &&
+ strncasecmp(header_info.location, "ftp://", sizeof("ftp://")-1) &&
+ strncasecmp(header_info.location, "ftps://", sizeof("ftps://")-1)))
+ {
++ char *loc_path = NULL;
+ if (*header_info.location != '/') {
+ if (*(header_info.location+1) != '\0' && resource->path) {
+ char *s = strrchr(ZSTR_VAL(resource->path), '/');
+@@ -1035,31 +1048,35 @@ finish:
+ if (resource->path &&
+ ZSTR_VAL(resource->path)[0] == '/' &&
+ ZSTR_VAL(resource->path)[1] == '\0') {
+- snprintf(loc_path, sizeof(loc_path) - 1, "%s%s",
+- ZSTR_VAL(resource->path), header_info.location);
++ spprintf(&loc_path, 0, "%s%s", ZSTR_VAL(resource->path), header_info.location);
+ } else {
+- snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s",
+- ZSTR_VAL(resource->path), header_info.location);
++ spprintf(&loc_path, 0, "%s/%s", ZSTR_VAL(resource->path), header_info.location);
+ }
+ } else {
+- snprintf(loc_path, sizeof(loc_path) - 1, "/%s", header_info.location);
++ spprintf(&loc_path, 0, "/%s", header_info.location);
+ }
+ } else {
+- strlcpy(loc_path, header_info.location, sizeof(loc_path));
++ loc_path = header_info.location;
++ header_info.location = NULL;
+ }
+ if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
+- snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path);
++ spprintf(&new_path, 0, "%s://%s:%d%s", ZSTR_VAL(resource->scheme),
++ ZSTR_VAL(resource->host), resource->port, loc_path);
+ } else {
+- snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), loc_path);
++ spprintf(&new_path, 0, "%s://%s%s", ZSTR_VAL(resource->scheme),
++ ZSTR_VAL(resource->host), loc_path);
+ }
++ efree(loc_path);
+ } else {
+- strlcpy(new_path, header_info.location, sizeof(new_path));
++ new_path = header_info.location;
++ header_info.location = NULL;
+ }
+
+ php_url_free(resource);
+ /* check for invalid redirection URLs */
+ if ((resource = php_url_parse(new_path)) == NULL) {
+ php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path);
++ efree(new_path);
+ goto out;
+ }
+
+@@ -1071,6 +1088,7 @@ finish:
+ while (s < e) { \
+ if (iscntrl(*s)) { \
+ php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path); \
++ efree(new_path); \
+ goto out; \
+ } \
+ s++; \
+@@ -1086,6 +1104,7 @@ finish:
+ stream = php_stream_url_wrap_http_ex(
+ wrapper, new_path, mode, options, opened_path, context,
+ --redirect_max, HTTP_WRAPPER_REDIRECTED, response_header STREAMS_CC);
++ efree(new_path);
+ } else {
+ php_stream_wrapper_log_error(wrapper, options, "HTTP request failed! %s", tmp_line);
+ }
+@@ -1098,6 +1117,10 @@ out:
+ efree(http_header_line);
+ }
+
++ if (header_info.location != NULL) {
++ efree(header_info.location);
++ }
++
+ if (resource) {
+ php_url_free(resource);
+ }
+diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
+new file mode 100644
+index 00000000000..744cff9cc72
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt
+@@ -0,0 +1,58 @@
++--TEST--
++GHSA-52jp-hrpf-2jff: HTTP stream wrapper truncate redirect location to 1024 bytes (success)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++$ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ $loc = str_repeat("y", 8000);
++ fwrite($conn, "HTTP/1.0 301 Ok\r\nContent-Type: text/html;\r\nLocation: $loc\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ case STREAM_NOTIFY_REDIRECTED:
++ echo "Redirected: ";
++ var_dump($message);
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx)));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html;
++Redirected: string(8000) "%s"
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: %s
++string(0) ""
++array(3) {
++ [0]=>
++ string(15) "HTTP/1.0 301 Ok"
++ [1]=>
++ string(24) "Content-Type: text/html;"
++ [2]=>
++ string(8010) "Location: %s"
++}
+diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
+new file mode 100644
+index 00000000000..bc71fd4e411
+--- /dev/null
++++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt
+@@ -0,0 +1,55 @@
++--TEST--
++GHSA-52jp-hrpf-2jff: HTTP stream wrapper truncate redirect location to 1024 bytes (over limit)
++--FILE--
++<?php
++$serverCode = <<<'CODE'
++$ctxt = stream_context_create([
++ "socket" => [
++ "tcp_nodelay" => true
++ ]
++ ]);
++
++ $server = stream_socket_server(
++ "tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ctxt);
++ phpt_notify_server_start($server);
++
++ $conn = stream_socket_accept($server);
++
++ phpt_notify(message:"server-accepted");
++
++ $loc = str_repeat("y", 9000);
++ fwrite($conn, "HTTP/1.0 301 Ok\r\nContent-Type: text/html;\r\nLocation: $loc\r\n\r\nbody\r\n");
++CODE;
++
++$clientCode = <<<'CODE'
++ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
++ switch($notification_code) {
++ case STREAM_NOTIFY_MIME_TYPE_IS:
++ echo "Found the mime-type: ", $message, PHP_EOL;
++ break;
++ case STREAM_NOTIFY_REDIRECTED:
++ echo "Redirected: ";
++ var_dump($message);
++ }
++ }
++
++ $ctx = stream_context_create();
++ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
++ var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx)));
++ var_dump($http_response_header);
++CODE;
++
++include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__);
++ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
++?>
++--EXPECTF--
++Found the mime-type: text/html;
++
++Warning: file_get_contents(http://127.0.0.1:%d): Failed to open stream: HTTP Location header size is over the limit of 8182 bytes in %s
++string(0) ""
++array(2) {
++ [0]=>
++ string(15) "HTTP/1.0 301 Ok"
++ [1]=>
++ string(24) "Content-Type: text/html;"
++}
+--
+2.48.1
+
diff --git a/php-cve-2025-6491.patch b/php-cve-2025-6491.patch
new file mode 100644
index 0000000..d4e4f36
--- /dev/null
+++ b/php-cve-2025-6491.patch
@@ -0,0 +1,102 @@
+From 1b7410a57f8a5fd1dd43854bcf7b9200517c9fd2 Mon Sep 17 00:00:00 2001
+From: Ahmed Lekssays <lekssaysahmed@gmail.com>
+Date: Tue, 3 Jun 2025 09:00:55 +0000
+Subject: [PATCH 1/4] Fix GHSA-453j-q27h-5p8x
+
+Libxml versions prior to 2.13 cannot correctly handle a call to
+xmlNodeSetName() with a name longer than 2G. It will leave the node
+object in an invalid state with a NULL name. This later causes a NULL
+pointer dereference when using the name during message serialization.
+
+To solve this, implement a workaround that resets the name to the
+sentinel name if this situation arises.
+
+Versions of libxml of 2.13 and higher are not affected.
+
+This can be exploited if a SoapVar is created with a fully qualified
+name that is longer than 2G. This would be possible if some application
+code uses a namespace prefix from an untrusted source like from a remote
+SOAP service.
+
+Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+(cherry picked from commit 9cb3d8d200f0c822b17bda35a2a67a97b039d3e1)
+---
+ ext/soap/soap.c | 6 ++--
+ ext/soap/tests/soap_qname_crash.phpt | 48 ++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+), 2 deletions(-)
+ create mode 100644 ext/soap/tests/soap_qname_crash.phpt
+
+diff --git a/ext/soap/soap.c b/ext/soap/soap.c
+index a8df136d665..08d6f285d28 100644
+--- a/ext/soap/soap.c
++++ b/ext/soap/soap.c
+@@ -4143,8 +4143,10 @@ static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName,
+ }
+ xmlParam = master_to_xml(enc, val, style, parent);
+ zval_ptr_dtor(&defval);
+- if (!strcmp((char*)xmlParam->name, "BOGUS")) {
+- xmlNodeSetName(xmlParam, BAD_CAST(paramName));
++ if (xmlParam != NULL) {
++ if (xmlParam->name == NULL || strcmp((char*)xmlParam->name, "BOGUS") == 0) {
++ xmlNodeSetName(xmlParam, BAD_CAST(paramName));
++ }
+ }
+ return xmlParam;
+ }
+diff --git a/ext/soap/tests/soap_qname_crash.phpt b/ext/soap/tests/soap_qname_crash.phpt
+new file mode 100644
+index 00000000000..52177577788
+--- /dev/null
++++ b/ext/soap/tests/soap_qname_crash.phpt
+@@ -0,0 +1,48 @@
++--TEST--
++Test SoapClient with excessively large QName prefix in SoapVar
++--EXTENSIONS--
++soap
++--SKIPIF--
++<?php
++if (PHP_INT_SIZE != 8) die("skip: 64-bit only");
++?>
++--INI--
++memory_limit=8G
++--FILE--
++<?php
++
++class TestSoapClient extends SoapClient {
++ public function __doRequest(
++ $request,
++ $location,
++ $action,
++ $version,
++ $one_way = false,
++ ): ?string {
++ die($request);
++ }
++}
++
++$prefix = str_repeat("A", 2 * 1024 * 1024 * 1024);
++$qname = "{$prefix}:tag";
++
++echo "Attempting to create SoapVar with very large QName\n";
++
++$var = new SoapVar("value", XSD_QNAME, null, null, $qname);
++
++echo "Attempting encoding\n";
++
++$options = [
++ 'location' => 'http://127.0.0.1/',
++ 'uri' => 'urn:dummy',
++ 'trace' => 1,
++ 'exceptions' => true,
++];
++$client = new TestSoapClient(null, $options);
++$client->__soapCall("DummyFunction", [$var]);
++?>
++--EXPECT--
++Attempting to create SoapVar with very large QName
++Attempting encoding
++<?xml version="1.0" encoding="UTF-8"?>
++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:dummy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:DummyFunction><param0 xsi:type="xsd:QName">value</param0></ns1:DummyFunction></SOAP-ENV:Body></SOAP-ENV:Envelope>
+--
+2.50.0
+
diff --git a/php-fpm.service b/php-fpm.service
index 687dfc0..0712a11 100644
--- a/php-fpm.service
+++ b/php-fpm.service
@@ -4,7 +4,7 @@
[Unit]
Description=The PHP FastCGI Process Manager
-After=syslog.target network.target
+After=network.target
[Service]
Type=notify
diff --git a/php-ghsa-4w77-75f9-2c8w.patch b/php-ghsa-4w77-75f9-2c8w.patch
new file mode 100644
index 0000000..61e859f
--- /dev/null
+++ b/php-ghsa-4w77-75f9-2c8w.patch
@@ -0,0 +1,133 @@
+From 462092a48aa0dbad24d9fa8a4a9d418faa14d309 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Sat, 9 Nov 2024 15:29:52 +0100
+Subject: [PATCH 6/8] Fix GHSA-4w77-75f9-2c8w
+
+(cherry picked from commit 7dd336ae838bbf2c62dc47e3c900d657d3534c02)
+---
+ sapi/cli/php_cli_server.c | 6 +---
+ sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt | 41 +++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+), 5 deletions(-)
+ create mode 100644 sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt
+
+diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
+index 295448f1211..5104318a634 100644
+--- a/sapi/cli/php_cli_server.c
++++ b/sapi/cli/php_cli_server.c
+@@ -1863,8 +1863,6 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client,
+
+ static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */
+ {
+- char *val;
+-
+ request_info->request_method = php_http_method_str(client->request.request_method);
+ request_info->proto_num = client->request.protocol_version;
+ request_info->request_uri = client->request.request_uri;
+@@ -1872,9 +1870,7 @@ static void php_cli_server_client_populate_request_info(const php_cli_server_cli
+ request_info->query_string = client->request.query_string;
+ request_info->content_length = client->request.content_len;
+ request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL;
+- if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1))) {
+- request_info->content_type = val;
+- }
++ request_info->content_type = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1);
+ } /* }}} */
+
+ static void destroy_request_info(sapi_request_info *request_info) /* {{{ */
+diff --git a/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt b/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt
+new file mode 100644
+index 00000000000..2c8aeff12d5
+--- /dev/null
++++ b/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt
+@@ -0,0 +1,41 @@
++--TEST--
++GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface)
++--INI--
++allow_url_fopen=1
++--SKIPIF--
++<?php
++include "skipif.inc";
++?>
++--FILE--
++<?php
++include "php_cli_server.inc";
++
++$serverCode = <<<'CODE'
++var_dump(file_get_contents('php://input'));
++CODE;
++
++php_cli_server_start($serverCode, null, []);
++
++$options = [
++ "http" => [
++ "method" => "POST",
++ "header" => "Content-Type: application/x-www-form-urlencoded",
++ "content" => "AAAAA",
++ ],
++];
++$context = stream_context_create($options);
++
++echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", context: $context);
++
++$options = [
++ "http" => [
++ "method" => "POST",
++ ],
++];
++$context = stream_context_create($options);
++
++echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", context: $context);
++?>
++--EXPECT--
++string(5) "AAAAA"
++string(0) ""
+--
+2.47.0
+
+From 22bdb43da0ecd6e72d63b63aa6c1f3a25d1bca3a Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Fri, 22 Nov 2024 08:58:10 +0100
+Subject: [PATCH 7/8] NEWS for 8.1.31 backports
+
+---
+ NEWS | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index bad0a719aae..0f82a65a44b 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,30 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.31
++
++- CLI:
++ . Fixed bug GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data
++ Processing in CLI SAPI Interface). (nielsdos)
++
++- LDAP:
++ . Fixed bug GHSA-g665-fm4p-vhff (OOB access in ldap_escape). (CVE-2024-8932)
++ (nielsdos)
++
++- PDO DBLIB:
++ . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing
++ OOB writes). (CVE-2024-11236) (nielsdos)
++
++- PDO Firebird:
++ . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the firebird quoter
++ causing OOB writes). (CVE-2024-11236) (nielsdos)
++
++- Streams:
++ . Fixed bug GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context
++ might allow for CRLF injection in URIs). (CVE-2024-11234) (Jakub Zelenka)
++ . Fixed bug GHSA-r977-prxv-hc43 (Single byte overread with
++ convert.quoted-printable-decode filter). (CVE-2024-11233) (nielsdos)
++
+ Backported from 8.1.30
+
+ - CGI:
+--
+2.47.0
+
diff --git a/php-keyring.gpg b/php-keyring.gpg
index 0774fa8..1433e1a 100644
--- a/php-keyring.gpg
+++ b/php-keyring.gpg
@@ -1,780 +1,770 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
-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
-5zO4pPQ1rIGTN4CBa7QcJH3fc3i9rYMYAtuVlpCUmDMEYHHgIBYJKwYBBAHaRw8B
-AQdAOm0RDYTmM6omlqoTx6Wy65agVJ4q8EPGczNnYOrHyo20HUpha3ViIFplbGVu
-a2EgPGJ1a2thQHBocC5uZXQ+iJMEExYIADsCGwMFCwkIBwIGFQoJCAsCBBYCAwEC
-HgECF4AWIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCYHHi+QIZAQAKCRAcB3ncXAqd
-5MZdAP0eAbdHgjHqKYol3QaXRhErAvvLHPSEXN5cAImF3zIICgD+NJZZMQDXd1OO
-KDt+YLiIqIq2ibRhOP5mZryPCGkq9QG0J0pha3ViIFplbGVua2EgPGpha3ViLm9w
-ZW5zc2xAZ21haWwuY29tPoiQBBMWCAA4FiEEwo2TdXVgPrSrtyWGHAd53FwKneQF
-AmBx4owCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQHAd53FwKneS0NwEA
-t0IRpoCN/JNwg1TIseybpmC65nSzYVyX10xe4Ji50dcBAI6TYA+47z6F4IVRg2c8
-Vtg1xktot7b/tKn6hgdv59sLtCdKYWt1YiBaZWxlbmthIDxqYWt1Yi56ZWxlbmth
-QGdtYWlsLmNvbT6IkAQTFggAOBYhBMKNk3V1YD60q7clhhwHedxcCp3kBQJgceAg
-AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEBwHedxcCp3k+3MBAKuK15Xy
-Hw+sdFATFuW9vN+lXqHnYid2jRzQUoh5wG/FAQDcBXQgXRfe72XRoxY4AE3E4onG
-MfzW3kbDKDVF7o4zDrg4BGBx4CASCisGAQQBl1UBBQEBB0Bm2FjWsSDUwL5nbAht
-l+rwnGLKbWiVYrwHQocgKFj6GwMBCAeIeAQYFggAIBYhBMKNk3V1YD60q7clhhwH
-edxcCp3kBQJgceAgAhsMAAoJEBwHedxcCp3k8ZwA/jLRHUBKIeRAxeGJhoqJRr2o
-TxrP887FuX9/ikSX21bcAQD90AB2fu6dpAkOFyZzX9UdE7QxtBhHVWRx3DRr4P/c
-DpgzBGYgDVwWCSsGAQQB2kcPAQEHQET/J56AhF3VoW7XvfydS3kGVTEN7zzOwA06
-KmRjb1w3tCZDYWx2aW4gQnVja2xleSAoUEhQKSA8Y2FsdmluYkBwaHAubmV0PoiT
-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
-=ilrq
+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
+nHPNsFNBKk0UUuDa9ktgklvkCQ==
+=Ob23
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/php.spec b/php.spec
index 5f8ba6e..af8d8f2 100644
--- a/php.spec
+++ b/php.spec
@@ -49,17 +49,10 @@
%global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock)
-%ifarch aarch64
-%global oraclever 19.24
-%global oraclemax 20
-%global oraclelib 19.1
-%global oracledir 19.24
-%else
-%global oraclever 23.5
+%global oraclever 23.8
%global oraclemax 24
%global oraclelib 23.1
%global oracledir 23
-%endif
# Build for LiteSpeed Web Server (LSAPI), you can disable using --without tests
%bcond_without lsws
@@ -77,7 +70,11 @@
%bcond_with zip
# Optional extensions; to disable: pass "--without xxx" etc to rpmbuild/mock.
%bcond_without imap
+%if 0%{?rhel} == 10
+%bcond_with firebird
+%else
%bcond_without firebird
+%endif
%bcond_without freetds
%bcond_without tidy
%bcond_without sqlite3
@@ -128,7 +125,7 @@
Summary: PHP scripting language for creating dynamic web sites
Name: %{?scl_prefix}php
Version: %{upver}%{?rcver:~%{rcver}}%{?gh_date:.%{gh_date}}
-Release: 9%{?dist}
+Release: 14%{?dist}
# All files licensed under PHP version 3.01, except
# Zend is licensed under Zend
# TSRM is licensed under BSD
@@ -168,12 +165,12 @@ Patch1: php-7.4.0-httpd.patch
Patch5: php-7.2.0-includedir.patch
Patch6: php-8.0.0-embed.patch
Patch7: php-7.4.0-libdb.patch
-# For libxml 2.12 from 8.1
-Patch8: php-8.0.30-libxml212.patch
# get rid of deprecated functions from 8.1
Patch9: php-8.0.6-deprecated.patch
-# RHEL backports
-Patch10: php-7.0.7-curl.patch
+# For recent ICU from 8.2
+Patch11: php-8.0.30-icu.patch
+# Fix strict prototypes from 8.1
+Patch12: php-8.0.30-proto.patch
# Functional changes
# Use system nikic/php-parser
@@ -214,11 +211,26 @@ Patch203: php-cve-2024-8925.patch
Patch204: php-cve-2024-8926.patch
Patch205: php-cve-2024-8927.patch
Patch206: php-cve-2024-9026.patch
+Patch207: php-cve-2024-11236.patch
+Patch208: php-cve-2024-11234.patch
+Patch209: php-cve-2024-8932.patch
+Patch210: php-cve-2024-11233.patch
+Patch211: php-ghsa-4w77-75f9-2c8w.patch
+Patch212: php-cve-2024-8929.patch
+Patch213: php-cve-2025-1217.patch
+Patch214: php-cve-2025-1734.patch
+Patch215: php-cve-2025-1861.patch
+Patch216: php-cve-2025-1736.patch
+Patch217: php-cve-2025-1219.patch
+Patch218: php-cve-2025-6491.patch
+Patch219: php-cve-2025-1220.patch
+Patch220: php-cve-2025-1735.patch
# Fixes for tests (300+)
# Factory is droped from system tzdata
Patch300: php-7.4.0-datetests.patch
Patch301: php-8.0.30-zlib-tests.patch
+Patch302: php-8.0.30-pcretests.patch
# WIP
@@ -649,14 +661,7 @@ License.
Summary: A module for PHP applications that use OCI8 databases
# All files licensed under PHP version 3.01
License: PHP
-%ifarch aarch64
-BuildRequires: oracle-instantclient%{oraclever}-devel
-# Should requires libclntsh.so.19.1()(aarch-64), but it's not provided by Oracle RPM.
-Requires: libclntsh.so.%{oraclelib}
-AutoReq: 0
-%else
BuildRequires: (oracle-instantclient-devel >= %{oraclever} with oracle-instantclient-devel < %{oraclemax})
-%endif
Requires: %{?scl_prefix}php-pdo%{?_isa} = %{version}-%{release}
Provides: %{?scl_prefix}php_database
Provides: %{?scl_prefix}php-pdo_oci
@@ -974,11 +979,9 @@ in pure PHP.
%patch -P5 -p1 -b .includedir
%patch -P6 -p1 -b .embed
%patch -P7 -p1 -b .libdb
-%patch -P8 -p1 -b .libxml212
%patch -P9 -p1 -b .deprecated
-%if 0%{?rhel} == 7
-%patch -P10 -p1 -b .curltls
-%endif
+%patch -P11 -p1 -b .icu74
+%patch -P12 -p1 -b .proto
%patch -P41 -p1 -b .syslib
%patch -P42 -p1 -b .systzdata
@@ -1008,10 +1011,25 @@ rm ext/openssl/tests/p12_with_extra_certs.p12
%patch -P204 -p1 -b .cve8926
%patch -P205 -p1 -b .cve8927
%patch -P206 -p1 -b .cve9026
+%patch -P207 -p1 -b .cve11236
+%patch -P208 -p1 -b .cve11234
+%patch -P209 -p1 -b .cve8932
+%patch -P210 -p1 -b .cve11233
+%patch -P211 -p1 -b .ghsa4w77
+%patch -P212 -p1 -b .cve8929
+%patch -P213 -p1 -b .cve1217
+%patch -P214 -p1 -b .cve1734
+%patch -P215 -p1 -b .cve1861
+%patch -P216 -p1 -b .cve1736
+%patch -P217 -p1 -b .cve1219
+%patch -P218 -p1 -b .cve6491
+%patch -P219 -p1 -b .cve1220
+%patch -P220 -p1 -b .cve1735
# Fixes for tests
%patch -P300 -p1 -b .datetests
%patch -P301 -p1 -b .zlibng
+%patch -P302 -p1 -b .pcretests
# WIP patch
@@ -1034,12 +1052,6 @@ mkdir \
# ----- Manage known as failed test -------
# affected by systzdata patch
rm ext/date/tests/timezone_location_get.phpt
-%if 0%{?fedora} < 36
-# need tzdata 2022b
-rm ext/date/tests/bug33414-1.phpt
-rm ext/date/tests/bug33415-2.phpt
-rm ext/date/tests/date_modify-1.phpt
-%endif
# too fast builder
rm ext/date/tests/bug73837.phpt
# fails sometime
@@ -1056,6 +1068,15 @@ rm ext/zlib/tests/004-mb.phpt
# failed when systemd is enabled
rm sapi/fpm/tests/gh8885-stderr-fd-reload-usr1.phpt
rm sapi/fpm/tests/gh8885-stderr-fd-reload-usr2.phpt
+# Known to fail
+%if 0%{?rhel} == 8
+rm ext/openssl/tests/openssl_error_string_basic.phpt
+rm ext/openssl/tests/openssl_open_basic.phpt
+%else
+rm ext/openssl/tests/openssl_error_string_basic_openssl3.phpt
+%endif
+rm ext/openssl/tests/openssl_private_decrypt_basic.phpt
+rm ext/openssl/tests/openssl_x509_parse_basic.phpt
# Safety check for API version change.
pver=$(sed -n '/#define PHP_VERSION /{s/.* "//;s/".*$//;p}' main/php_version.h)
@@ -1900,6 +1921,47 @@ EOF
%changelog
+* Thu Jul 3 2025 Remi Collet <remi@remirepo.net> - 8.0.30-14
+- Fix pgsql extension does not check for errors during escaping
+ CVE-2025-1735
+- Fix NULL Pointer Dereference in PHP SOAP Extension via Large XML Namespace Prefix
+ CVE-2025-6491
+- Fix Null byte termination in hostnames
+ CVE-2025-1220
+
+* Thu Mar 13 2025 Remi Collet <remi@remirepo.net> - 8.0.30-13
+- Fix libxml streams use wrong `content-type` header when requesting a redirected resource
+ CVE-2025-1219
+- Fix Stream HTTP wrapper header check might omit basic auth header
+ CVE-2025-1736
+- Fix Stream HTTP wrapper truncate redirect location to 1024 bytes
+ CVE-2025-1861
+- Fix Streams HTTP wrapper does not fail for headers without colon
+ CVE-2025-1734
+- Fix Header parser of `http` stream wrapper does not handle folded headers
+ CVE-2025-1217
+- use oracle client library version 23.7 on x86_64 and aarch64
+
+* Thu Feb 13 2025 Remi Collet <remi@remirepo.net> - 8.0.30-12
+- backport fix for ICU 74+
+- backport fix strict prototypes
+
+* Wed Nov 27 2024 Remi Collet <remi@remirepo.net> - 8.0.30-11
+- Fix Leak partial content of the heap through heap buffer over-read
+ CVE-2024-8929
+
+* Fri Nov 22 2024 Remi Collet <remi@remirepo.net> - 8.0.30-10
+- Fix Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface
+ GHSA-4w77-75f9-2c8w
+- Fix OOB access in ldap_escape
+ CVE-2024-8932
+- Fix Integer overflow in the dblib/firebird quoter causing OOB writes
+ CVE-2024-11236
+- Fix Configuring a proxy in a stream context might allow for CRLF injection in URIs
+ CVE-2024-11234
+- Fix Single byte overread with convert.quoted-printable-decode filter
+ CVE-2024-11233
+
* Thu Sep 26 2024 Remi Collet <remi@remirepo.net> - 8.0.30-9
- Fix Bypass of CVE-2012-1823, Argument Injection in PHP-CGI
CVE-2024-4577