summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--failed.txt13
-rw-r--r--macros.php4
-rw-r--r--php-7.1.33-intl.patch13
-rw-r--r--php-7.2.0-oci8conf.patch24
-rw-r--r--php-7.2.16-systzdata-v17.patch2
-rw-r--r--php-bug76450.patch208
-rw-r--r--php-bug77423.patch465
-rw-r--r--php-bug79971.patch167
-rw-r--r--php-bug80672.patch237
-rw-r--r--php-bug80710.patch371
-rw-r--r--php-bug81026.patch429
-rw-r--r--php-bug81122.patch88
-rw-r--r--php-bug81211.patch163
-rw-r--r--php-bug81719.patch62
-rw-r--r--php-bug81720.patch77
-rw-r--r--php-bug81726.patch180
-rw-r--r--php-bug81727.patch81
-rw-r--r--php-bug81738.patch129
-rw-r--r--php-bug81740.patch87
-rw-r--r--php-bug81744.patch190
-rw-r--r--php-bug81746.patch100
-rw-r--r--php-cve-2023-0662.patch148
-rw-r--r--php-cve-2023-3247.patch152
-rw-r--r--php-cve-2023-3823.patch91
-rw-r--r--php-cve-2023-3824.patch714
-rw-r--r--php-cve-2024-11233.patch158
-rw-r--r--php-cve-2024-11234.patch97
-rw-r--r--php-cve-2024-11236.patch150
-rw-r--r--php-cve-2024-2756.patch197
-rw-r--r--php-cve-2024-3096.patch85
-rw-r--r--php-cve-2024-5458.patch184
-rw-r--r--php-cve-2024-8925.patch236
-rw-r--r--php-cve-2024-8926.patch204
-rw-r--r--php-cve-2024-8927.patch98
-rw-r--r--php-cve-2024-8932.patch141
-rw-r--r--php-ghsa-4w77-75f9-2c8w.patch139
-rw-r--r--php-keyring.gpg1094
-rw-r--r--php72.spec366
39 files changed, 6909 insertions, 436 deletions
diff --git a/.gitignore b/.gitignore
index 485c916..ee5ffff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+clog
TODO
package-*.xml
*.tgz
diff --git a/failed.txt b/failed.txt
index dea1a00..e36292e 100644
--- a/failed.txt
+++ b/failed.txt
@@ -1,15 +1,13 @@
-===== 7.2.33 (2020-08-06)
+===== 7.2.34-25 (2024-11-26)
-$ grep -r 'Tests failed' /var/lib/mock/{fc,el}*/build.log
+$ grep -r 'Tests failed' /var/lib/mock/*/build.log
-/var/lib/mock/el6i/build.log:Tests failed : 0
-/var/lib/mock/el6x/build.log:Tests failed : 0
-/var/lib/mock/el7x/build.log:Tests failed : 0
-/var/lib/mock/el8x72/build.logTests failed : 17
+/var/lib/mock/el8a72/build.log:Tests failed : 22
+/var/lib/mock/el8x72/build.log:Tests failed : 22
el8x:
- 5 openssl failure under investigation
+ 3 buildroot issue with strict openssl policy (fixed in 7.4) and tzdata
1 proc_open give erratic test results :(
@@ -17,4 +15,3 @@ el8x:
3 known issue
4 bugs related to tzdata
5 need investigation
-
diff --git a/macros.php b/macros.php
index 0c750a7..e27985c 100644
--- a/macros.php
+++ b/macros.php
@@ -18,4 +18,8 @@
%__php %{_bindir}/php
%__ztsphp %{_bindir}/zts-php
+%__phpize %{_bindir}/phpize
+%__ztsphpize %{_bindir}/zts-phpize
+%__phpconfig %{_bindir}/php-config
+%__ztsphpconfig %{_bindir}/zts-php-config
diff --git a/php-7.1.33-intl.patch b/php-7.1.33-intl.patch
new file mode 100644
index 0000000..961fd89
--- /dev/null
+++ b/php-7.1.33-intl.patch
@@ -0,0 +1,13 @@
+diff -up ./ext/intl/collator/collator_sort.c.old ./ext/intl/collator/collator_sort.c
+diff -up ./ext/intl/config.m4.old ./ext/intl/config.m4
+--- ./ext/intl/config.m4.old 2021-09-07 07:38:38.698104692 +0200
++++ ./ext/intl/config.m4 2021-09-07 07:38:42.909098288 +0200
+@@ -9,7 +9,7 @@ if test "$PHP_INTL" != "no"; then
+ PHP_SETUP_ICU(INTL_SHARED_LIBADD)
+ PHP_SUBST(INTL_SHARED_LIBADD)
+ PHP_REQUIRE_CXX()
+- INTL_COMMON_FLAGS="$ICU_INCS -Wno-write-strings -D__STDC_LIMIT_MACROS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"
++ INTL_COMMON_FLAGS="$ICU_INCS -Wno-write-strings -DU_DEFINE_FALSE_AND_TRUE=1 -D__STDC_LIMIT_MACROS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"
+ if test "$icu_version" -ge "4002"; then
+ icu_spoof_src=" spoofchecker/spoofchecker_class.c \
+ spoofchecker/spoofchecker.c\
diff --git a/php-7.2.0-oci8conf.patch b/php-7.2.0-oci8conf.patch
index 0ad16a1..d026575 100644
--- a/php-7.2.0-oci8conf.patch
+++ b/php-7.2.0-oci8conf.patch
@@ -10,26 +10,4 @@ diff -up ./ext/ldap/php_ldap.h.remi-oci8 ./ext/ldap/php_ldap.h
extern zend_module_entry ldap_module_entry;
#define ldap_module_ptr &ldap_module_entry
-diff -up ./ext/oci8/config.m4.remi-oci8 ./ext/oci8/config.m4
---- ./ext/oci8/config.m4.remi-oci8 2017-06-20 15:45:39.000000000 +0200
-+++ ./ext/oci8/config.m4 2017-06-20 16:55:01.640203868 +0200
-@@ -372,6 +372,7 @@ if test "$PHP_OCI8" != "no"; then
-
- dnl Header directory for Instant Client SDK RPM install
- OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/lib/oracle/\(.*\)/client\('${PHP_OCI8_IC_LIBDIR_SUFFIX}'\)*/lib[/]*$!/usr/include/oracle/\1/client\2!'`
-+ OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/\(lib64\|lib\)/oracle/\(.*\)/\(client64\|client\)/lib[/]*$!/usr/include/oracle/\2/\3!'`
-
- dnl Header directory for Instant Client SDK zip file install
- OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include
-diff -up ./ext/pdo_oci/config.m4.remi-oci8 ./ext/pdo_oci/config.m4
---- ./ext/pdo_oci/config.m4.remi-oci8 2017-06-20 16:55:01.640203868 +0200
-+++ ./ext/pdo_oci/config.m4 2017-06-20 17:16:03.053538358 +0200
-@@ -93,7 +93,7 @@ if test "$PHP_PDO_OCI" != "no"; then
-
- AC_MSG_CHECKING([for oci.h])
- dnl Header directory for Instant Client SDK RPM install
-- OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\2/\3!'`
-+ OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/\(lib64\|lib\)/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\3/\4!'`
-
- dnl Header directory for manual installation
- OCISDKMANINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib[/]*$!\1/include!'`
+
diff --git a/php-7.2.16-systzdata-v17.patch b/php-7.2.16-systzdata-v17.patch
index 640bff2..e8ae8b2 100644
--- a/php-7.2.16-systzdata-v17.patch
+++ b/php-7.2.16-systzdata-v17.patch
@@ -410,7 +410,7 @@ diff -up php-7.2.16RC1/ext/date/lib/parse_tz.c.systzdata php-7.2.16RC1/ext/date/
+ size_t n;
+ char *data, *p;
+
-+ data = malloc(3 * sysdb->index_size + 7);
++ data = malloc(3 * sysdb->index_size + sizeof(FAKE_HEADER) - 1);
+
+ p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1);
+
diff --git a/php-bug76450.patch b/php-bug76450.patch
new file mode 100644
index 0000000..e1cffa6
--- /dev/null
+++ b/php-bug76450.patch
@@ -0,0 +1,208 @@
+From 18aadb2d10b70f40f67b3fa233f67f366d7d2572 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Wed, 5 May 2021 12:42:17 +0200
+Subject: [PATCH 3/7] Fix #76452: Crash while parsing blob data in
+ firebird_fetch_blob
+
+We need to prevent integer overflow when calling `erealloc()` with
+`len+1`.
+
+(cherry picked from commit 286162e9b03071c4308e7e92597bca4239f49d89)
+---
+ ext/pdo_firebird/firebird_statement.c | 5 +++++
+ ext/pdo_firebird/tests/bug_76452.data | Bin 0 -> 856 bytes
+ ext/pdo_firebird/tests/bug_76452.phpt | 31 ++++++++++++++++++++++++++
+ 3 files changed, 36 insertions(+)
+ create mode 100644 ext/pdo_firebird/tests/bug_76452.data
+ create mode 100644 ext/pdo_firebird/tests/bug_76452.phpt
+
+diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
+index 1c0f5b6071..c5e6b684c3 100644
+--- a/ext/pdo_firebird/firebird_statement.c
++++ b/ext/pdo_firebird/firebird_statement.c
+@@ -294,6 +294,11 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
+ unsigned short seg_len;
+ ISC_STATUS stat;
+
++ /* prevent overflow */
++ if (*len == ZEND_ULONG_MAX) {
++ result = 0;
++ goto fetch_blob_end;
++ }
+ *ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1);
+
+ for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
+
+From e968635df5b42b9358c08f3c57bf15f24e4de62e Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Fri, 30 Apr 2021 14:10:50 +0200
+Subject: [PATCH 4/7] Fix #76450: SIGSEGV in firebird_stmt_execute
+
+We need to verify that the `result_size` is not larger than our buffer,
+and also should make sure that the `len` which is passed to
+`isc_vax_integer()` has a permissible value; otherwise we bail out.
+
+(cherry picked from commit bcbf8aa0c96d8d9e81ec3428232485555fae0b37)
+---
+ ext/pdo_firebird/firebird_statement.c | 7 +++++++
+ ext/pdo_firebird/tests/bug_76450.data | Bin 0 -> 464 bytes
+ ext/pdo_firebird/tests/bug_76450.phpt | 29 ++++++++++++++++++++++++++
+ 3 files changed, 36 insertions(+)
+ create mode 100644 ext/pdo_firebird/tests/bug_76450.data
+ create mode 100644 ext/pdo_firebird/tests/bug_76450.phpt
+
+diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
+index c5e6b684c3..bdde6c7cf2 100644
+--- a/ext/pdo_firebird/firebird_statement.c
++++ b/ext/pdo_firebird/firebird_statement.c
+@@ -133,8 +133,14 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
+ }
+ if (result[0] == isc_info_sql_records) {
+ unsigned i = 3, result_size = isc_vax_integer(&result[1], 2);
++ if (result_size > sizeof(result)) {
++ goto error;
++ }
+ while (result[i] != isc_info_end && i < result_size) {
+ short len = (short) isc_vax_integer(&result[i + 1], 2);
++ if (len != 1 && len != 2 && len != 4) {
++ goto error;
++ }
+ if (result[i] != isc_info_req_select_count) {
+ affected_rows += isc_vax_integer(&result[i + 3], len);
+ }
+@@ -158,6 +164,7 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
+ return 1;
+ } while (0);
+
++error:
+ RECORD_ERROR(stmt);
+
+ return 0;
+
+From 6c114f1907051632e02cdc45de8b4b249d84e7df Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Fri, 30 Apr 2021 13:53:21 +0200
+Subject: [PATCH 5/7] Fix #76449: SIGSEGV in firebird_handle_doer
+
+We need to verify that the `result_size` is not larger than our buffer,
+and also should make sure that the `len` which is passed to
+`isc_vax_integer()` has a permissible value; otherwise we bail out.
+
+(cherry picked from commit 08da7c73726f7b86b67d6f0ff87c73c585a7834a)
+---
+ ext/pdo_firebird/firebird_driver.c | 9 +++++++++
+ ext/pdo_firebird/tests/bug_76449.data | Bin 0 -> 464 bytes
+ ext/pdo_firebird/tests/bug_76449.phpt | 23 +++++++++++++++++++++++
+ 3 files changed, 32 insertions(+)
+ create mode 100644 ext/pdo_firebird/tests/bug_76449.data
+ create mode 100644 ext/pdo_firebird/tests/bug_76449.phpt
+
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index 3060615e8d..c9f90fdef1 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -206,8 +206,17 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sq
+ if (result[0] == isc_info_sql_records) {
+ unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
+
++ if (result_size > sizeof(result)) {
++ ret = -1;
++ goto free_statement;
++ }
+ while (result[i] != isc_info_end && i < result_size) {
+ short len = (short)isc_vax_integer(&result[i+1],2);
++ /* bail out on bad len */
++ if (len != 1 && len != 2 && len != 4) {
++ ret = -1;
++ goto free_statement;
++ }
+ if (result[i] != isc_info_req_select_count) {
+ ret += isc_vax_integer(&result[i+3],len);
+ }
+
+From c9bdb0c993a079102ce854ef7859087170e7b9a1 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Thu, 29 Apr 2021 15:26:22 +0200
+Subject: [PATCH 6/7] Fix #76448: Stack buffer overflow in firebird_info_cb
+
+We ensure not to overflow the stack allocated buffer by using `strlcat`.
+
+(cherry picked from commit 67afa32541ebc4abbf633cb1e7e879b2fbb616ad)
+---
+ ext/pdo_firebird/firebird_driver.c | 8 +++++---
+ ext/pdo_firebird/tests/bug_76448.data | Bin 0 -> 749 bytes
+ ext/pdo_firebird/tests/bug_76448.phpt | 23 +++++++++++++++++++++++
+ 3 files changed, 28 insertions(+), 3 deletions(-)
+ create mode 100644 ext/pdo_firebird/tests/bug_76448.data
+ create mode 100644 ext/pdo_firebird/tests/bug_76448.phpt
+
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index c9f90fdef1..1e2e7746fa 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -509,14 +509,16 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
+ }
+ /* }}} */
+
++#define INFO_BUF_LEN 512
++
+ /* callback to used to report database server info */
+ static void firebird_info_cb(void *arg, char const *s) /* {{{ */
+ {
+ if (arg) {
+ if (*(char*)arg) { /* second call */
+- strcat(arg, " ");
++ strlcat(arg, " ", INFO_BUF_LEN);
+ }
+- strcat(arg, s);
++ strlcat(arg, s, INFO_BUF_LEN);
+ }
+ }
+ /* }}} */
+@@ -527,7 +529,7 @@ static int firebird_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
+ pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+
+ switch (attr) {
+- char tmp[512];
++ char tmp[INFO_BUF_LEN];
+
+ case PDO_ATTR_AUTOCOMMIT:
+ ZVAL_LONG(val,dbh->auto_commit);
+
+From 7598733c51af30611aa64e456c9a777069d2efb9 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 20 Jun 2021 22:20:38 -0700
+Subject: [PATCH 7/7] Update NEWS
+
+(cherry picked from commit c68a687566591e2268f35d124a90c7d556ce968b)
+---
+ NEWS | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index e331598176..f083e44dcc 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,19 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.3.29
++
++- Core:
++ . Fixed #81122: SSRF bypass in FILTER_VALIDATE_URL. (CVE-2021-21705) (cmb)
++
++- PDO_Firebird:
++ . Fixed #76448: Stack buffer overflow in firebird_info_cb. (CVE-2021-21704)
++ (cmb)
++ . Fixed #76449: SIGSEGV in firebird_handle_doer. (CVE-2021-21704) (cmb)
++ . Fixed #76450: SIGSEGV in firebird_stmt_execute. (CVE-2021-21704) (cmb)
++ . Fixed #76452: Crash while parsing blob data in firebird_fetch_blob.
++ (CVE-2021-21704) (cmb)
++
+ Backported from 7.3.28
+
+ - Imap:
+--
+2.31.1
+
diff --git a/php-bug77423.patch b/php-bug77423.patch
new file mode 100644
index 0000000..5d61bc1
--- /dev/null
+++ b/php-bug77423.patch
@@ -0,0 +1,465 @@
+From 2d3d72412a6734e19a38ed10f385227a6238e4a6 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Wed, 13 May 2020 09:36:52 +0200
+Subject: [PATCH] Fix #77423: parse_url() will deliver a wrong host to user
+
+To avoid that `parse_url()` returns an erroneous host, which would be
+valid for `FILTER_VALIDATE_URL`, we make sure that only userinfo which
+is valid according to RFC 3986 is treated as such.
+
+For consistency with the existing url parsing code, we use ctype
+functions, although that is not necessarily correct.
+---
+ ext/standard/tests/strings/url_t.phpt | 6 ++--
+ ext/standard/tests/url/bug77423.phpt | 30 +++++++++++++++++++
+ .../tests/url/parse_url_basic_001.phpt | 6 ++--
+ .../tests/url/parse_url_basic_003.phpt | 2 +-
+ .../tests/url/parse_url_basic_005.phpt | 2 +-
+ .../tests/url/parse_url_unterminated.phpt | 6 ++--
+ ext/standard/url.c | 21 +++++++++++++
+ 7 files changed, 59 insertions(+), 14 deletions(-)
+ create mode 100644 ext/standard/tests/url/bug77423.phpt
+
+diff --git a/ext/standard/tests/strings/url_t.phpt b/ext/standard/tests/strings/url_t.phpt
+index 79ff3bc4a8e3..f564f59f0632 100644
+--- a/ext/standard/tests/strings/url_t.phpt
++++ b/ext/standard/tests/strings/url_t.phpt
+@@ -575,15 +575,13 @@ $sample_urls = array (
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(11) "www.php.net"
++ string(26) "secret@hideout@www.php.net"
+ ["port"]=>
+ int(80)
+- ["user"]=>
+- string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/tests/url/bug77423.phpt b/ext/standard/tests/url/bug77423.phpt
+new file mode 100644
+index 000000000000..be03fe95e24e
+--- /dev/null
++++ b/ext/standard/tests/url/bug77423.phpt
+@@ -0,0 +1,30 @@
++--TEST--
++Bug #77423 (parse_url() will deliver a wrong host to user)
++--FILE--
++<?php
++$urls = array(
++ "http://php.net\@aliyun.com/aaa.do",
++ "https://example.com\uFF03@bing.com",
++);
++foreach ($urls as $url) {
++ var_dump(filter_var($url, FILTER_VALIDATE_URL));
++ var_dump(parse_url($url));
++}
++?>
++--EXPECT--
++bool(false)
++array(3) {
++ ["scheme"]=>
++ string(4) "http"
++ ["host"]=>
++ string(19) "php.net\@aliyun.com"
++ ["path"]=>
++ string(7) "/aaa.do"
++}
++bool(false)
++array(2) {
++ ["scheme"]=>
++ string(5) "https"
++ ["host"]=>
++ string(26) "example.com\uFF03@bing.com"
++}
+diff --git a/ext/standard/tests/url/parse_url_basic_001.phpt b/ext/standard/tests/url/parse_url_basic_001.phpt
+index 4606849c5781..51010991326c 100644
+--- a/ext/standard/tests/url/parse_url_basic_001.phpt
++++ b/ext/standard/tests/url/parse_url_basic_001.phpt
+@@ -506,15 +506,13 @@ echo "Done";
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(11) "www.php.net"
++ string(26) "secret@hideout@www.php.net"
+ ["port"]=>
+ int(80)
+- ["user"]=>
+- string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/tests/url/parse_url_basic_003.phpt b/ext/standard/tests/url/parse_url_basic_003.phpt
+index 3d5a4a344afd..7968fd3f09fd 100644
+--- a/ext/standard/tests/url/parse_url_basic_003.phpt
++++ b/ext/standard/tests/url/parse_url_basic_003.phpt
+@@ -68,7 +68,7 @@ echo "Done";
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(26) "secret@hideout@www.php.net"
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> nntp://news.php.net : string(12) "news.php.net"
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : string(11) "ftp.gnu.org"
+diff --git a/ext/standard/tests/url/parse_url_basic_005.phpt b/ext/standard/tests/url/parse_url_basic_005.phpt
+index aefb33964bc4..ba778bf9035d 100644
+--- a/ext/standard/tests/url/parse_url_basic_005.phpt
++++ b/ext/standard/tests/url/parse_url_basic_005.phpt
+@@ -68,7 +68,7 @@ echo "Done";
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(0) ""
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(14) "secret@hideout"
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> nntp://news.php.net : NULL
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : NULL
+diff --git a/ext/standard/tests/url/parse_url_unterminated.phpt b/ext/standard/tests/url/parse_url_unterminated.phpt
+index 912b6a5641e8..875d93a10948 100644
+--- a/ext/standard/tests/url/parse_url_unterminated.phpt
++++ b/ext/standard/tests/url/parse_url_unterminated.phpt
+@@ -508,15 +508,13 @@ echo "Done";
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(11) "www.php.net"
++ string(26) "secret@hideout@www.php.net"
+ ["port"]=>
+ int(80)
+- ["user"]=>
+- string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 1dd073e2bb42..8d155bb9846c 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -92,6 +92,22 @@ PHPAPI php_url *php_url_parse(char const *str)
+ return php_url_parse_ex(str, strlen(str));
+ }
+
++static int is_userinfo_valid(const char *str, size_t len)
++{
++ char *valid = "-._~!$&'()*+,;=:";
++ char *p = str;
++ while (p - str < len) {
++ if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
++ p++;
++ } else if (*p == '%' && p - str <= len - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
++ p += 3;
++ } else {
++ return 0;
++ }
++ }
++ return 1;
++}
++
+ /* {{{ php_url_parse
+ */
+ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
+@@ -235,13 +251,18 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
+ ret->pass = estrndup(pp, (p-pp));
+ php_replace_controlchars_ex(ret->pass, (p-pp));
+ } else {
++ if (!is_userinfo_valid(s, p-s)) {
++ goto check_port;
++ }
+ ret->user = estrndup(s, (p-s));
+ php_replace_controlchars_ex(ret->user, (p-s));
++
+ }
+
+ s = p + 1;
+ }
+
++check_port:
+ /* check for port */
+ if (s < ue && *s == '[' && *(e-1) == ']') {
+ /* Short circuit portscan,
+From 22756113c67b9fc7dce542c80722f24351e85a45 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 7 Jan 2021 11:42:58 +0100
+Subject: [PATCH] NEWS
+
+---
+ NEWS | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 1f037cb301..7f2d588c4d 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,5 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
++
++Backported from 7.3.26
++
++- Standard:
++ . Fixed bug #77423 (FILTER_VALIDATE_URL accepts URLs with invalid userinfo).
++ (CVE-2020-7071) (cmb)
++
+ 01 Oct 2020, PHP 7.2.34
+
+ - Core:
+From 356f7008f36da60ec9794d48c55d117f1dd31903 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Tue, 19 Jan 2021 11:23:25 +0100
+Subject: [PATCH] Alternative fix for bug 77423
+
+That bug report originally was about `parse_url()` misbehaving, but the
+security aspect was actually only regarding `FILTER_VALIDATE_URL`.
+Since the changes to `parse_url_ex()` apparently affect userland code
+which is relying on the sloppy URL parsing[1], this alternative
+restores the old parsing behavior, but ensures that the userinfo is
+checked for correctness for `FILTER_VALIDATE_URL`.
+
+[1] <https://github.com/php/php-src/commit/5174de7cd33c3d4fa591c9c93859ff9989b07e8c#commitcomment-45967652>
+
+(cherry picked from commit 4a89e726bd4d0571991dc22a9a1ad4509e8fe347)
+(cherry picked from commit 9c673083cd46ee2a954a62156acbe4b6e657c048)
+---
+ ext/filter/logical_filters.c | 25 +++++++++++++++++++
+ .../tests/url => filter/tests}/bug77423.phpt | 15 -----------
+ ext/standard/tests/strings/url_t.phpt | 6 +++--
+ .../tests/url/parse_url_basic_001.phpt | 6 +++--
+ .../tests/url/parse_url_basic_003.phpt | 2 +-
+ .../tests/url/parse_url_basic_005.phpt | 2 +-
+ .../tests/url/parse_url_unterminated.phpt | 6 +++--
+ ext/standard/url.c | 21 ----------------
+ 8 files changed, 39 insertions(+), 44 deletions(-)
+ rename ext/{standard/tests/url => filter/tests}/bug77423.phpt (53%)
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index b2d0264b76..ad0956a505 100644
+--- a/ext/filter/logical_filters.c
++++ b/ext/filter/logical_filters.c
+@@ -514,6 +514,24 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+ }
+ /* }}} */
+
++static int is_userinfo_valid(char *str)
++{
++ const char *valid = "-._~!$&'()*+,;=:";
++ const char *p = str;
++ size_t len = strlen(str);
++
++ while (p - str < len) {
++ if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
++ p++;
++ } else if (*p == '%' && p - str <= len - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
++ p += 3;
++ } else {
++ return 0;
++ }
++ }
++ return 1;
++}
++
+ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+ {
+ php_url *url;
+@@ -568,6 +586,13 @@ bad_url:
+ php_url_free(url);
+ RETURN_VALIDATION_FAILED
+ }
++
++ if (url->user != NULL && !is_userinfo_valid(url->user)) {
++ php_url_free(url);
++ RETURN_VALIDATION_FAILED
++
++ }
++
+ php_url_free(url);
+ }
+ /* }}} */
+diff --git a/ext/standard/tests/url/bug77423.phpt b/ext/filter/tests/bug77423.phpt
+similarity index 53%
+rename from ext/standard/tests/url/bug77423.phpt
+rename to ext/filter/tests/bug77423.phpt
+index be03fe95e2..761c7c359a 100644
+--- a/ext/standard/tests/url/bug77423.phpt
++++ b/ext/filter/tests/bug77423.phpt
+@@ -8,23 +8,8 @@ $urls = array(
+ );
+ foreach ($urls as $url) {
+ var_dump(filter_var($url, FILTER_VALIDATE_URL));
+- var_dump(parse_url($url));
+ }
+ ?>
+ --EXPECT--
+ bool(false)
+-array(3) {
+- ["scheme"]=>
+- string(4) "http"
+- ["host"]=>
+- string(19) "php.net\@aliyun.com"
+- ["path"]=>
+- string(7) "/aaa.do"
+-}
+ bool(false)
+-array(2) {
+- ["scheme"]=>
+- string(5) "https"
+- ["host"]=>
+- string(26) "example.com\uFF03@bing.com"
+-}
+diff --git a/ext/standard/tests/strings/url_t.phpt b/ext/standard/tests/strings/url_t.phpt
+index f564f59f06..79ff3bc4a8 100644
+--- a/ext/standard/tests/strings/url_t.phpt
++++ b/ext/standard/tests/strings/url_t.phpt
+@@ -575,13 +575,15 @@ $sample_urls = array (
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(26) "secret@hideout@www.php.net"
++ string(11) "www.php.net"
+ ["port"]=>
+ int(80)
++ ["user"]=>
++ string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/tests/url/parse_url_basic_001.phpt b/ext/standard/tests/url/parse_url_basic_001.phpt
+index 5101099132..4606849c57 100644
+--- a/ext/standard/tests/url/parse_url_basic_001.phpt
++++ b/ext/standard/tests/url/parse_url_basic_001.phpt
+@@ -506,13 +506,15 @@ echo "Done";
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(26) "secret@hideout@www.php.net"
++ string(11) "www.php.net"
+ ["port"]=>
+ int(80)
++ ["user"]=>
++ string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/tests/url/parse_url_basic_003.phpt b/ext/standard/tests/url/parse_url_basic_003.phpt
+index 7968fd3f09..3d5a4a344a 100644
+--- a/ext/standard/tests/url/parse_url_basic_003.phpt
++++ b/ext/standard/tests/url/parse_url_basic_003.phpt
+@@ -68,7 +68,7 @@ echo "Done";
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(26) "secret@hideout@www.php.net"
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> nntp://news.php.net : string(12) "news.php.net"
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : string(11) "ftp.gnu.org"
+diff --git a/ext/standard/tests/url/parse_url_basic_005.phpt b/ext/standard/tests/url/parse_url_basic_005.phpt
+index ba778bf903..aefb33964b 100644
+--- a/ext/standard/tests/url/parse_url_basic_005.phpt
++++ b/ext/standard/tests/url/parse_url_basic_005.phpt
+@@ -68,7 +68,7 @@ echo "Done";
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(0) ""
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(14) "secret@hideout"
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> nntp://news.php.net : NULL
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : NULL
+diff --git a/ext/standard/tests/url/parse_url_unterminated.phpt b/ext/standard/tests/url/parse_url_unterminated.phpt
+index 875d93a109..912b6a5641 100644
+--- a/ext/standard/tests/url/parse_url_unterminated.phpt
++++ b/ext/standard/tests/url/parse_url_unterminated.phpt
+@@ -508,13 +508,15 @@ echo "Done";
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(26) "secret@hideout@www.php.net"
++ string(11) "www.php.net"
+ ["port"]=>
+ int(80)
++ ["user"]=>
++ string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 8d155bb984..1dd073e2bb 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -92,22 +92,6 @@ PHPAPI php_url *php_url_parse(char const *str)
+ return php_url_parse_ex(str, strlen(str));
+ }
+
+-static int is_userinfo_valid(const char *str, size_t len)
+-{
+- char *valid = "-._~!$&'()*+,;=:";
+- char *p = str;
+- while (p - str < len) {
+- if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
+- p++;
+- } else if (*p == '%' && p - str <= len - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
+- p += 3;
+- } else {
+- return 0;
+- }
+- }
+- return 1;
+-}
+-
+ /* {{{ php_url_parse
+ */
+ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
+@@ -251,18 +235,13 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
+ ret->pass = estrndup(pp, (p-pp));
+ php_replace_controlchars_ex(ret->pass, (p-pp));
+ } else {
+- if (!is_userinfo_valid(s, p-s)) {
+- goto check_port;
+- }
+ ret->user = estrndup(s, (p-s));
+ php_replace_controlchars_ex(ret->user, (p-s));
+-
+ }
+
+ s = p + 1;
+ }
+
+-check_port:
+ /* check for port */
+ if (s < ue && *s == '[' && *(e-1) == ']') {
+ /* Short circuit portscan,
+--
+2.29.2
+
diff --git a/php-bug79971.patch b/php-bug79971.patch
new file mode 100644
index 0000000..9f31d28
--- /dev/null
+++ b/php-bug79971.patch
@@ -0,0 +1,167 @@
+From 2936b97fe42fb5713595a1559b91d568ccddb04a Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Tue, 1 Sep 2020 10:04:28 +0200
+Subject: [PATCH 1/2] Fix #79971: special character is breaking the path in xml
+ function
+
+The libxml based XML functions accepting a filename actually accept
+URIs with possibly percent-encoded characters. Percent-encoded NUL
+bytes lead to truncation, like non-encoded NUL bytes would. We catch
+those, and let the functions fail with a respective warning.
+
+(cherry picked from commit f15f8fc573eb38c3c73e23e0930063a6f6409ed4)
+---
+ ext/dom/domimplementation.c | 5 +++++
+ ext/dom/tests/bug79971_2.phpt | 20 ++++++++++++++++++++
+ ext/libxml/libxml.c | 9 +++++++++
+ ext/simplexml/tests/bug79971_1.phpt | 27 +++++++++++++++++++++++++++
+ ext/simplexml/tests/bug79971_1.xml | 2 ++
+ 5 files changed, 63 insertions(+)
+ create mode 100644 ext/dom/tests/bug79971_2.phpt
+ create mode 100644 ext/simplexml/tests/bug79971_1.phpt
+ create mode 100644 ext/simplexml/tests/bug79971_1.xml
+
+diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c
+index 28e35eb785..f4d1358b8e 100644
+--- a/ext/dom/domimplementation.c
++++ b/ext/dom/domimplementation.c
+@@ -114,6 +114,11 @@ PHP_METHOD(domimplementation, createDocumentType)
+ pch2 = (xmlChar *) systemid;
+ }
+
++ if (strstr(name, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ RETURN_FALSE;
++ }
++
+ uri = xmlParseURI(name);
+ if (uri != NULL && uri->opaque != NULL) {
+ localname = xmlStrdup((xmlChar *) uri->opaque);
+diff --git a/ext/dom/tests/bug79971_2.phpt b/ext/dom/tests/bug79971_2.phpt
+new file mode 100644
+index 0000000000..c4e6b1e4e0
+--- /dev/null
++++ b/ext/dom/tests/bug79971_2.phpt
+@@ -0,0 +1,20 @@
++--TEST--
++Bug #79971 (special character is breaking the path in xml function)
++--SKIPIF--
++<?php
++if (!extension_loaded('dom')) die('skip dom extension not available');
++?>
++--FILE--
++<?php
++$imp = new DOMImplementation;
++if (PHP_OS_FAMILY === 'Windows') {
++ $path = '/' . str_replace('\\', '/', __DIR__);
++} else {
++ $path = __DIR__;
++}
++$uri = "file://$path/bug79971_2.xml";
++var_dump($imp->createDocumentType("$uri%00foo"));
++?>
++--EXPECTF--
++Warning: DOMImplementation::createDocumentType(): URI must not contain percent-encoded NUL bytes in %s on line %d
++bool(false)
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index c871cb89bd..da553d64ee 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -308,6 +308,10 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char
+ int isescaped=0;
+ xmlURI *uri;
+
++ if (strstr(filename, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ return NULL;
++ }
+
+ uri = xmlParseURI(filename);
+ if (uri && (uri->scheme == NULL ||
+@@ -438,6 +442,11 @@ php_libxml_output_buffer_create_filename(const char *URI,
+ if (URI == NULL)
+ return(NULL);
+
++ if (strstr(URI, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ return NULL;
++ }
++
+ puri = xmlParseURI(URI);
+ if (puri != NULL) {
+ if (puri->scheme != NULL)
+diff --git a/ext/simplexml/tests/bug79971_1.phpt b/ext/simplexml/tests/bug79971_1.phpt
+new file mode 100644
+index 0000000000..197776d82d
+--- /dev/null
++++ b/ext/simplexml/tests/bug79971_1.phpt
+@@ -0,0 +1,27 @@
++--TEST--
++Bug #79971 (special character is breaking the path in xml function)
++--SKIPIF--
++<?php
++if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
++?>
++--FILE--
++<?php
++if (PHP_OS_FAMILY === 'Windows') {
++ $path = '/' . str_replace('\\', '/', __DIR__);
++} else {
++ $path = __DIR__;
++}
++$uri = "file://$path/bug79971_1.xml";
++var_dump(simplexml_load_file("$uri%00foo"));
++
++$sxe = simplexml_load_file($uri);
++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
++bool(false)
++
++Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d
++bool(false)
+diff --git a/ext/simplexml/tests/bug79971_1.xml b/ext/simplexml/tests/bug79971_1.xml
+new file mode 100644
+index 0000000000..912bb76d9d
+--- /dev/null
++++ b/ext/simplexml/tests/bug79971_1.xml
+@@ -0,0 +1,2 @@
++<?xml version="1.0"?>
++<root></root>
+--
+2.31.1
+
+From c032381da0bfb6457aa9cfa7a430790f6eab8178 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Mon, 15 Nov 2021 09:05:33 +0100
+Subject: [PATCH 2/2] NEWS
+
+---
+ NEWS | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/NEWS b/NEWS
+index e5ecd3865a..2177c64aef 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,7 +1,13 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+-Backported from 7.4.25
++Backported from 7.3.33
++
++- XML:
++ . Fix #79971: special character is breaking the path in xml function.
++ (CVE-2021-21707) (cmb)
++
++Backported from 7.3.32
+
+ - FPM:
+ . Fixed bug #81026 (PHP-FPM oob R/W in root process leading to privilege
+--
+2.31.1
+
diff --git a/php-bug80672.patch b/php-bug80672.patch
new file mode 100644
index 0000000..5f63aab
--- /dev/null
+++ b/php-bug80672.patch
@@ -0,0 +1,237 @@
+From f1e2cfa008d1596251968d13eb9a8539dba6879f Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 31 Jan 2021 21:15:23 -0800
+Subject: [PATCH 1/2] Fix bug #80672 - Null Dereference in SoapClient
+
+(cherry picked from commit 3c939e3f69955d087e0bb671868f7267dfb2a502)
+---
+ NEWS | 5 +++++
+ ext/soap/php_sdl.c | 26 ++++++++++++++------------
+ ext/soap/php_xml.c | 4 ++--
+ ext/soap/tests/bug80672.phpt | 15 +++++++++++++++
+ ext/soap/tests/bug80672.xml | 6 ++++++
+ 5 files changed, 42 insertions(+), 14 deletions(-)
+ create mode 100644 ext/soap/tests/bug80672.phpt
+ create mode 100644 ext/soap/tests/bug80672.xml
+
+diff --git a/NEWS b/NEWS
+index 7f2d588c4d..884285f05f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,11 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.3.27
++
++- SOAP:
++ . Fixed bug #80672 (Null Dereference in SoapClient). (CVE-2021-21702) (cmb, Stas)
++
+ Backported from 7.3.26
+
+ - Standard:
+diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
+index d16056e4a3..b8d40f0cfe 100644
+--- a/ext/soap/php_sdl.c
++++ b/ext/soap/php_sdl.c
+@@ -314,6 +314,8 @@ void sdl_restore_uri_credentials(sdlCtx *ctx)
+ ctx->context = NULL;
+ }
+
++#define SAFE_STR(a) ((a)?a:"")
++
+ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ {
+ sdlPtr tmpsdl = ctx->sdl;
+@@ -375,7 +377,7 @@ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
+ load_schema(ctx, trav2);
+ } else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+ trav2 = trav2->next;
+ }
+@@ -436,7 +438,7 @@ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
+ }
+ } else if (!node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -546,7 +548,7 @@ static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xml
+ }
+ smart_str_free(&key);
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -648,7 +650,7 @@ static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap
+ }
+ smart_str_free(&key);
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -680,14 +682,14 @@ static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
+ sdlParamPtr param;
+
+ if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", SAFE_STR(trav->name));
+ }
+ if (node_is_equal(trav,"documentation")) {
+ trav = trav->next;
+ continue;
+ }
+ if (!node_is_equal(trav,"part")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ part = trav;
+ param = emalloc(sizeof(sdlParam));
+@@ -696,7 +698,7 @@ static HashTable* wsdl_message(sdlCtx *ctx, xmlChar* message_name)
+
+ name = get_attribute(part->properties, "name");
+ if (name == NULL) {
+- soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", message->name);
++ soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", SAFE_STR(message->name));
+ }
+
+ param->paramName = estrdup((char*)name->children->content);
+@@ -765,7 +767,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
+ continue;
+ }
+ if (!node_is_equal(trav,"port")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+
+ port = trav;
+@@ -804,7 +806,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
+ }
+ }
+ if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+ trav2 = trav2->next;
+ }
+@@ -906,7 +908,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
+ continue;
+ }
+ if (!node_is_equal(trav2,"operation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+
+ operation = trav2;
+@@ -925,7 +927,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
+ !node_is_equal(trav3,"output") &&
+ !node_is_equal(trav3,"fault") &&
+ !node_is_equal(trav3,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav3->name));
+ }
+ trav3 = trav3->next;
+ }
+@@ -1103,7 +1105,7 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
+ }
+ }
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
+index bf76e237a9..1ac684eb81 100644
+--- a/ext/soap/php_xml.c
++++ b/ext/soap/php_xml.c
+@@ -204,7 +204,7 @@ xmlNsPtr node_find_ns(xmlNodePtr node)
+
+ int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
+ {
+- if (name == NULL || strcmp((char*)node->name, name) == 0) {
++ if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
+ if (ns) {
+ xmlNsPtr nsPtr = attr_find_ns(node);
+ if (nsPtr) {
+@@ -220,7 +220,7 @@ int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
+
+ int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
+ {
+- if (name == NULL || strcmp((char*)node->name, name) == 0) {
++ if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
+ if (ns) {
+ xmlNsPtr nsPtr = node_find_ns(node);
+ if (nsPtr) {
+diff --git a/ext/soap/tests/bug80672.phpt b/ext/soap/tests/bug80672.phpt
+new file mode 100644
+index 0000000000..71e2b1d841
+--- /dev/null
++++ b/ext/soap/tests/bug80672.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #80672 Null Dereference in SoapClient
++--SKIPIF--
++<?php require_once('skipif.inc'); ?>
++--FILE--
++<?php
++try {
++ $client = new SoapClient(__DIR__ . "/bug80672.xml");
++ $query = $soap->query(array('sXML' => 'something'));
++} catch(SoapFault $e) {
++ print $e->getMessage();
++}
++?>
++--EXPECTF--
++SOAP-ERROR: Parsing WSDL: Unexpected WSDL element <>
+\ No newline at end of file
+diff --git a/ext/soap/tests/bug80672.xml b/ext/soap/tests/bug80672.xml
+new file mode 100644
+index 0000000000..0fa185bf1e
+--- /dev/null
++++ b/ext/soap/tests/bug80672.xml
+@@ -0,0 +1,6 @@
++<?xml version="1.0" encoding="ISO-8859-1"?>
++<soap:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
++ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
++ xmlns:soap="http://schemas.xmlsoap.org/wsdl/">
++<![CDATA[test]]>
++</soap:definitions>
+--
+2.29.2
+
+From 02352d5acc1896756dcb4645f54689ffdcc4ca52 Mon Sep 17 00:00:00 2001
+From: Nikita Popov <nikita.ppv@gmail.com>
+Date: Mon, 1 Feb 2021 09:46:17 +0100
+Subject: [PATCH 2/2] Fix build
+
+(cherry picked from commit e5d767d27f94895e09f0321562fd3774d4656164)
+---
+ ext/soap/php_sdl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
+index b8d40f0cfe..522db1c979 100644
+--- a/ext/soap/php_sdl.c
++++ b/ext/soap/php_sdl.c
+@@ -314,7 +314,7 @@ void sdl_restore_uri_credentials(sdlCtx *ctx)
+ ctx->context = NULL;
+ }
+
+-#define SAFE_STR(a) ((a)?a:"")
++#define SAFE_STR(a) ((a)?((const char *)a):"")
+
+ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ {
+--
+2.29.2
+
diff --git a/php-bug80710.patch b/php-bug80710.patch
new file mode 100644
index 0000000..2dd68f0
--- /dev/null
+++ b/php-bug80710.patch
@@ -0,0 +1,371 @@
+From 9017896cccefe000938f80b49361b1c183849922 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Fri, 5 Feb 2021 22:51:41 +0100
+Subject: [PATCH 1/2] Fix #80710: imap_mail_compose() header injection
+
+Like `mail()` and `mb_send_mail()`, `imap_mail_compose()` must prevent
+header injection. For maximum backward compatibility, we still allow
+header folding for general headers, and still accept trailing line
+breaks for address lists.
+
+(cherry picked from commit 37962c61d29794645ec45d45d78123382d82c2e5)
+---
+ ext/imap/php_imap.c | 56 ++++++++++++++++++++++++++++++++++
+ ext/imap/tests/bug80710_1.phpt | 37 ++++++++++++++++++++++
+ ext/imap/tests/bug80710_2.phpt | 37 ++++++++++++++++++++++
+ 3 files changed, 130 insertions(+)
+ create mode 100644 ext/imap/tests/bug80710_1.phpt
+ create mode 100644 ext/imap/tests/bug80710_2.phpt
+
+diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
+index 37eb5e1296..9cac2264fb 100644
+--- a/ext/imap/php_imap.c
++++ b/ext/imap/php_imap.c
+@@ -3528,6 +3528,23 @@ PHP_FUNCTION(imap_fetch_overview)
+ }
+ /* }}} */
+
++static zend_bool header_injection(zend_string *str, zend_bool adrlist)
++{
++ char *p = ZSTR_VAL(str);
++
++ while ((p = strpbrk(p, "\r\n")) != NULL) {
++ if (!(p[0] == '\r' && p[1] == '\n')
++ /* adrlists do not support folding, but swallow trailing line breaks */
++ && !((adrlist && p[1] == '\0')
++ /* other headers support folding */
++ || !adrlist && (p[1] == ' ' || p[1] == '\t'))) {
++ return 1;
++ }
++ p++;
++ }
++ return 0;
++}
++
+ /* {{{ proto string imap_mail_compose(array envelope, array body)
+ Create a MIME message based on given envelope and body sections */
+ PHP_FUNCTION(imap_mail_compose)
+@@ -3548,6 +3565,13 @@ PHP_FUNCTION(imap_mail_compose)
+ return;
+ }
+
++#define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
++ if (header_injection(zstr, adrlist)) { \
++ php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
++ RETVAL_FALSE; \
++ goto done; \
++ }
++
+ #define PHP_RFC822_PARSE_ADRLIST(target, value) \
+ str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
+ rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
+@@ -3556,46 +3580,57 @@ PHP_FUNCTION(imap_mail_compose)
+ env = mail_newenvelope();
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
+ env->remail = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
+ PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "date", sizeof("date") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
+ env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "from", sizeof("from") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
+ PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
+ PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
+ env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
+ env->subject = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "to", sizeof("to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
+ PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
+ PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
+ PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
+ env->message_id=cpystr(Z_STRVAL_P(pvalue));
+ }
+
+@@ -3605,6 +3640,7 @@ PHP_FUNCTION(imap_mail_compose)
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
+ custom_headers_param = mail_newbody_parameter();
+ convert_to_string_ex(env_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
+ custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
+ custom_headers_param->attribute = NULL;
+ memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
+@@ -3637,6 +3673,7 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
+ tmp_param = mail_newbody_parameter();
+ tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
+ tmp_param->attribute = cpystr("CHARSET");
+@@ -3647,9 +3684,11 @@ PHP_FUNCTION(imap_mail_compose)
+ if(Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body disposition key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3660,18 +3699,22 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
+ bod->subtype = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
+ bod->id = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
+ bod->description = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
+ }
+@@ -3679,9 +3722,11 @@ PHP_FUNCTION(imap_mail_compose)
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3710,6 +3755,7 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
+ bod->md5 = cpystr(Z_STRVAL_P(pvalue));
+ }
+ } else if (Z_TYPE_P(data) == IS_ARRAY) {
+@@ -3740,6 +3786,7 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
+ tmp_param = mail_newbody_parameter();
+ tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
+@@ -3751,9 +3798,11 @@ PHP_FUNCTION(imap_mail_compose)
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
+ disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3764,18 +3813,22 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
+ bod->subtype = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
+ bod->id = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
+ bod->description = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
+ }
+@@ -3783,9 +3836,11 @@ PHP_FUNCTION(imap_mail_compose)
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body disposition key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3814,6 +3869,7 @@ PHP_FUNCTION(imap_mail_compose)
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
+ bod->md5 = cpystr(Z_STRVAL_P(pvalue));
+ }
+ }
+diff --git a/ext/imap/tests/bug80710_1.phpt b/ext/imap/tests/bug80710_1.phpt
+new file mode 100644
+index 0000000000..5cdee03401
+--- /dev/null
++++ b/ext/imap/tests/bug80710_1.phpt
+@@ -0,0 +1,37 @@
++--TEST--
++Bug #80710 (imap_mail_compose() header injection) - MIME Splitting Attack
++--SKIPIF--
++<?php
++if (!extension_loaded("imap")) die("skip imap extension not available");
++?>
++--FILE--
++<?php
++$envelope["from"]= "joe@example.com\n From : X-INJECTED";
++$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
++$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
++$envelope["x-remail"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
++
++$part1["type"] = TYPEMULTIPART;
++$part1["subtype"] = "mixed";
++
++$part2["type"] = TYPEAPPLICATION;
++$part2["encoding"] = ENCBINARY;
++$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
++$part2["description"] = "some file\nContent-Type: X-INJECTED";
++$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
++
++$part3["type"] = TYPETEXT;
++$part3["subtype"] = "plain";
++$part3["description"] = "description3";
++$part3["contents.data"] = "contents.data3\n\n\n\t";
++
++$body[1] = $part1;
++$body[2] = $part2;
++$body[3] = $part3;
++
++echo imap_mail_compose($envelope, $body);
++?>
++--EXPECTF--
++Warning: imap_mail_compose(): header injection attempt in from in %s on line %d
+diff --git a/ext/imap/tests/bug80710_2.phpt b/ext/imap/tests/bug80710_2.phpt
+new file mode 100644
+index 0000000000..b9f2fa8544
+--- /dev/null
++++ b/ext/imap/tests/bug80710_2.phpt
+@@ -0,0 +1,37 @@
++--TEST--
++Bug #80710 (imap_mail_compose() header injection) - Remail
++--SKIPIF--
++<?php
++if (!extension_loaded("imap")) die("skip imap extension not available");
++?>
++--FILE--
++<?php
++$envelope["from"]= "joe@example.com\n From : X-INJECTED";
++$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
++$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
++$envelope["remail"] = "X-INJECTED-REMAIL: X-INJECTED\nFrom: X-INJECTED-REMAIL-FROM"; //<--- Injected as first hdr
++$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
++
++$part1["type"] = TYPEMULTIPART;
++$part1["subtype"] = "mixed";
++
++$part2["type"] = TYPEAPPLICATION;
++$part2["encoding"] = ENCBINARY;
++$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
++$part2["description"] = "some file\nContent-Type: X-INJECTED";
++$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
++
++$part3["type"] = TYPETEXT;
++$part3["subtype"] = "plain";
++$part3["description"] = "description3";
++$part3["contents.data"] = "contents.data3\n\n\n\t";
++
++$body[1] = $part1;
++$body[2] = $part2;
++$body[3] = $part3;
++
++echo imap_mail_compose($envelope, $body);
++?>
++--EXPECTF--
++Warning: imap_mail_compose(): header injection attempt in remail in %s on line %d
+--
+2.30.2
+
+From f16c623ec8ae3f3cdc73ab3fa05ae6bb0a77d1f3 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Tue, 27 Apr 2021 13:38:39 +0200
+Subject: [PATCH 2/2] Add missing NEWS entry for #80710
+
+(cherry picked from commit 60a68a45c3e9f63585151221e7fe9ddff78bd71f)
+---
+ NEWS | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 884285f05f..e331598176 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,11 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.3.28
++
++- Imap:
++ . Fixed bug #80710 (imap_mail_compose() header injection). (cmb, Stas)
++
+ Backported from 7.3.27
+
+ - SOAP:
+--
+2.30.2
+
diff --git a/php-bug81026.patch b/php-bug81026.patch
new file mode 100644
index 0000000..3bb8cc7
--- /dev/null
+++ b/php-bug81026.patch
@@ -0,0 +1,429 @@
+From 7e7f808fbc9a6a5d2eabdd9e7cb058a61f439aee Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sat, 2 Oct 2021 22:53:41 +0100
+Subject: [PATCH 1/2] Fix bug #81026 (PHP-FPM oob R/W in root process leading
+ to priv escalation)
+
+The main change is to store scoreboard procs directly to the variable sized
+array rather than indirectly through the pointer.
+
+Signed-off-by: Stanislav Malyshev <stas@php.net>
+(cherry picked from commit cb2021e5f69da5e2868130a05bb53db0f9f89e4b)
+---
+ sapi/fpm/fpm/fpm_children.c | 14 ++---
+ sapi/fpm/fpm/fpm_request.c | 4 +-
+ sapi/fpm/fpm/fpm_scoreboard.c | 106 ++++++++++++++++++++-------------
+ sapi/fpm/fpm/fpm_scoreboard.h | 11 ++--
+ sapi/fpm/fpm/fpm_status.c | 4 +-
+ sapi/fpm/fpm/fpm_worker_pool.c | 2 +-
+ 6 files changed, 81 insertions(+), 60 deletions(-)
+
+diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
+index eed0c6757a..05513f0084 100644
+--- a/sapi/fpm/fpm/fpm_children.c
++++ b/sapi/fpm/fpm/fpm_children.c
+@@ -243,7 +243,7 @@ void fpm_children_bury() /* {{{ */
+
+ fpm_child_unlink(child);
+
+- fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i);
++ fpm_scoreboard_proc_free(child);
+
+ fpm_clock_get(&tv1);
+
+@@ -253,9 +253,9 @@ void fpm_children_bury() /* {{{ */
+ if (!fpm_pctl_can_spawn_children()) {
+ severity = ZLOG_DEBUG;
+ }
+- zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
++ zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
+ } else {
+- zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
++ zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
+ }
+
+ fpm_child_close(child, 1 /* in event_loop */);
+@@ -321,7 +321,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
+ return 0;
+ }
+
+- if (0 > fpm_scoreboard_proc_alloc(wp->scoreboard, &c->scoreboard_i)) {
++ if (0 > fpm_scoreboard_proc_alloc(c)) {
+ fpm_stdio_discard_pipes(c);
+ fpm_child_free(c);
+ return 0;
+@@ -333,7 +333,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
+
+ static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */
+ {
+- fpm_scoreboard_proc_free(child->wp->scoreboard, child->scoreboard_i);
++ fpm_scoreboard_proc_free(child);
+ fpm_stdio_discard_pipes(child);
+ fpm_child_free(child);
+ }
+@@ -346,10 +346,10 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
+ if (wp == child->wp) {
+ continue;
+ }
+- fpm_scoreboard_free(wp->scoreboard);
++ fpm_scoreboard_free(wp);
+ }
+
+- fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, getpid());
++ fpm_scoreboard_child_use(child, getpid());
+ fpm_stdio_child_use_pipes(child);
+ fpm_child_free(child);
+ }
+diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
+index a4ace85310..deaccf432a 100644
+--- a/sapi/fpm/fpm/fpm_request.c
++++ b/sapi/fpm/fpm/fpm_request.c
+@@ -286,7 +286,7 @@ int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */
+ struct fpm_scoreboard_proc_s *proc;
+
+ /* no need in atomicity here */
+- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return 0;
+ }
+@@ -301,7 +301,7 @@ int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /*
+
+ if (!tv) return -1;
+
+- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return -1;
+ }
+diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
+index 7a65fcbeb7..091efdc574 100644
+--- a/sapi/fpm/fpm/fpm_scoreboard.c
++++ b/sapi/fpm/fpm/fpm_scoreboard.c
+@@ -7,6 +7,7 @@
+ #include <time.h>
+
+ #include "fpm_config.h"
++#include "fpm_children.h"
+ #include "fpm_scoreboard.h"
+ #include "fpm_shm.h"
+ #include "fpm_sockets.h"
+@@ -24,7 +25,6 @@ static float fpm_scoreboard_tick;
+ int fpm_scoreboard_init_main() /* {{{ */
+ {
+ struct fpm_worker_pool_s *wp;
+- unsigned int i;
+
+ #ifdef HAVE_TIMES
+ #if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
+@@ -41,7 +41,7 @@ int fpm_scoreboard_init_main() /* {{{ */
+
+
+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+- size_t scoreboard_size, scoreboard_nprocs_size;
++ size_t scoreboard_procs_size;
+ void *shm_mem;
+
+ if (wp->config->pm_max_children < 1) {
+@@ -54,22 +54,15 @@ int fpm_scoreboard_init_main() /* {{{ */
+ return -1;
+ }
+
+- scoreboard_size = sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children) * sizeof(struct fpm_scoreboard_proc_s *);
+- scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
+- shm_mem = fpm_shm_alloc(scoreboard_size + scoreboard_nprocs_size);
++ scoreboard_procs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
++ shm_mem = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + scoreboard_procs_size);
+
+ if (!shm_mem) {
+ return -1;
+ }
+- wp->scoreboard = shm_mem;
++ wp->scoreboard = shm_mem;
++ wp->scoreboard->pm = wp->config->pm;
+ wp->scoreboard->nprocs = wp->config->pm_max_children;
+- shm_mem += scoreboard_size;
+-
+- for (i = 0; i < wp->scoreboard->nprocs; i++, shm_mem += sizeof(struct fpm_scoreboard_proc_s)) {
+- wp->scoreboard->procs[i] = shm_mem;
+- }
+-
+- wp->scoreboard->pm = wp->config->pm;
+ wp->scoreboard->start_epoch = time(NULL);
+ strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool));
+ }
+@@ -163,28 +156,48 @@ struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/
+ }
+ /* }}} */
+
+-struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
++static inline struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_ex(
++ struct fpm_scoreboard_s *scoreboard, int child_index, unsigned int nprocs) /* {{{*/
+ {
+ if (!scoreboard) {
+- scoreboard = fpm_scoreboard;
++ return NULL;
+ }
+
+- if (!scoreboard) {
++ if (child_index < 0 || (unsigned int)child_index >= nprocs) {
+ return NULL;
+ }
+
++ return &scoreboard->procs[child_index];
++}
++/* }}} */
++
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(
++ struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
++{
++ if (!scoreboard) {
++ scoreboard = fpm_scoreboard;
++ }
++
+ if (child_index < 0) {
+ child_index = fpm_scoreboard_i;
+ }
+
+- if (child_index < 0 || (unsigned int)child_index >= scoreboard->nprocs) {
+- return NULL;
+- }
++ return fpm_scoreboard_proc_get_ex(scoreboard, child_index, scoreboard->nprocs);
++}
++/* }}} */
+
+- return scoreboard->procs[child_index];
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child) /* {{{*/
++{
++ struct fpm_worker_pool_s *wp = child->wp;
++ unsigned int nprocs = wp->config->pm_max_children;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int child_index = child->scoreboard_i;
++
++ return fpm_scoreboard_proc_get_ex(scoreboard, child_index, nprocs);
+ }
+ /* }}} */
+
++
+ struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
+ {
+ struct fpm_scoreboard_s *s;
+@@ -235,28 +248,28 @@ void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */
+ proc->lock = 0;
+ }
+
+-void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */
++void fpm_scoreboard_free(struct fpm_worker_pool_s *wp) /* {{{ */
+ {
+- size_t scoreboard_size, scoreboard_nprocs_size;
++ size_t scoreboard_procs_size;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
+
+ if (!scoreboard) {
+ zlog(ZLOG_ERROR, "**scoreboard is NULL");
+ return;
+ }
+
+- scoreboard_size = sizeof(struct fpm_scoreboard_s) + (scoreboard->nprocs) * sizeof(struct fpm_scoreboard_proc_s *);
+- scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * scoreboard->nprocs;
++ scoreboard_procs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
+
+- fpm_shm_free(scoreboard, scoreboard_size + scoreboard_nprocs_size);
++ fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s) + scoreboard_procs_size);
+ }
+ /* }}} */
+
+-void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */
++void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid) /* {{{ */
+ {
+ struct fpm_scoreboard_proc_s *proc;
+- fpm_scoreboard = scoreboard;
+- fpm_scoreboard_i = child_index;
+- proc = fpm_scoreboard_proc_get(scoreboard, child_index);
++ fpm_scoreboard = child->wp->scoreboard;
++ fpm_scoreboard_i = child->scoreboard_i;
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return;
+ }
+@@ -265,18 +278,22 @@ void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_ind
+ }
+ /* }}} */
+
+-void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */
++void fpm_scoreboard_proc_free(struct fpm_child_s *child) /* {{{ */
+ {
++ struct fpm_worker_pool_s *wp = child->wp;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int child_index = child->scoreboard_i;
++
+ if (!scoreboard) {
+ return;
+ }
+
+- if (child_index < 0 || (unsigned int)child_index >= scoreboard->nprocs) {
++ if (child_index < 0 || child_index >= wp->config->pm_max_children) {
+ return;
+ }
+
+- if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
+- memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
++ if (scoreboard->procs[child_index].used > 0) {
++ memset(&scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
+ }
+
+ /* set this slot as free to avoid search on next alloc */
+@@ -284,41 +301,44 @@ void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_ind
+ }
+ /* }}} */
+
+-int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */
++int fpm_scoreboard_proc_alloc(struct fpm_child_s *child) /* {{{ */
+ {
+ int i = -1;
++ struct fpm_worker_pool_s *wp = child->wp;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int nprocs = wp->config->pm_max_children;
+
+- if (!scoreboard || !child_index) {
++ if (!scoreboard) {
+ return -1;
+ }
+
+ /* first try the slot which is supposed to be free */
+- if (scoreboard->free_proc >= 0 && (unsigned int)scoreboard->free_proc < scoreboard->nprocs) {
+- if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
++ if (scoreboard->free_proc >= 0 && scoreboard->free_proc < nprocs) {
++ if (!scoreboard->procs[scoreboard->free_proc].used) {
+ i = scoreboard->free_proc;
+ }
+ }
+
+ if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
+ zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
+- for (i = 0; i < (int)scoreboard->nprocs; i++) {
+- if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */
++ for (i = 0; i < nprocs; i++) {
++ if (!scoreboard->procs[i].used) { /* found */
+ break;
+ }
+ }
+ }
+
+ /* no free slot */
+- if (i < 0 || i >= (int)scoreboard->nprocs) {
++ if (i < 0 || i >= nprocs) {
+ zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
+ return -1;
+ }
+
+- scoreboard->procs[i]->used = 1;
+- *child_index = i;
++ scoreboard->procs[i].used = 1;
++ child->scoreboard_i = i;
+
+ /* supposed next slot is free */
+- if (i + 1 >= (int)scoreboard->nprocs) {
++ if (i + 1 >= nprocs) {
+ scoreboard->free_proc = 0;
+ } else {
+ scoreboard->free_proc = i + 1;
+diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
+index abce616d76..6405abb7cf 100644
+--- a/sapi/fpm/fpm/fpm_scoreboard.h
++++ b/sapi/fpm/fpm/fpm_scoreboard.h
+@@ -64,7 +64,7 @@ struct fpm_scoreboard_s {
+ unsigned int nprocs;
+ int free_proc;
+ unsigned long int slow_rq;
+- struct fpm_scoreboard_proc_s *procs[];
++ struct fpm_scoreboard_proc_s procs[];
+ };
+
+ int fpm_scoreboard_init_main();
+@@ -73,18 +73,19 @@ int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp);
+ void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard);
+ struct fpm_scoreboard_s *fpm_scoreboard_get();
+ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index);
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child);
+
+ struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang);
+ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard);
+ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang);
+ void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc);
+
+-void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard);
++void fpm_scoreboard_free(struct fpm_worker_pool_s *wp);
+
+-void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid);
++void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid);
+
+-void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
+-int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
++void fpm_scoreboard_proc_free(struct fpm_child_s *child);
++int fpm_scoreboard_proc_alloc(struct fpm_child_s *child);
+
+ #ifdef HAVE_TIMES
+ float fpm_scoreboard_get_tick();
+diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
+index 1d78ebf849..45852a5b39 100644
+--- a/sapi/fpm/fpm/fpm_status.c
++++ b/sapi/fpm/fpm/fpm_status.c
+@@ -402,10 +402,10 @@ int fpm_status_handle_request(void) /* {{{ */
+
+ first = 1;
+ for (i=0; i<scoreboard_p->nprocs; i++) {
+- if (!scoreboard_p->procs[i] || !scoreboard_p->procs[i]->used) {
++ if (!scoreboard_p->procs[i].used) {
+ continue;
+ }
+- proc = *scoreboard_p->procs[i];
++ proc = scoreboard_p->procs[i];
+
+ if (first) {
+ first = 0;
+diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c
+index 90e155975e..96b7ca50fc 100644
+--- a/sapi/fpm/fpm/fpm_worker_pool.c
++++ b/sapi/fpm/fpm/fpm_worker_pool.c
+@@ -43,7 +43,7 @@ static void fpm_worker_pool_cleanup(int which, void *arg) /* {{{ */
+ fpm_worker_pool_config_free(wp->config);
+ fpm_children_free(wp->children);
+ if ((which & FPM_CLEANUP_CHILD) == 0 && fpm_globals.parent_pid == getpid()) {
+- fpm_scoreboard_free(wp->scoreboard);
++ fpm_scoreboard_free(wp);
+ }
+ fpm_worker_pool_free(wp);
+ }
+--
+2.31.1
+
+From b84a7a8c2db91714bfb2894894e61758189983df Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 20 Oct 2021 14:06:59 +0200
+Subject: [PATCH 2/2] NEWS
+
+---
+ NEWS | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 1e8a7c7903..b8b1849134 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.4.25
++
++- FPM:
++ . Fixed bug #81026 (PHP-FPM oob R/W in root process leading to privilege
++ escalation) (CVE-2021-21703). (Jakub Zelenka)
++
+ Backported from 7.3.30
+
+ - Phar:
+--
+2.31.1
+
diff --git a/php-bug81122.patch b/php-bug81122.patch
new file mode 100644
index 0000000..a534139
--- /dev/null
+++ b/php-bug81122.patch
@@ -0,0 +1,88 @@
+From 34e7f97cf67a8e2e0dd6675e4d82c0f8be7ad77f Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Mon, 14 Jun 2021 13:22:27 +0200
+Subject: [PATCH 1/7] Fix #81122: SSRF bypass in FILTER_VALIDATE_URL
+
+We need to ensure that the password detected by parse_url() is actually
+a valid password; we can re-use is_userinfo_valid() for that.
+
+(cherry picked from commit a5538c62293fa782fcc382d0635cfc0c8b9190e3)
+---
+ ext/filter/logical_filters.c | 4 +++-
+ ext/filter/tests/bug81122.phpt | 21 +++++++++++++++++++++
+ 2 files changed, 24 insertions(+), 1 deletion(-)
+ create mode 100644 ext/filter/tests/bug81122.phpt
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index ad0956a505..7ddf44cff0 100644
+--- a/ext/filter/logical_filters.c
++++ b/ext/filter/logical_filters.c
+@@ -587,7 +587,9 @@ bad_url:
+ RETURN_VALIDATION_FAILED
+ }
+
+- if (url->user != NULL && !is_userinfo_valid(url->user)) {
++ if (url->user != NULL && !is_userinfo_valid(url->user)
++ || url->pass != NULL && !is_userinfo_valid(url->pass)
++ ) {
+ php_url_free(url);
+ RETURN_VALIDATION_FAILED
+
+diff --git a/ext/filter/tests/bug81122.phpt b/ext/filter/tests/bug81122.phpt
+new file mode 100644
+index 0000000000..d89d4114a5
+--- /dev/null
++++ b/ext/filter/tests/bug81122.phpt
+@@ -0,0 +1,21 @@
++--TEST--
++Bug #81122 (SSRF bypass in FILTER_VALIDATE_URL)
++--SKIPIF--
++<?php
++if (!extension_loaded('filter')) die("skip filter extension not available");
++?>
++--FILE--
++<?php
++$urls = [
++ "https://example.com:\\@test.com/",
++ "https://user:\\epass@test.com",
++ "https://user:\\@test.com",
++];
++foreach ($urls as $url) {
++ var_dump(filter_var($url, FILTER_VALIDATE_URL));
++}
++?>
++--EXPECT--
++bool(false)
++bool(false)
++bool(false)
+--
+2.31.1
+
+From 84d1d39e26520ae131a6ac14891c836adc969ad5 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Sun, 27 Jun 2021 21:57:58 -0700
+Subject: [PATCH 2/7] Fix warning
+
+(cherry picked from commit 190013787bbc424c240413d914e3a038f974ccef)
+---
+ ext/filter/logical_filters.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index 7ddf44cff0..6894fa2551 100644
+--- a/ext/filter/logical_filters.c
++++ b/ext/filter/logical_filters.c
+@@ -587,8 +587,8 @@ bad_url:
+ RETURN_VALIDATION_FAILED
+ }
+
+- if (url->user != NULL && !is_userinfo_valid(url->user)
+- || url->pass != NULL && !is_userinfo_valid(url->pass)
++ if ((url->user != NULL && !is_userinfo_valid(url->user))
++ || (url->pass != NULL && !is_userinfo_valid(url->pass))
+ ) {
+ php_url_free(url);
+ RETURN_VALIDATION_FAILED
+--
+2.31.1
+
diff --git a/php-bug81211.patch b/php-bug81211.patch
new file mode 100644
index 0000000..1e09d65
--- /dev/null
+++ b/php-bug81211.patch
@@ -0,0 +1,163 @@
+From 92a270e564ffda7fe825d1472fe567323f137fba Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Mon, 23 Aug 2021 13:42:17 +0200
+Subject: [PATCH 1/3] Fix #81211: Symlinks are followed when creating PHAR
+ archive
+
+It is insufficient to check whether the `base` is contained in `fname`;
+we also need to ensure that `fname` is properly separated. And of
+course, `fname` has to start with `base`.
+
+(cherry picked from commit 2ff853aa113e52637c85e28d1a03df1aa2d747b5)
+---
+ ext/phar/phar_object.c | 3 +-
+ ext/phar/tests/bug81211.phpt | 45 +++++++++++++++++++
+ .../tests/file/windows_links/common.inc | 9 +++-
+ 3 files changed, 55 insertions(+), 2 deletions(-)
+ create mode 100644 ext/phar/tests/bug81211.phpt
+
+diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
+index 2987b64012..01bdc0596b 100644
+--- a/ext/phar/phar_object.c
++++ b/ext/phar/phar_object.c
+@@ -1440,6 +1440,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
+ zend_class_entry *ce = p_obj->c;
+ phar_archive_object *phar_obj = p_obj->p;
+ php_stream_statbuf ssb;
++ char ch;
+
+ value = iter->funcs->get_current_data(iter);
+
+@@ -1569,7 +1570,7 @@ phar_spl_fileinfo:
+ base = temp;
+ base_len = (int)strlen(base);
+
+- if (strstr(fname, base)) {
++ if (fname_len >= base_len && strncmp(fname, base, base_len) == 0 && ((ch = fname[base_len - IS_SLASH(base[base_len - 1])]) == '\0' || IS_SLASH(ch))) {
+ str_key_len = fname_len - base_len;
+
+ if (str_key_len <= 0) {
+diff --git a/ext/phar/tests/bug81211.phpt b/ext/phar/tests/bug81211.phpt
+new file mode 100644
+index 0000000000..43d82143f2
+--- /dev/null
++++ b/ext/phar/tests/bug81211.phpt
+@@ -0,0 +1,45 @@
++--TEST--
++Bug #81211 (Symlinks are followed when creating PHAR archive)
++--SKIPIF--
++<?php
++if (!extension_loaded('phar')) die('skip phar extension is not available');
++if (PHP_OS_FAMILY === 'Windows') {
++ if (false === include __DIR__ . '/../../standard/tests/file/windows_links/common.inc') {
++ die('skip windows_links/common.inc is not available');
++ }
++ skipIfSeCreateSymbolicLinkPrivilegeIsDisabled(__FILE__);
++}
++?>
++--FILE--
++<?php
++mkdir(__DIR__ . '/bug81211');
++mkdir(__DIR__ . '/bug81211/foobar');
++mkdir(__DIR__ . '/bug81211/foo');
++
++file_put_contents(__DIR__ . '/bug81211/foobar/file', 'this file should NOT be included in the archive!');
++symlink(__DIR__ . '/bug81211/foobar/file', __DIR__ . '/bug81211/foo/symlink');
++
++$archive = new PharData(__DIR__ . '/bug81211/archive.tar');
++try {
++ $archive->buildFromDirectory(__DIR__ . '/bug81211/foo');
++} catch (UnexpectedValueException $ex) {
++ echo $ex->getMessage(), PHP_EOL;
++}
++try {
++ $archive->buildFromIterator(new RecursiveDirectoryIterator(__DIR__ . '/bug81211/foo', FilesystemIterator::SKIP_DOTS), __DIR__ . '/bug81211/foo');
++} catch (UnexpectedValueException $ex) {
++ echo $ex->getMessage(), PHP_EOL;
++}
++?>
++--CLEAN--
++<?php
++@unlink(__DIR__ . '/bug81211/archive.tar');
++@unlink(__DIR__ . '/bug81211/foo/symlink');
++@unlink(__DIR__ . '/bug81211/foobar/file');
++@rmdir(__DIR__ . '/bug81211/foo');
++@rmdir(__DIR__ . '/bug81211/foobar');
++@rmdir(__DIR__ . '/bug81211');
++?>
++--EXPECTF--
++Iterator RecursiveIteratorIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo"
++Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo"
+diff --git a/ext/standard/tests/file/windows_links/common.inc b/ext/standard/tests/file/windows_links/common.inc
+index 505368b8b0..caa3758d44 100644
+--- a/ext/standard/tests/file/windows_links/common.inc
++++ b/ext/standard/tests/file/windows_links/common.inc
+@@ -20,4 +20,11 @@ function get_mountvol() {
+ return "$sysroot\\System32\\mountvol.exe";
+ }
+
+-?>
++function skipIfSeCreateSymbolicLinkPrivilegeIsDisabled(string $filename) {
++ $ln = "$filename.lnk";
++ $ret = exec("mklink $ln " . __FILE__ .' 2>&1', $out);
++ @unlink($ln);
++ if (strpos($ret, 'privilege') !== false) {
++ die('skip SeCreateSymbolicLinkPrivilege not enabled');
++ }
++}
+--
+2.31.1
+
+From cb376010c6a48c5454c47140dfbdee6f0e48bb12 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <stas@php.net>
+Date: Mon, 23 Aug 2021 23:43:32 -0700
+Subject: [PATCH 2/3] Fix test
+
+(cherry picked from commit b815645aac76b494dc119fa6b88de32fa9bcccf1)
+---
+ ext/phar/tests/bug81211.phpt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/phar/tests/bug81211.phpt b/ext/phar/tests/bug81211.phpt
+index 43d82143f2..96b1401b40 100644
+--- a/ext/phar/tests/bug81211.phpt
++++ b/ext/phar/tests/bug81211.phpt
+@@ -41,5 +41,5 @@ try {
+ @rmdir(__DIR__ . '/bug81211');
+ ?>
+ --EXPECTF--
+-Iterator RecursiveIteratorIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo"
+-Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo"
++Iterator RecursiveIteratorIterator returned a path "%s%ebug81211%efoobar%efile" that is not in the base directory "%s%ebug81211%efoo"
++Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211%efoobar%efile" that is not in the base directory "%s%ebug81211%efoo"
+--
+2.31.1
+
+From 5539cefcda6aca7af220e7be7760a682abb88200 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 25 Aug 2021 15:23:50 +0200
+Subject: [PATCH 3/3] NEWS
+
+---
+ NEWS | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index f083e44dcc..1e8a7c7903 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,11 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.3.30
++
++- Phar:
++ . Fixed bug #81211: Symlinks are followed when creating PHAR archive (cmb)
++
+ Backported from 7.3.29
+
+ - Core:
+--
+2.31.1
+
diff --git a/php-bug81719.patch b/php-bug81719.patch
new file mode 100644
index 0000000..5aa8ab5
--- /dev/null
+++ b/php-bug81719.patch
@@ -0,0 +1,62 @@
+From 1560224d3a26574f0195af3853e4d7e050b0b06f Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <smalyshev@gmail.com>
+Date: Mon, 6 Jun 2022 00:56:51 -0600
+Subject: [PATCH 2/3] Fix bug #81719: mysqlnd/pdo password buffer overflow
+
+(cherry picked from commit 58006537fc5f133ae8549efe5118cde418b3ace9)
+(cherry picked from commit 9433de72e291db518357fe55531cc15432d43ec4)
+---
+ ext/mysqlnd/mysqlnd_wireprotocol.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
+index 759b131b63..eb7af323a4 100644
+--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
++++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
+@@ -794,7 +794,8 @@ php_mysqlnd_change_auth_response_write(void * _packet)
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+- zend_uchar * buffer = pfc->cmd_buffer.length >= packet->auth_data_len? pfc->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
++ size_t total_packet_size = packet->auth_data_len + MYSQLND_HEADER_SIZE;
++ zend_uchar * const buffer = pfc->cmd_buffer.length >= total_packet_size? pfc->cmd_buffer.buffer : mnd_emalloc(total_packet_size);
+ zend_uchar * p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+
+ DBG_ENTER("php_mysqlnd_change_auth_response_write");
+--
+2.35.3
+
+From 87247fb08e905e629836350ac4e639edd1b40ed8 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 7 Jun 2022 09:57:15 +0200
+Subject: [PATCH 3/3] NEWS
+
+(cherry picked from commit f451082baf14ee9ea86cdd19870e906adb368f02)
+---
+ NEWS | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 2177c64aef..8f09ddfee0 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,16 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.4.30
++
++- mysqlnd:
++ . Fixed bug #81719: mysqlnd/pdo password buffer overflow.
++ (CVE-2022-31626) (c dot fol at ambionics dot io)
++
++- pgsql
++ . Fixed bug #81720: Uninitialized array in pg_query_params().
++ (CVE-2022-31625) (cmb)
++
+ Backported from 7.3.33
+
+ - XML:
+--
+2.35.3
+
diff --git a/php-bug81720.patch b/php-bug81720.patch
new file mode 100644
index 0000000..3e47b6c
--- /dev/null
+++ b/php-bug81720.patch
@@ -0,0 +1,77 @@
+From 310b17f5c8938389b1dbd7d8ff5a8144bfb9a351 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Tue, 17 May 2022 12:59:23 +0200
+Subject: [PATCH 1/3] Fix #81720: Uninitialized array in pg_query_params()
+ leading to RCE
+
+We must not free parameters which we haven't initialized yet.
+
+We also fix the not directly related issue, that we checked for the
+wrong value being `NULL`, potentially causing a segfault.
+
+(cherry picked from commit 55f6895f4b4c677272fd4ee1113acdbd99c4b5ab)
+(cherry picked from commit 6f979c832c861fb32e2dbad5e0cc29edcee7c500)
+---
+ ext/pgsql/pgsql.c | 4 ++--
+ ext/pgsql/tests/bug81720.phpt | 27 +++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 2 deletions(-)
+ create mode 100644 ext/pgsql/tests/bug81720.phpt
+
+diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
+index c97c600b66..8bc7568056 100644
+--- a/ext/pgsql/pgsql.c
++++ b/ext/pgsql/pgsql.c
+@@ -1988,7 +1988,7 @@ PHP_FUNCTION(pg_query_params)
+ if (Z_TYPE(tmp_val) != IS_STRING) {
+ php_error_docref(NULL, E_WARNING,"Error converting parameter");
+ zval_ptr_dtor(&tmp_val);
+- _php_pgsql_free_params(params, num_params);
++ _php_pgsql_free_params(params, i);
+ RETURN_FALSE;
+ }
+ params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
+@@ -5188,7 +5188,7 @@ PHP_FUNCTION(pg_send_execute)
+ if (Z_TYPE(tmp_val) != IS_STRING) {
+ php_error_docref(NULL, E_WARNING,"Error converting parameter");
+ zval_ptr_dtor(&tmp_val);
+- _php_pgsql_free_params(params, num_params);
++ _php_pgsql_free_params(params, i);
+ RETURN_FALSE;
+ }
+ params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
+diff --git a/ext/pgsql/tests/bug81720.phpt b/ext/pgsql/tests/bug81720.phpt
+new file mode 100644
+index 0000000000..d79f1fcdd6
+--- /dev/null
++++ b/ext/pgsql/tests/bug81720.phpt
+@@ -0,0 +1,27 @@
++--TEST--
++Bug #81720 (Uninitialized array in pg_query_params() leading to RCE)
++--SKIPIF--
++<?php include("skipif.inc"); ?>
++--FILE--
++<?php
++include('config.inc');
++
++$conn = pg_connect($conn_str);
++
++try {
++ pg_query_params($conn, 'SELECT $1, $2', [1, new stdClass()]);
++} catch (Throwable $ex) {
++ echo $ex->getMessage(), PHP_EOL;
++}
++
++try {
++ pg_send_prepare($conn, "my_query", 'SELECT $1, $2');
++ pg_get_result($conn);
++ pg_send_execute($conn, "my_query", [1, new stdClass()]);
++} catch (Throwable $ex) {
++ echo $ex->getMessage(), PHP_EOL;
++}
++?>
++--EXPECT--
++Object of class stdClass could not be converted to string
++Object of class stdClass could not be converted to string
+--
+2.35.3
+
diff --git a/php-bug81726.patch b/php-bug81726.patch
new file mode 100644
index 0000000..847ebff
--- /dev/null
+++ b/php-bug81726.patch
@@ -0,0 +1,180 @@
+From 2bdc26af43cdd4376bf8e0fdf532bb12dd35d3dd Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Mon, 25 Jul 2022 15:58:59 +0200
+Subject: [PATCH 2/2] Fix #81726: phar wrapper: DOS when using quine gzip file
+
+The phar wrapper needs to uncompress the file; the uncompressed file
+might be compressed, so the wrapper implementation loops. This raises
+potential DOS issues regarding too deep or even infinite recursion (the
+latter are called compressed file quines[1]). We avoid that by
+introducing a recursion limit; we choose the somewhat arbitrary limit
+`3`.
+
+This issue has been reported by real_as3617 and gPayl0ad.
+
+[1] <https://honno.dev/gzip-quine/>
+
+(cherry picked from commit 404e8bdb68350931176a5bdc86fc417b34fb583d)
+(cherry picked from commit 96fda78bcddd1d793cf2d0ee463dbb49621b577f)
+---
+ NEWS | 2 ++
+ ext/phar/phar.c | 16 +++++++++++-----
+ ext/phar/tests/bug81726.gz | Bin 0 -> 204 bytes
+ ext/phar/tests/bug81726.phpt | 14 ++++++++++++++
+ 4 files changed, 27 insertions(+), 5 deletions(-)
+ create mode 100644 ext/phar/tests/bug81726.gz
+ create mode 100644 ext/phar/tests/bug81726.phpt
+
+diff --git a/NEWS b/NEWS
+index 90ac6b751b..be8bfd2f98 100644
+--- a/NEWS
++++ b/NEWS
+@@ -4,6 +4,8 @@ PHP NEWS
+ Backported from 7.4.31
+
+ - Core:
++ . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
++ (CVE-2022-31628). (cmb)
+ . Fixed bug #81727: Don't mangle HTTP variable names that clash with ones
+ that have a specific semantic meaning. (CVE-2022-31629). (Derick)
+
+diff --git a/ext/phar/phar.c b/ext/phar/phar.c
+index ba76a9b0e0..52c973d7c4 100644
+--- a/ext/phar/phar.c
++++ b/ext/phar/phar.c
+@@ -1575,7 +1575,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ const char zip_magic[] = "PK\x03\x04";
+ const char gz_magic[] = "\x1f\x8b\x08";
+ const char bz_magic[] = "BZh";
+- char *pos, test = '\0';
++ char *pos;
++ int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion
+ const int window_size = 1024;
+ char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */
+ const zend_long readsize = sizeof(buffer) - sizeof(token);
+@@ -1603,8 +1604,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
+ }
+
+- if (!test) {
+- test = '\1';
++ if (recursion_count) {
+ pos = buffer+tokenlen;
+ if (!memcmp(pos, gz_magic, 3)) {
+ char err = 0;
+@@ -1664,7 +1664,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ compression = PHAR_FILE_COMPRESSED_GZ;
+
+ /* now, start over */
+- test = '\0';
++ if (!--recursion_count) {
++ MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\"");
++ break;
++ }
+ continue;
+ } else if (!memcmp(pos, bz_magic, 3)) {
+ php_stream_filter *filter;
+@@ -1702,7 +1705,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ compression = PHAR_FILE_COMPRESSED_BZ2;
+
+ /* now, start over */
+- test = '\0';
++ if (!--recursion_count) {
++ MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\"");
++ break;
++ }
+ continue;
+ }
+
+From 8fad7bf40e1b5bf74f308eb882b1d72987ef539c Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Tue, 27 Sep 2022 17:43:40 +0200
+Subject: [PATCH] Fix regression introduced by fixing bug 81726
+
+When a tar phar is created, `phar_open_from_fp()` is also called, but
+since the file has just been created, none of the format checks can
+succeed, so we continue to loop, but must not check again for the
+format. Therefore, we bring back the old `test` variable.
+
+Closes GH-9620.
+
+(cherry picked from commit 432bf196d59bcb661fcf9cb7029cea9b43f490af)
+---
+ ext/phar/phar.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/ext/phar/phar.c b/ext/phar/phar.c
+index 52c973d7c4..534af318f4 100644
+--- a/ext/phar/phar.c
++++ b/ext/phar/phar.c
+@@ -1575,7 +1575,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ const char zip_magic[] = "PK\x03\x04";
+ const char gz_magic[] = "\x1f\x8b\x08";
+ const char bz_magic[] = "BZh";
+- char *pos;
++ char *pos, test = '\0';
+ int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion
+ const int window_size = 1024;
+ char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */
+@@ -1604,7 +1604,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
+ }
+
+- if (recursion_count) {
++ if (!test && recursion_count) {
++ test = '\1';
+ pos = buffer+tokenlen;
+ if (!memcmp(pos, gz_magic, 3)) {
+ char err = 0;
+@@ -1664,6 +1665,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ compression = PHAR_FILE_COMPRESSED_GZ;
+
+ /* now, start over */
++ test = '\0';
+ if (!--recursion_count) {
+ MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\"");
+ break;
+@@ -1705,6 +1707,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
+ compression = PHAR_FILE_COMPRESSED_BZ2;
+
+ /* now, start over */
++ test = '\0';
+ if (!--recursion_count) {
+ MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\"");
+ break;
+--
+2.37.3
+
+From 9d32d284b25f5df75780911a47b3c23cbaac1761 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Fri, 30 Sep 2022 09:22:14 +0200
+Subject: [PATCH] fix NEWS
+
+---
+ NEWS | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index fe4cb9c484..b7a19aea19 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,14 +1,16 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+-Backported from 7.4.31
++Backported from 7.4.32
+
+ - Core:
+- . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
+- (CVE-2022-31628). (cmb)
+ . Fixed bug #81727: Don't mangle HTTP variable names that clash with ones
+ that have a specific semantic meaning. (CVE-2022-31629). (Derick)
+
++- Phar:
++ . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
++ (CVE-2022-31628). (cmb)
++
+ Backported from 7.4.30
+
+ - mysqlnd:
diff --git a/php-bug81727.patch b/php-bug81727.patch
new file mode 100644
index 0000000..74a25eb
--- /dev/null
+++ b/php-bug81727.patch
@@ -0,0 +1,81 @@
+From e92c3b23aa13860777dd09106ce309dac49edd13 Mon Sep 17 00:00:00 2001
+From: Derick Rethans <github@derickrethans.nl>
+Date: Fri, 9 Sep 2022 16:54:03 +0100
+Subject: [PATCH 1/2] Fix #81727: Don't mangle HTTP variable names that clash
+ with ones that have a specific semantic meaning.
+
+(cherry picked from commit 0611be4e82887cee0de6c4cbae320d34eec946ca)
+(cherry picked from commit 8b300e157e92b0e945ad813d608f076b5323d721)
+---
+ NEWS | 6 ++++++
+ ext/standard/tests/bug81727.phpt | 15 +++++++++++++++
+ main/php_variables.c | 14 ++++++++++++++
+ 3 files changed, 35 insertions(+)
+ create mode 100644 ext/standard/tests/bug81727.phpt
+
+diff --git a/NEWS b/NEWS
+index 8f09ddfee0..90ac6b751b 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.4.31
++
++- Core:
++ . Fixed bug #81727: Don't mangle HTTP variable names that clash with ones
++ that have a specific semantic meaning. (CVE-2022-31629). (Derick)
++
+ Backported from 7.4.30
+
+ - mysqlnd:
+diff --git a/ext/standard/tests/bug81727.phpt b/ext/standard/tests/bug81727.phpt
+new file mode 100644
+index 0000000000..71a9cb46c8
+--- /dev/null
++++ b/ext/standard/tests/bug81727.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #81727: $_COOKIE name starting with ..Host/..Secure should be discarded
++--COOKIE--
++..Host-test=ignore; __Host-test=correct; . Secure-test=ignore; . Elephpant=Awesome;
++--FILE--
++<?php
++var_dump($_COOKIE);
++?>
++--EXPECT--
++array(2) {
++ ["__Host-test"]=>
++ string(7) "correct"
++ ["__Elephpant"]=>
++ string(7) "Awesome"
++}
+diff --git a/main/php_variables.c b/main/php_variables.c
+index 097c17d32a..bd59134fc9 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -109,6 +109,20 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ }
+ var_len = p - var;
+
++ /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */
++ if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) {
++ zval_ptr_dtor_nogc(val);
++ free_alloca(var_orig, use_heap);
++ return;
++ }
++
++ /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */
++ if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) {
++ zval_ptr_dtor_nogc(val);
++ free_alloca(var_orig, use_heap);
++ return;
++ }
++
+ if (var_len==0) { /* empty variable name, or variable name with a space in it */
+ zval_dtor(val);
+ free_alloca(var_orig, use_heap);
+--
+2.37.3
+
diff --git a/php-bug81738.patch b/php-bug81738.patch
new file mode 100644
index 0000000..6fceeab
--- /dev/null
+++ b/php-bug81738.patch
@@ -0,0 +1,129 @@
+From 4b1f3b84336a26db9649c5175e29984fa1b54950 Mon Sep 17 00:00:00 2001
+From: Stanislav Malyshev <smalyshev@gmail.com>
+Date: Thu, 20 Oct 2022 23:57:35 -0600
+Subject: [PATCH] Fix bug #81738 (buffer overflow in hash_update() on long
+ parameter)
+
+(cherry picked from commit de4517ad607df8d4cb3735228b39e4a48f95556c)
+---
+ NEWS | 6 ++++++
+ ext/hash/sha3/generic32lc/KeccakSponge.inc | 14 ++++++++------
+ ext/hash/sha3/generic64lc/KeccakSponge.inc | 14 ++++++++------
+ 3 files changed, 22 insertions(+), 12 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index e31f007ad0..b6e3c4fe6c 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 7.4.33
++
++- Hash:
++ . Fixed bug #81738: buffer overflow in hash_update() on long parameter.
++ (CVE-2022-37454) (nicky at mouha dot be)
++
+ Backported from 7.4.32
+
+ - Core:
+diff --git a/ext/hash/sha3/generic32lc/KeccakSponge.inc b/ext/hash/sha3/generic32lc/KeccakSponge.inc
+index 42a15aac6d..f8c42ff788 100644
+--- a/ext/hash/sha3/generic32lc/KeccakSponge.inc
++++ b/ext/hash/sha3/generic32lc/KeccakSponge.inc
+@@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
+ i = 0;
+ curData = data;
+ while(i < dataByteLen) {
+- if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {
++ if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
+ #ifdef SnP_FastLoop_Absorb
+ /* processing full blocks first */
+ if ((rateInBytes % (SnP_width/200)) == 0) {
+@@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
+ }
+ else {
+ /* normal lane: using the message queue */
+- partialBlock = (unsigned int)(dataByteLen - i);
+- if (partialBlock+instance->byteIOIndex > rateInBytes)
++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
+ partialBlock = rateInBytes-instance->byteIOIndex;
++ else
++ partialBlock = (unsigned int)(dataByteLen - i);
+ #ifdef KeccakReference
+ displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
+ #endif
+@@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
+ i = 0;
+ curData = data;
+ while(i < dataByteLen) {
+- if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
++ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
+ for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
+ SnP_Permute(instance->state);
+ SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
+@@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
+ SnP_Permute(instance->state);
+ instance->byteIOIndex = 0;
+ }
+- partialBlock = (unsigned int)(dataByteLen - i);
+- if (partialBlock+instance->byteIOIndex > rateInBytes)
++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
+ partialBlock = rateInBytes-instance->byteIOIndex;
++ else
++ partialBlock = (unsigned int)(dataByteLen - i);
+ i += partialBlock;
+
+ SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
+diff --git a/ext/hash/sha3/generic64lc/KeccakSponge.inc b/ext/hash/sha3/generic64lc/KeccakSponge.inc
+index 42a15aac6d..f8c42ff788 100644
+--- a/ext/hash/sha3/generic64lc/KeccakSponge.inc
++++ b/ext/hash/sha3/generic64lc/KeccakSponge.inc
+@@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
+ i = 0;
+ curData = data;
+ while(i < dataByteLen) {
+- if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {
++ if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
+ #ifdef SnP_FastLoop_Absorb
+ /* processing full blocks first */
+ if ((rateInBytes % (SnP_width/200)) == 0) {
+@@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat
+ }
+ else {
+ /* normal lane: using the message queue */
+- partialBlock = (unsigned int)(dataByteLen - i);
+- if (partialBlock+instance->byteIOIndex > rateInBytes)
++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
+ partialBlock = rateInBytes-instance->byteIOIndex;
++ else
++ partialBlock = (unsigned int)(dataByteLen - i);
+ #ifdef KeccakReference
+ displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
+ #endif
+@@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
+ i = 0;
+ curData = data;
+ while(i < dataByteLen) {
+- if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {
++ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
+ for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
+ SnP_Permute(instance->state);
+ SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
+@@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte
+ SnP_Permute(instance->state);
+ instance->byteIOIndex = 0;
+ }
+- partialBlock = (unsigned int)(dataByteLen - i);
+- if (partialBlock+instance->byteIOIndex > rateInBytes)
++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
+ partialBlock = rateInBytes-instance->byteIOIndex;
++ else
++ partialBlock = (unsigned int)(dataByteLen - i);
+ i += partialBlock;
+
+ SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
+--
+2.37.3
+
diff --git a/php-bug81740.patch b/php-bug81740.patch
new file mode 100644
index 0000000..de24046
--- /dev/null
+++ b/php-bug81740.patch
@@ -0,0 +1,87 @@
+From 67ef55c661506875d04e58bc9d1293a919eb798e Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Mon, 31 Oct 2022 17:20:23 +0100
+Subject: [PATCH 1/2] Fix #81740: PDO::quote() may return unquoted string
+
+`sqlite3_snprintf()` expects its first parameter to be `int`; we need
+to avoid overflow.
+
+(cherry picked from commit 921b6813da3237a83e908998483f46ae3d8bacba)
+(cherry picked from commit 7cb160efe19d3dfb8b92629805733ea186b55050)
+---
+ ext/pdo_sqlite/sqlite_driver.c | 3 +++
+ ext/pdo_sqlite/tests/bug81740.phpt | 17 +++++++++++++++++
+ 2 files changed, 20 insertions(+)
+ create mode 100644 ext/pdo_sqlite/tests/bug81740.phpt
+
+diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
+index 2bf452a88a..4bd844e2b5 100644
+--- a/ext/pdo_sqlite/sqlite_driver.c
++++ b/ext/pdo_sqlite/sqlite_driver.c
+@@ -236,6 +236,9 @@ static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t
+ /* NB: doesn't handle binary strings... use prepared stmts for that */
+ static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
+ {
++ if (unquotedlen > (INT_MAX - 3) / 2) {
++ return 0;
++ }
+ *quoted = safe_emalloc(2, unquotedlen, 3);
+ sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
+ *quotedlen = strlen(*quoted);
+diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt
+new file mode 100644
+index 0000000000..99fb07c304
+--- /dev/null
++++ b/ext/pdo_sqlite/tests/bug81740.phpt
+@@ -0,0 +1,17 @@
++--TEST--
++Bug #81740 (PDO::quote() may return unquoted string)
++--SKIPIF--
++<?php
++if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
++?>
++--INI--
++memory_limit=-1
++--FILE--
++<?php
++$pdo = new PDO("sqlite::memory:");
++$string = str_repeat("a", 0x80000000);
++var_dump($pdo->quote($string));
++?>
++--EXPECT--
++bool(false)
+--
+2.38.1
+
+From 09d73edbbcdb419611e341bec46bf083c708d864 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Mon, 19 Dec 2022 09:24:02 +0100
+Subject: [PATCH 2/2] NEWS
+
+(cherry picked from commit 7328f3a0344806b846bd05657bdce96e47810bf0)
+(cherry picked from commit 144d79977c7e2a410a705f550dbc8ee754dd1cb3)
+---
+ NEWS | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index b6e3c4fe6c..1c00ef6357 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.0.27
++
++- PDO/SQLite:
++ . Fixed bug #81740 (PDO::quote() may return unquoted string).
++ (CVE-2022-31631) (cmb)
++
+ Backported from 7.4.33
+
+ - Hash:
+--
+2.38.1
+
diff --git a/php-bug81744.patch b/php-bug81744.patch
new file mode 100644
index 0000000..2864136
--- /dev/null
+++ b/php-bug81744.patch
@@ -0,0 +1,190 @@
+From 77e6dd89b92c3c7b3191e53508b1cd1744a89208 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be>
+Date: Mon, 23 Jan 2023 21:15:24 +0100
+Subject: [PATCH 1/8] crypt: Fix validation of malformed BCrypt hashes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+PHP’s implementation of crypt_blowfish differs from the upstream Openwall
+version by adding a “PHP Hack”, which allows one to cut short the BCrypt salt
+by including a `$` character within the characters that represent the salt.
+
+Hashes that are affected by the “PHP Hack” may erroneously validate any
+password as valid when used with `password_verify` and when comparing the
+return value of `crypt()` against the input.
+
+The PHP Hack exists since the first version of PHP’s own crypt_blowfish
+implementation that was added in 1e820eca02dcf322b41fd2fe4ed2a6b8309f8ab5.
+
+No clear reason is given for the PHP Hack’s existence. This commit removes it,
+because BCrypt hashes containing a `$` character in their salt are not valid
+BCrypt hashes.
+
+(cherry picked from commit c840f71524067aa474c00c3eacfb83bd860bfc8a)
+(cherry picked from commit 7437aaae38cf4b3357e7580f9e22fd4a403b6c23)
+---
+ ext/standard/crypt_blowfish.c | 8 --
+ .../tests/crypt/bcrypt_salt_dollar.phpt | 82 +++++++++++++++++++
+ 2 files changed, 82 insertions(+), 8 deletions(-)
+ create mode 100644 ext/standard/tests/crypt/bcrypt_salt_dollar.phpt
+
+diff --git a/ext/standard/crypt_blowfish.c b/ext/standard/crypt_blowfish.c
+index 5cf306715f..e923b55ed0 100644
+--- a/ext/standard/crypt_blowfish.c
++++ b/ext/standard/crypt_blowfish.c
+@@ -377,7 +377,6 @@ static unsigned char BF_atoi64[0x60] = {
+ #define BF_safe_atoi64(dst, src) \
+ { \
+ tmp = (unsigned char)(src); \
+- if (tmp == '$') break; /* PHP hack */ \
+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+ tmp = BF_atoi64[tmp]; \
+ if (tmp > 63) return -1; \
+@@ -405,13 +404,6 @@ static int BF_decode(BF_word *dst, const char *src, int size)
+ *dptr++ = ((c3 & 0x03) << 6) | c4;
+ } while (dptr < end);
+
+- if (end - dptr == size) {
+- return -1;
+- }
+-
+- while (dptr < end) /* PHP hack */
+- *dptr++ = 0;
+-
+ return 0;
+ }
+
+diff --git a/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt
+new file mode 100644
+index 0000000000..32e335f4b0
+--- /dev/null
++++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt
+@@ -0,0 +1,82 @@
++--TEST--
++bcrypt correctly rejects salts containing $
++--FILE--
++<?php
++for ($i = 0; $i < 23; $i++) {
++ $salt = '$2y$04$' . str_repeat('0', $i) . '$';
++ $result = crypt("foo", $salt);
++ var_dump($salt);
++ var_dump($result);
++ var_dump($result === $salt);
++}
++?>
++--EXPECT--
++string(8) "$2y$04$$"
++string(2) "*0"
++bool(false)
++string(9) "$2y$04$0$"
++string(2) "*0"
++bool(false)
++string(10) "$2y$04$00$"
++string(2) "*0"
++bool(false)
++string(11) "$2y$04$000$"
++string(2) "*0"
++bool(false)
++string(12) "$2y$04$0000$"
++string(2) "*0"
++bool(false)
++string(13) "$2y$04$00000$"
++string(2) "*0"
++bool(false)
++string(14) "$2y$04$000000$"
++string(2) "*0"
++bool(false)
++string(15) "$2y$04$0000000$"
++string(2) "*0"
++bool(false)
++string(16) "$2y$04$00000000$"
++string(2) "*0"
++bool(false)
++string(17) "$2y$04$000000000$"
++string(2) "*0"
++bool(false)
++string(18) "$2y$04$0000000000$"
++string(2) "*0"
++bool(false)
++string(19) "$2y$04$00000000000$"
++string(2) "*0"
++bool(false)
++string(20) "$2y$04$000000000000$"
++string(2) "*0"
++bool(false)
++string(21) "$2y$04$0000000000000$"
++string(2) "*0"
++bool(false)
++string(22) "$2y$04$00000000000000$"
++string(2) "*0"
++bool(false)
++string(23) "$2y$04$000000000000000$"
++string(2) "*0"
++bool(false)
++string(24) "$2y$04$0000000000000000$"
++string(2) "*0"
++bool(false)
++string(25) "$2y$04$00000000000000000$"
++string(2) "*0"
++bool(false)
++string(26) "$2y$04$000000000000000000$"
++string(2) "*0"
++bool(false)
++string(27) "$2y$04$0000000000000000000$"
++string(2) "*0"
++bool(false)
++string(28) "$2y$04$00000000000000000000$"
++string(2) "*0"
++bool(false)
++string(29) "$2y$04$000000000000000000000$"
++string(2) "*0"
++bool(false)
++string(30) "$2y$04$0000000000000000000000$"
++string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K"
++bool(false)
+--
+2.39.1
+
+From c57400002961b6df74960c52777ad0fb3dbeabea Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be>
+Date: Mon, 23 Jan 2023 22:13:57 +0100
+Subject: [PATCH 2/8] crypt: Fix possible buffer overread in php_crypt()
+
+(cherry picked from commit a92acbad873a05470af1a47cb785a18eadd827b5)
+(cherry picked from commit ed0281b588a6840cb95f3134a4e68847a3be5bb7)
+---
+ ext/standard/crypt.c | 1 +
+ ext/standard/tests/password/password_bcrypt_short.phpt | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+ create mode 100644 ext/standard/tests/password/password_bcrypt_short.phpt
+
+diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c
+index e873ca7946..c391cfd3f6 100644
+--- a/ext/standard/crypt.c
++++ b/ext/standard/crypt.c
+@@ -156,6 +156,7 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch
+ } else if (
+ salt[0] == '$' &&
+ salt[1] == '2' &&
++ salt[2] != 0 &&
+ salt[3] == '$') {
+ char output[PHP_MAX_SALT_LEN + 1];
+
+diff --git a/ext/standard/tests/password/password_bcrypt_short.phpt b/ext/standard/tests/password/password_bcrypt_short.phpt
+new file mode 100644
+index 0000000000..085bc8a239
+--- /dev/null
++++ b/ext/standard/tests/password/password_bcrypt_short.phpt
+@@ -0,0 +1,8 @@
++--TEST--
++Test that password_hash() does not overread buffers when a short hash is passed
++--FILE--
++<?php
++var_dump(password_verify("foo", '$2'));
++?>
++--EXPECT--
++bool(false)
+--
+2.39.1
+
diff --git a/php-bug81746.patch b/php-bug81746.patch
new file mode 100644
index 0000000..c654709
--- /dev/null
+++ b/php-bug81746.patch
@@ -0,0 +1,100 @@
+From 3640e9897928d5b5607270c20593a0c04a455e1e Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 27 Jan 2023 19:28:27 +0100
+Subject: [PATCH 3/8] Fix array overrun when appending slash to paths
+
+Fix it by extending the array sizes by one character. As the input is
+limited to the maximum path length, there will always be place to append
+the slash. As the php_check_specific_open_basedir() simply uses the
+strings to compare against each other, no new failures related to too
+long paths are introduced.
+We'll let the DOM and XML case handle a potentially too long path in the
+library code.
+
+(cherry picked from commit ec10b28d64decbc54aa1e585dce580f0bd7a5953)
+(cherry picked from commit 887cd0710ad856a0d22c329b6ea6c71ebd8621ae)
+---
+ ext/dom/document.c | 2 +-
+ ext/xmlreader/php_xmlreader.c | 2 +-
+ main/fopen_wrappers.c | 6 +++---
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/ext/dom/document.c b/ext/dom/document.c
+index 11ef4aa818..c212faa695 100644
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -1359,7 +1359,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
+ int validate, recover, resolve_externals, keep_blanks, substitute_ent;
+ int resolved_path_len;
+ int old_error_reporting = 0;
+- char *directory=NULL, resolved_path[MAXPATHLEN];
++ char *directory=NULL, resolved_path[MAXPATHLEN + 1];
+
+ if (id != NULL) {
+ intern = Z_DOMOBJ_P(id);
+diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c
+index 6c1da2761d..0f2b62ae20 100644
+--- a/ext/xmlreader/php_xmlreader.c
++++ b/ext/xmlreader/php_xmlreader.c
+@@ -1040,7 +1040,7 @@ PHP_METHOD(xmlreader, XML)
+ xmlreader_object *intern = NULL;
+ char *source, *uri = NULL, *encoding = NULL;
+ int resolved_path_len, ret = 0;
+- char *directory=NULL, resolved_path[MAXPATHLEN];
++ char *directory=NULL, resolved_path[MAXPATHLEN + 1];
+ xmlParserInputBufferPtr inputbfr;
+ xmlTextReaderPtr reader;
+
+diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
+index 520edfadbb..33047bb160 100644
+--- a/main/fopen_wrappers.c
++++ b/main/fopen_wrappers.c
+@@ -135,10 +135,10 @@ PHPAPI ZEND_INI_MH(OnUpdateBaseDir)
+ */
+ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path)
+ {
+- char resolved_name[MAXPATHLEN];
+- char resolved_basedir[MAXPATHLEN];
++ char resolved_name[MAXPATHLEN + 1];
++ char resolved_basedir[MAXPATHLEN + 1];
+ char local_open_basedir[MAXPATHLEN];
+- char path_tmp[MAXPATHLEN];
++ char path_tmp[MAXPATHLEN + 1];
+ char *path_file;
+ size_t resolved_basedir_len;
+ size_t resolved_name_len;
+--
+2.39.1
+
+From 2b9c9a8cb00914c08e34ee242d4aa3ba4aa74ef4 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Mon, 13 Feb 2023 11:46:47 +0100
+Subject: [PATCH 4/8] NEWS
+
+(cherry picked from commit 614468ce4056c0ef93aae09532dcffdf65b594b5)
+---
+ NEWS | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 1c00ef6357..ad57c5ccd5 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,14 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.0.28
++
++- Core:
++ . Fixed bug #81744 (Password_verify() always return true with some hash).
++ (CVE-2023-0567). (Tim Düsterhus)
++ . Fixed bug #81746 (1-byte array overrun in common path resolve code).
++ (CVE-2023-0568). (Niels Dossche)
++
+ Backported from 8.0.27
+
+ - PDO/SQLite:
+--
+2.39.1
+
diff --git a/php-cve-2023-0662.patch b/php-cve-2023-0662.patch
new file mode 100644
index 0000000..07361d1
--- /dev/null
+++ b/php-cve-2023-0662.patch
@@ -0,0 +1,148 @@
+From 1548e88ea16f68d15a71040c7fb6bff3874c5e32 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Thu, 19 Jan 2023 14:11:18 +0000
+Subject: [PATCH 5/8] Fix repeated warning for file uploads limit exceeding
+
+(cherry picked from commit 3a2fdef1ae38881110006616ee1f0534b082ca45)
+---
+ main/rfc1867.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index 27718e72a4..3f7a0c76f9 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -932,7 +932,10 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ skip_upload = 1;
+ } else if (upload_cnt <= 0) {
+ skip_upload = 1;
+- sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
++ if (upload_cnt == 0) {
++ --upload_cnt;
++ sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
++ }
+ }
+
+ /* Return with an error if the posted data is garbled */
+--
+2.39.1
+
+From 7d196fe1295491e624edf263525148c8c3bfd902 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Thu, 19 Jan 2023 14:31:25 +0000
+Subject: [PATCH 6/8] Introduce max_multipart_body_parts INI
+
+This fixes GHSA-54hq-v5wp-fqgv DOS vulnerabality by limitting number of
+parsed multipart body parts as currently all parts were always parsed.
+
+(cherry picked from commit 8ec78d28d20c82c75c4747f44c52601cfdb22516)
+---
+ main/main.c | 1 +
+ main/rfc1867.c | 11 +++++++++++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/main/main.c b/main/main.c
+index a3fc980b17..0cfdb91368 100644
+--- a/main/main.c
++++ b/main/main.c
+@@ -621,6 +621,7 @@ PHP_INI_BEGIN()
+ PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
+ PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
+ PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
++ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
+
+ STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
+ STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index 3f7a0c76f9..14813a300c 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -704,6 +704,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ void *event_extra_data = NULL;
+ unsigned int llen = 0;
+ int upload_cnt = INI_INT("max_file_uploads");
++ int body_parts_cnt = INI_INT("max_multipart_body_parts");
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
+ php_rfc1867_getword_t getword;
+ php_rfc1867_getword_conf_t getword_conf;
+@@ -725,6 +726,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ return;
+ }
+
++ if (body_parts_cnt < 0) {
++ body_parts_cnt = PG(max_input_vars) + upload_cnt;
++ }
++ int body_parts_limit = body_parts_cnt;
++
+ /* Get the boundary */
+ boundary = strstr(content_type_dup, "boundary");
+ if (!boundary) {
+@@ -809,6 +815,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ char *pair = NULL;
+ int end = 0;
+
++ if (--body_parts_cnt < 0) {
++ php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit);
++ goto fileupload_done;
++ }
++
+ while (isspace(*cd)) {
+ ++cd;
+ }
+--
+2.39.1
+
+From 7900df2bfa37eaf0217fd2d62f3418b0be096cba Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 14 Feb 2023 09:14:47 +0100
+Subject: [PATCH 7/8] NEWS
+
+(cherry picked from commit 472db3ee3a00ac00d36019eee0b3b7362334481c)
+---
+ NEWS | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index ad57c5ccd5..e59c43300a 100644
+--- a/NEWS
++++ b/NEWS
+@@ -9,6 +9,10 @@ Backported from 8.0.28
+ . Fixed bug #81746 (1-byte array overrun in common path resolve code).
+ (CVE-2023-0568). (Niels Dossche)
+
++- FPM:
++ . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart
++ request body). (CVE-2023-0662) (Jakub Zelenka)
++
+ Backported from 8.0.27
+
+ - PDO/SQLite:
+--
+2.39.1
+
+From 27d1f29635717f619267b5e2ebf87ec43faa18f0 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 14 Feb 2023 11:47:22 +0100
+Subject: [PATCH 8/8] fix NEWS, not FPM specific
+
+(cherry picked from commit c04f310440a906fc4ca885f4ecf6e3e4cd36edc7)
+---
+ NEWS | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index e59c43300a..47e9f89a64 100644
+--- a/NEWS
++++ b/NEWS
+@@ -8,8 +8,6 @@ Backported from 8.0.28
+ (CVE-2023-0567). (Tim Düsterhus)
+ . Fixed bug #81746 (1-byte array overrun in common path resolve code).
+ (CVE-2023-0568). (Niels Dossche)
+-
+-- FPM:
+ . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart
+ request body). (CVE-2023-0662) (Jakub Zelenka)
+
+--
+2.39.1
+
diff --git a/php-cve-2023-3247.patch b/php-cve-2023-3247.patch
new file mode 100644
index 0000000..54e8592
--- /dev/null
+++ b/php-cve-2023-3247.patch
@@ -0,0 +1,152 @@
+From a8cd8000fe5814302758a26f4ad4fd9d392c91e0 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Sun, 16 Apr 2023 15:05:03 +0200
+Subject: [PATCH] Fix missing randomness check and insufficient random bytes
+ for SOAP HTTP Digest
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If php_random_bytes_throw fails, the nonce will be uninitialized, but
+still sent to the server. The client nonce is intended to protect
+against a malicious server. See section 5.10 and 5.12 of RFC 7616 [1],
+and bullet point 2 below.
+
+Tim pointed out that even though it's the MD5 of the nonce that gets sent,
+enumerating 31 bits is trivial. So we have still a stack information leak
+of 31 bits.
+
+Furthermore, Tim found the following issues:
+* The small size of cnonce might cause the server to erroneously reject
+ a request due to a repeated (cnonce, nc) pair. As per the birthday
+ problem 31 bits of randomness will return a duplication with 50%
+ chance after less than 55000 requests and nc always starts counting at 1.
+* The cnonce is intended to protect the client and password against a
+ malicious server that returns a constant server nonce where the server
+ precomputed a rainbow table between passwords and correct client response.
+ As storage is fairly cheap, a server could precompute the client responses
+ for (a subset of) client nonces and still have a chance of reversing the
+ client response with the same probability as the cnonce duplication.
+
+ Precomputing the rainbow table for all 2^31 cnonces increases the rainbow
+ table size by factor 2 billion, which is infeasible. But precomputing it
+ for 2^14 cnonces only increases the table size by factor 16k and the server
+ would still have a 10% chance of successfully reversing a password with a
+ single client request.
+
+This patch fixes the issues by increasing the nonce size, and checking
+the return value of php_random_bytes_throw(). In the process we also get
+rid of the MD5 hashing of the nonce.
+
+[1] RFC 7616: https://www.rfc-editor.org/rfc/rfc7616
+
+Co-authored-by: Tim Düsterhus <timwolla@php.net>
+(cherry picked from commit 126d517ce240e9f638d9a5eaa509eaca49ef562a)
+(cherry picked from commit 0cfca9aa1395271833848daec0bace51d965531d)
+---
+ NEWS | 6 ++++++
+ ext/soap/php_http.c | 21 +++++++++++++--------
+ 2 files changed, 19 insertions(+), 8 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 47e9f89a646..ae5101b368e 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.0.29
++
++- Soap:
++ . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random
++ bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla)
++
+ Backported from 8.0.28
+
+ - Core:
+diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
+index 57754021b77..15b086e21c4 100644
+--- a/ext/soap/php_http.c
++++ b/ext/soap/php_http.c
+@@ -665,18 +665,23 @@ int make_http_soap_request(zval *this_ptr,
+ if ((digest = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest")-1)) != NULL) {
+ if (Z_TYPE_P(digest) == IS_ARRAY) {
+ char HA1[33], HA2[33], response[33], cnonce[33], nc[9];
+- zend_long nonce;
++ unsigned char nonce[16];
+ PHP_MD5_CTX md5ctx;
+ unsigned char hash[16];
+
+- php_random_bytes_throw(&nonce, sizeof(nonce));
+- nonce &= 0x7fffffff;
++ if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) {
++ ZEND_ASSERT(EG(exception));
++ php_stream_close(stream);
++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl")-1);
++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1);
++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy")-1);
++ smart_str_free(&soap_headers_z);
++ smart_str_free(&soap_headers);
++ return FALSE;
++ }
+
+- PHP_MD5Init(&md5ctx);
+- snprintf(cnonce, sizeof(cnonce), ZEND_LONG_FMT, nonce);
+- PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, strlen(cnonce));
+- PHP_MD5Final(hash, &md5ctx);
+- make_digest(cnonce, hash);
++ php_hash_bin2hex(cnonce, nonce, sizeof(nonce));
++ cnonce[32] = 0;
+
+ if ((tmp = zend_hash_str_find(Z_ARRVAL_P(digest), "nc", sizeof("nc")-1)) != NULL &&
+ Z_TYPE_P(tmp) == IS_LONG) {
+From 1563873cd3f1fbd2464d3521b699f14efce1db13 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 6 Jun 2023 18:05:22 +0200
+Subject: [PATCH] Fix GH-11382 add missing hash header for bin2hex
+
+(cherry picked from commit 40439039c224bb8cdebd1b7b3d03b8cc11e7cce7)
+---
+ ext/soap/php_http.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
+index 15b086e21c..6903a3b9c9 100644
+--- a/ext/soap/php_http.c
++++ b/ext/soap/php_http.c
+@@ -23,6 +23,7 @@
+ #include "ext/standard/base64.h"
+ #include "ext/standard/md5.h"
+ #include "ext/standard/php_random.h"
++#include "ext/hash/php_hash.h"
+
+ static char *get_http_header_value(char *headers, char *type);
+ static zend_string *get_http_body(php_stream *socketd, int close, char *headers);
+From 24d822d4e70431cc6dc795f7ff5193960f385c2f Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 15 Jun 2023 08:47:55 +0200
+Subject: [PATCH] add cve
+
+(cherry picked from commit f3021d66d7bb42d2578530cc94f9bde47e58eb10)
+---
+ NEWS | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/NEWS b/NEWS
+index ae5101b368..5f49a7ee04 100644
+--- a/NEWS
++++ b/NEWS
+@@ -5,7 +5,8 @@ Backported from 8.0.29
+
+ - Soap:
+ . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random
+- bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla)
++ bytes in HTTP Digest authentication for SOAP).
++ (CVE-2023-3247) (nielsdos, timwolla)
+
+ Backported from 8.0.28
+
+--
+2.40.1
+
diff --git a/php-cve-2023-3823.patch b/php-cve-2023-3823.patch
new file mode 100644
index 0000000..70829bf
--- /dev/null
+++ b/php-cve-2023-3823.patch
@@ -0,0 +1,91 @@
+From f8f433d0d8eaac21af4f4532496d33f9c2b381d6 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Mon, 10 Jul 2023 13:25:34 +0200
+Subject: [PATCH 1/5] Fix buffer mismanagement in phar_dir_read()
+
+Fixes GHSA-jqcx-ccgc-xwhv.
+
+(cherry picked from commit 80316123f3e9dcce8ac419bd9dd43546e2ccb5ef)
+(cherry picked from commit c398fe98c044c8e7c23135acdc38d4ef7bedc983)
+(cherry picked from commit 3f14261065e4c0552afa9cb16411475050a41c2c)
+---
+ ext/phar/dirstream.c | 15 ++++++++------
+ ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt | 27 +++++++++++++++++++++++++
+ 2 files changed, 36 insertions(+), 6 deletions(-)
+ create mode 100644 ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt
+
+diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c
+index 1ee886ec2f..66931b652c 100644
+--- a/ext/phar/dirstream.c
++++ b/ext/phar/dirstream.c
+@@ -92,25 +92,28 @@ static int phar_dir_seek(php_stream *stream, zend_off_t offset, int whence, zend
+ */
+ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count) /* {{{ */
+ {
+- size_t to_read;
+ HashTable *data = (HashTable *)stream->abstract;
+ zend_string *str_key;
+ zend_ulong unused;
+
++ if (count != sizeof(php_stream_dirent)) {
++ return -1;
++ }
++
+ if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key(data, &str_key, &unused)) {
+ return 0;
+ }
+
+ zend_hash_move_forward(data);
+- to_read = MIN(ZSTR_LEN(str_key), count);
+
+- if (to_read == 0 || count < ZSTR_LEN(str_key)) {
++ php_stream_dirent *dirent = (php_stream_dirent *) buf;
++
++ if (sizeof(dirent->d_name) <= ZSTR_LEN(str_key)) {
+ return 0;
+ }
+
+- memset(buf, 0, sizeof(php_stream_dirent));
+- memcpy(((php_stream_dirent *) buf)->d_name, ZSTR_VAL(str_key), to_read);
+- ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0';
++ memset(dirent, 0, sizeof(php_stream_dirent));
++ PHP_STRLCPY(dirent->d_name, ZSTR_VAL(str_key), sizeof(dirent->d_name), ZSTR_LEN(str_key));
+
+ return sizeof(php_stream_dirent);
+ }
+diff --git a/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt
+new file mode 100644
+index 0000000000..4e12f05fb6
+--- /dev/null
++++ b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt
+@@ -0,0 +1,27 @@
++--TEST--
++GHSA-jqcx-ccgc-xwhv (Buffer overflow and overread in phar_dir_read())
++--SKIPIF--
++<?php if (!extension_loaded("phar")) die("skip"); ?>
++--INI--
++phar.readonly=0
++--FILE--
++<?php
++$phar = new Phar(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar');
++$phar->startBuffering();
++$phar->addFromString(str_repeat('A', PHP_MAXPATHLEN - 1), 'This is the content of file 1.');
++$phar->addFromString(str_repeat('B', PHP_MAXPATHLEN - 1).'C', 'This is the content of file 2.');
++$phar->stopBuffering();
++
++$handle = opendir('phar://' . __DIR__ . '/GHSA-jqcx-ccgc-xwhv.phar');
++var_dump(strlen(readdir($handle)));
++// Must not be a string of length PHP_MAXPATHLEN+1
++var_dump(readdir($handle));
++closedir($handle);
++?>
++--CLEAN--
++<?php
++unlink(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar');
++?>
++--EXPECTF--
++int(%d)
++bool(false)
+--
+2.41.0
+
diff --git a/php-cve-2023-3824.patch b/php-cve-2023-3824.patch
new file mode 100644
index 0000000..e807dd6
--- /dev/null
+++ b/php-cve-2023-3824.patch
@@ -0,0 +1,714 @@
+From d7de6908dfc8774e86a54100ad4e2ee810426001 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Sat, 15 Jul 2023 17:33:52 +0200
+Subject: [PATCH 2/5] Sanitize libxml2 globals before parsing
+
+Fixes GHSA-3qrf-m4j2-pcrr.
+
+To parse a document with libxml2, you first need to create a parsing context.
+The parsing context contains parsing options (e.g. XML_NOENT to substitute
+entities) that the application (in this case PHP) can set.
+Unfortunately, libxml2 also supports providing default set options.
+For example, if you call xmlSubstituteEntitiesDefault(1) then the XML_NOENT
+option will be added to the parsing options every time you create a parsing
+context **even if the application never requested XML_NOENT**.
+
+Third party extensions can override these globals, in particular the
+substitute entity global. This causes entity substitution to be
+unexpectedly active.
+
+Fix it by setting the parsing options to a sane known value.
+For API calls that depend on global state we introduce
+PHP_LIBXML_SANITIZE_GLOBALS() and PHP_LIBXML_RESTORE_GLOBALS().
+For other APIs that work directly with a context we introduce
+php_libxml_sanitize_parse_ctxt_options().
+
+(cherry picked from commit c283c3ab0ba45d21b2b8745c1f9c7cbfe771c975)
+(cherry picked from commit b3758bd21223b97c042cae7bd26a66cde081ea98)
+(cherry picked from commit 4fb61f06b1aff89a4d7e548c37ffa5bf573270c3)
+---
+ ext/dom/document.c | 15 ++++++++
+ ext/dom/documentfragment.c | 2 ++
+ ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++
+ ext/libxml/php_libxml.h | 36 +++++++++++++++++++
+ ext/simplexml/simplexml.c | 6 ++++
+ ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++
+ ext/soap/php_xml.c | 2 ++
+ ext/xml/compat.c | 2 ++
+ ext/xmlreader/php_xmlreader.c | 9 +++++
+ ...xml_global_state_entity_loader_bypass.phpt | 35 ++++++++++++++++++
+ ext/xsl/xsltprocessor.c | 9 +++--
+ 11 files changed, 183 insertions(+), 5 deletions(-)
+ create mode 100644 ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+ create mode 100644 ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+ create mode 100644 ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+
+diff --git a/ext/dom/document.c b/ext/dom/document.c
+index c212faa695..b0eed5820b 100644
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -1438,6 +1438,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so
+ options |= XML_PARSE_NOBLANKS;
+ }
+
++ php_libxml_sanitize_parse_ctxt_options(ctxt);
+ xmlCtxtUseOptions(ctxt, options);
+
+ ctxt->recovery = recover;
+@@ -1735,7 +1736,9 @@ PHP_FUNCTION(dom_document_xinclude)
+
+ DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
+
++ PHP_LIBXML_SANITIZE_GLOBALS(xinclude);
+ err = xmlXIncludeProcessFlags(docp, (int)flags);
++ PHP_LIBXML_RESTORE_GLOBALS(xinclude);
+
+ /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
+ are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
+@@ -1774,6 +1777,7 @@ PHP_FUNCTION(dom_document_validate)
+
+ DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
+
++ PHP_LIBXML_SANITIZE_GLOBALS(validate);
+ cvp = xmlNewValidCtxt();
+
+ cvp->userData = NULL;
+@@ -1785,6 +1789,7 @@ PHP_FUNCTION(dom_document_validate)
+ } else {
+ RETVAL_FALSE;
+ }
++ PHP_LIBXML_RESTORE_GLOBALS(validate);
+
+ xmlFreeValidCtxt(cvp);
+
+@@ -1818,14 +1823,18 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
+
+ DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
+
++ PHP_LIBXML_SANITIZE_GLOBALS(new_parser_ctxt);
++
+ switch (type) {
+ case DOM_LOAD_FILE:
+ if (CHECK_NULL_PATH(source, source_len)) {
++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
+ php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
+ RETURN_FALSE;
+ }
+ valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
+ if (!valid_file) {
++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
+ php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
+ RETURN_FALSE;
+ }
+@@ -1846,6 +1855,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
+ parser);
+ sptr = xmlSchemaParse(parser);
+ xmlSchemaFreeParserCtxt(parser);
++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt);
+ if (!sptr) {
+ php_error_docref(NULL, E_WARNING, "Invalid Schema");
+ RETURN_FALSE;
+@@ -1866,11 +1876,13 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
+ }
+ #endif
+
++ PHP_LIBXML_SANITIZE_GLOBALS(validate);
+ xmlSchemaSetValidOptions(vptr, valid_opts);
+ xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
+ is_valid = xmlSchemaValidateDoc(vptr, docp);
+ xmlSchemaFree(sptr);
+ xmlSchemaFreeValidCtxt(vptr);
++ PHP_LIBXML_RESTORE_GLOBALS(validate);
+
+ if (is_valid == 0) {
+ RETURN_TRUE;
+@@ -1940,12 +1952,14 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
+ return;
+ }
+
++ PHP_LIBXML_SANITIZE_GLOBALS(parse);
+ xmlRelaxNGSetParserErrors(parser,
+ (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
+ (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
+ parser);
+ sptr = xmlRelaxNGParse(parser);
+ xmlRelaxNGFreeParserCtxt(parser);
++ PHP_LIBXML_RESTORE_GLOBALS(parse);
+ if (!sptr) {
+ php_error_docref(NULL, E_WARNING, "Invalid RelaxNG");
+ RETURN_FALSE;
+@@ -2045,6 +2059,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
+ ctxt->sax->error = php_libxml_ctx_error;
+ ctxt->sax->warning = php_libxml_ctx_warning;
+ }
++ php_libxml_sanitize_parse_ctxt_options(ctxt);
+ if (options) {
+ htmlCtxtUseOptions(ctxt, (int)options);
+ }
+diff --git a/ext/dom/documentfragment.c b/ext/dom/documentfragment.c
+index 87cb691501..b7ecfdc14b 100644
+--- a/ext/dom/documentfragment.c
++++ b/ext/dom/documentfragment.c
+@@ -134,7 +134,9 @@ PHP_METHOD(domdocumentfragment, appendXML) {
+ }
+
+ if (data) {
++ PHP_LIBXML_SANITIZE_GLOBALS(parse);
+ err = xmlParseBalancedChunkMemory(nodep->doc, NULL, NULL, 0, (xmlChar *) data, &lst);
++ PHP_LIBXML_RESTORE_GLOBALS(parse);
+ if (err != 0) {
+ RETURN_FALSE;
+ }
+diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+new file mode 100644
+index 0000000000..b28afd4694
+--- /dev/null
++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -0,0 +1,36 @@
++--TEST--
++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
++--SKIPIF--
++<?php
++if (!extension_loaded('libxml')) die('skip libxml extension not available');
++if (!extension_loaded('dom')) die('skip dom extension not available');
++if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++?>
++--FILE--
++<?php
++
++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>";
++
++libxml_use_internal_errors(true);
++
++function parseXML($xml) {
++ $doc = new DOMDocument();
++ @$doc->loadXML($xml);
++ $doc->createDocumentFragment()->appendXML("&bork;");
++ foreach (libxml_get_errors() as $error) {
++ var_dump(trim($error->message));
++ }
++}
++
++parseXML($xml);
++zend_test_override_libxml_global_state();
++parseXML($xml);
++
++echo "Done\n";
++
++?>
++--EXPECT--
++string(25) "Entity 'bork' not defined"
++string(25) "Entity 'bork' not defined"
++string(25) "Entity 'bork' not defined"
++Done
+diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h
+index f7aa726d88..371b4eecc5 100644
+--- a/ext/libxml/php_libxml.h
++++ b/ext/libxml/php_libxml.h
+@@ -122,6 +122,42 @@ PHP_LIBXML_API void php_libxml_shutdown(void);
+ ZEND_TSRMLS_CACHE_EXTERN()
+ #endif
+
++/* Other extension may override the global state options, these global options
++ * are copied initially to ctxt->options. Set the options to a known good value.
++ * See libxml2 globals.c and parserInternals.c.
++ * The unique_name argument allows multiple sanitizes and restores within the
++ * same function, even nested is necessary. */
++#define PHP_LIBXML_SANITIZE_GLOBALS(unique_name) \
++ int xml_old_loadsubset_##unique_name = xmlLoadExtDtdDefaultValue; \
++ xmlLoadExtDtdDefaultValue = 0; \
++ int xml_old_validate_##unique_name = xmlDoValidityCheckingDefaultValue; \
++ xmlDoValidityCheckingDefaultValue = 0; \
++ int xml_old_pedantic_##unique_name = xmlPedanticParserDefault(0); \
++ int xml_old_substitute_##unique_name = xmlSubstituteEntitiesDefault(0); \
++ int xml_old_linenrs_##unique_name = xmlLineNumbersDefault(0); \
++ int xml_old_blanks_##unique_name = xmlKeepBlanksDefault(1);
++
++#define PHP_LIBXML_RESTORE_GLOBALS(unique_name) \
++ xmlLoadExtDtdDefaultValue = xml_old_loadsubset_##unique_name; \
++ xmlDoValidityCheckingDefaultValue = xml_old_validate_##unique_name; \
++ (void) xmlPedanticParserDefault(xml_old_pedantic_##unique_name); \
++ (void) xmlSubstituteEntitiesDefault(xml_old_substitute_##unique_name); \
++ (void) xmlLineNumbersDefault(xml_old_linenrs_##unique_name); \
++ (void) xmlKeepBlanksDefault(xml_old_blanks_##unique_name);
++
++/* Alternative for above, working directly on the context and not setting globals.
++ * Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */
++static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt)
++{
++ ctxt->loadsubset = 0;
++ ctxt->validate = 0;
++ ctxt->pedantic = 0;
++ ctxt->replaceEntities = 0;
++ ctxt->linenumbers = 0;
++ ctxt->keepBlanks = 1;
++ ctxt->options = 0;
++}
++
+ #else /* HAVE_LIBXML */
+ #define libxml_module_ptr NULL
+ #endif
+diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
+index 341daed0ee..c2b0230e19 100644
+--- a/ext/simplexml/simplexml.c
++++ b/ext/simplexml/simplexml.c
+@@ -2217,7 +2217,9 @@ PHP_FUNCTION(simplexml_load_file)
+ RETURN_FALSE;
+ }
+
++ PHP_LIBXML_SANITIZE_GLOBALS(read_file);
+ docp = xmlReadFile(filename, NULL, (int)options);
++ PHP_LIBXML_RESTORE_GLOBALS(read_file);
+
+ if (!docp) {
+ RETURN_FALSE;
+@@ -2271,7 +2273,9 @@ PHP_FUNCTION(simplexml_load_string)
+ RETURN_FALSE;
+ }
+
++ PHP_LIBXML_SANITIZE_GLOBALS(read_memory);
+ docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
++ PHP_LIBXML_RESTORE_GLOBALS(read_memory);
+
+ if (!docp) {
+ RETURN_FALSE;
+@@ -2321,7 +2325,9 @@ SXE_METHOD(__construct)
+ return;
+ }
+
++ PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory);
+ docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
++ PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);
+
+ if (!docp) {
+ ((php_libxml_node_object *)sxe)->document = NULL;
+diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+new file mode 100644
+index 0000000000..2152e01232
+--- /dev/null
++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -0,0 +1,36 @@
++--TEST--
++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
++--SKIPIF--
++<?php
++if (!extension_loaded('libxml')) die('skip libxml extension not available');
++if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
++if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++?>
++--FILE--
++<?php
++
++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>";
++
++libxml_use_internal_errors(true);
++zend_test_override_libxml_global_state();
++
++echo "--- String test ---\n";
++simplexml_load_string($xml);
++echo "--- Constructor test ---\n";
++new SimpleXMLElement($xml);
++echo "--- File test ---\n";
++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml);
++simplexml_load_file("libxml_global_state_entity_loader_bypass.tmp");
++
++echo "Done\n";
++
++?>
++--CLEAN--
++<?php
++@unlink("libxml_global_state_entity_loader_bypass.tmp");
++?>
++--EXPECT--
++--- String test ---
++--- Constructor test ---
++--- File test ---
++Done
+diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
+index 1ac684eb81..053960c559 100644
+--- a/ext/soap/php_xml.c
++++ b/ext/soap/php_xml.c
+@@ -94,6 +94,7 @@ xmlDocPtr soap_xmlParseFile(const char *filename)
+ if (ctxt) {
+ zend_bool old;
+
++ php_libxml_sanitize_parse_ctxt_options(ctxt);
+ ctxt->keepBlanks = 0;
+ ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
+ ctxt->sax->comment = soap_Comment;
+@@ -144,6 +145,7 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
+ if (ctxt) {
+ zend_bool old;
+
++ php_libxml_sanitize_parse_ctxt_options(ctxt);
+ ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
+ ctxt->sax->comment = soap_Comment;
+ ctxt->sax->warning = NULL;
+diff --git a/ext/xml/compat.c b/ext/xml/compat.c
+index ef83485722..c55047215b 100644
+--- a/ext/xml/compat.c
++++ b/ext/xml/compat.c
+@@ -19,6 +19,7 @@
+ #include "php.h"
+ #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT)
+ #include "expat_compat.h"
++#include "ext/libxml/php_libxml.h"
+
+ typedef struct _php_xml_ns {
+ xmlNsPtr nsptr;
+@@ -473,6 +474,7 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m
+ parser->parser->charset = XML_CHAR_ENCODING_NONE;
+ #endif
+
++ php_libxml_sanitize_parse_ctxt_options(parser->parser);
+ #if LIBXML_VERSION >= 20703
+ xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX);
+ #endif
+diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c
+index 0f2b62ae20..f0fd013ff9 100644
+--- a/ext/xmlreader/php_xmlreader.c
++++ b/ext/xmlreader/php_xmlreader.c
+@@ -301,6 +301,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz
+ return NULL;
+ }
+
++ PHP_LIBXML_SANITIZE_GLOBALS(parse);
+ if (error_func || warn_func) {
+ xmlRelaxNGSetParserErrors(parser,
+ (xmlRelaxNGValidityErrorFunc) error_func,
+@@ -309,6 +310,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz
+ }
+ sptr = xmlRelaxNGParse(parser);
+ xmlRelaxNGFreeParserCtxt(parser);
++ PHP_LIBXML_RESTORE_GLOBALS(parse);
+
+ return sptr;
+ }
+@@ -881,7 +883,9 @@ PHP_METHOD(xmlreader, open)
+ valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
+
+ if (valid_file) {
++ PHP_LIBXML_SANITIZE_GLOBALS(reader_for_file);
+ reader = xmlReaderForFile(valid_file, encoding, options);
++ PHP_LIBXML_RESTORE_GLOBALS(reader_for_file);
+ }
+
+ if (reader == NULL) {
+@@ -959,7 +963,9 @@ PHP_METHOD(xmlreader, setSchema)
+
+ intern = Z_XMLREADER_P(id);
+ if (intern && intern->ptr) {
++ PHP_LIBXML_SANITIZE_GLOBALS(schema);
+ retval = xmlTextReaderSchemaValidate(intern->ptr, source);
++ PHP_LIBXML_RESTORE_GLOBALS(schema);
+
+ if (retval == 0) {
+ RETURN_TRUE;
+@@ -1079,6 +1085,7 @@ PHP_METHOD(xmlreader, XML)
+ }
+ uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
+ }
++ PHP_LIBXML_SANITIZE_GLOBALS(text_reader);
+ reader = xmlNewTextReader(inputbfr, uri);
+
+ if (reader != NULL) {
+@@ -1099,9 +1106,11 @@ PHP_METHOD(xmlreader, XML)
+ xmlFree(uri);
+ }
+
++ PHP_LIBXML_RESTORE_GLOBALS(text_reader);
+ return;
+ }
+ }
++ PHP_LIBXML_RESTORE_GLOBALS(text_reader);
+ }
+
+ if (uri) {
+diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+new file mode 100644
+index 0000000000..e9ffb04c2b
+--- /dev/null
++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -0,0 +1,35 @@
++--TEST--
++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
++--SKIPIF--
++<?php
++if (!extension_loaded('libxml')) die('skip libxml extension not available');
++if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available');
++if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++?>
++--FILE--
++<?php
++
++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>";
++
++libxml_use_internal_errors(true);
++zend_test_override_libxml_global_state();
++
++echo "--- String test ---\n";
++$reader = XMLReader::xml($xml);
++$reader->read();
++echo "--- File test ---\n";
++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml);
++$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp");
++$reader->read();
++
++echo "Done\n";
++
++?>
++--CLEAN--
++<?php
++@unlink("libxml_global_state_entity_loader_bypass.tmp");
++?>
++--EXPECT--
++--- String test ---
++--- File test ---
++Done
+diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
+index 9948d6f0b3..7bbe640a5c 100644
+--- a/ext/xsl/xsltprocessor.c
++++ b/ext/xsl/xsltprocessor.c
+@@ -396,7 +396,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
+ xmlDoc *doc = NULL, *newdoc = NULL;
+ xsltStylesheetPtr sheetp, oldsheetp;
+ xsl_object *intern;
+- int prevSubstValue, prevExtDtdValue, clone_docu = 0;
++ int clone_docu = 0;
+ xmlNode *nodep = NULL;
+ zend_object_handlers *std_hnd;
+ zval *cloneDocu, member, rv;
+@@ -419,13 +419,12 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
+ stylesheet document otherwise the node proxies will be a mess */
+ newdoc = xmlCopyDoc(doc, 1);
+ xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
+- prevSubstValue = xmlSubstituteEntitiesDefault(1);
+- prevExtDtdValue = xmlLoadExtDtdDefaultValue;
++ PHP_LIBXML_SANITIZE_GLOBALS(parse);
++ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+
+ sheetp = xsltParseStylesheetDoc(newdoc);
+- xmlSubstituteEntitiesDefault(prevSubstValue);
+- xmlLoadExtDtdDefaultValue = prevExtDtdValue;
++ PHP_LIBXML_RESTORE_GLOBALS(parse);
+
+ if (!sheetp) {
+ xmlFreeDoc(newdoc);
+--
+2.41.0
+
+From 3535016313ece1e12ffd5d9fc2f39478941be3d8 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 1 Aug 2023 07:37:25 +0200
+Subject: [PATCH 3/5] backport zend_test changes
+ (zend_test_override_libxml_global_state)
+
+(cherry picked from commit 24e669e790e6aebd219c9a9fa19017455c8646b4)
+(cherry picked from commit 79a97d0e2b93c40c3728d587046266989c5acc42)
+---
+ ...xml_global_state_entity_loader_bypass.phpt | 1 +
+ ...xml_global_state_entity_loader_bypass.phpt | 1 +
+ ...xml_global_state_entity_loader_bypass.phpt | 5 +++--
+ ext/zend_test/test.c | 22 +++++++++++++++++++
+ 4 files changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+index b28afd4694..7fc2a249ac 100644
+--- a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('dom')) die('skip dom extension not available');
+ if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+ <?php
+diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+index 2152e01232..54f9d4941e 100644
+--- a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
+ if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+ <?php
+diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+index e9ffb04c2b..b0120b325e 100644
+--- a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available');
+ if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+ <?php
+@@ -15,11 +16,11 @@ libxml_use_internal_errors(true);
+ zend_test_override_libxml_global_state();
+
+ echo "--- String test ---\n";
+-$reader = XMLReader::xml($xml);
++$reader = @XMLReader::xml($xml);
+ $reader->read();
+ echo "--- File test ---\n";
+ file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml);
+-$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp");
++$reader = @XMLReader::open("libxml_global_state_entity_loader_bypass.tmp");
+ $reader->read();
+
+ echo "Done\n";
+diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
+index 4a7fe540fb..611bc9b68c 100644
+--- a/ext/zend_test/test.c
++++ b/ext/zend_test/test.c
+@@ -25,6 +25,11 @@
+ #include "ext/standard/info.h"
+ #include "php_test.h"
+
++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
++# include <libxml/globals.h>
++# include <libxml/parser.h>
++#endif
++
+ static zend_class_entry *zend_test_interface;
+ static zend_class_entry *zend_test_class;
+ static zend_class_entry *zend_test_trait;
+@@ -44,6 +49,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_leak_variable, 0, 0, 1)
+ ZEND_ARG_INFO(0, variable)
+ ZEND_END_ARG_INFO()
+
++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
++static ZEND_FUNCTION(zend_test_override_libxml_global_state)
++{
++ ZEND_PARSE_PARAMETERS_NONE();
++
++ xmlLoadExtDtdDefaultValue = 1;
++ xmlDoValidityCheckingDefaultValue = 1;
++ (void) xmlPedanticParserDefault(1);
++ (void) xmlSubstituteEntitiesDefault(1);
++ (void) xmlLineNumbersDefault(1);
++ (void) xmlKeepBlanksDefault(0);
++}
++#endif
++
+ ZEND_FUNCTION(zend_test_func)
+ {
+ /* dummy */
+@@ -251,6 +270,9 @@ const zend_function_entry zend_test_functions[] = {
+ ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string)
+ ZEND_FE(zend_leak_bytes, NULL)
+ ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable)
++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
++ ZEND_FE(zend_test_override_libxml_global_state, NULL)
++#endif
+ ZEND_FE_END
+ };
+
+--
+2.41.0
+
+From 26d70866843598f4a2ed94b01999b38e1d7c0e97 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 1 Aug 2023 15:45:24 +0200
+Subject: [PATCH 4/5] adapt to 7.2
+
+---
+ ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt | 1 -
+ .../tests/libxml_global_state_entity_loader_bypass.phpt | 1 -
+ .../tests/libxml_global_state_entity_loader_bypass.phpt | 1 -
+ ext/zend_test/test.c | 2 --
+ 4 files changed, 5 deletions(-)
+
+diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+index 7fc2a249ac..25499006d9 100644
+--- a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ <?php
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('dom')) die('skip dom extension not available');
+-if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
+ if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+index 54f9d4941e..e09ecb5d72 100644
+--- a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ <?php
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
+-if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
+ if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+index b0120b325e..9824e10603 100644
+--- a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
+@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass)
+ <?php
+ if (!extension_loaded('libxml')) die('skip libxml extension not available');
+ if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available');
+-if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
+ if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows');
+ ?>
+ --FILE--
+diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
+index 611bc9b68c..51818083d9 100644
+--- a/ext/zend_test/test.c
++++ b/ext/zend_test/test.c
+@@ -52,8 +52,6 @@ ZEND_END_ARG_INFO()
+ #if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
+ static ZEND_FUNCTION(zend_test_override_libxml_global_state)
+ {
+- ZEND_PARSE_PARAMETERS_NONE();
+-
+ xmlLoadExtDtdDefaultValue = 1;
+ xmlDoValidityCheckingDefaultValue = 1;
+ (void) xmlPedanticParserDefault(1);
+--
+2.41.0
+
+From 79c0bf87711036b83f8ee1723c034ccc839d847b Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 1 Aug 2023 07:22:33 +0200
+Subject: [PATCH 5/5] NEWS
+
+(cherry picked from commit ef1d507acf7be23d7624dc3c891683b2218feb51)
+(cherry picked from commit 3cf7c2b10e577136b267f2d90bfdff6743271c5c)
+---
+ NEWS | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 5f49a7ee04..286f3df0f4 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,16 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.0.30
++
++- Libxml:
++ . Fixed bug GHSA-3qrf-m4j2-pcrr (Security issue with external entity loading
++ in XML without enabling it). (CVE-2023-3823) (nielsdos, ilutov)
++
++- Phar:
++ . Fixed bug GHSA-jqcx-ccgc-xwhv (Buffer mismanagement in phar_dir_read()).
++ (CVE-2023-3824) (nielsdos)
++
+ Backported from 8.0.29
+
+ - Soap:
+--
+2.41.0
+
diff --git a/php-cve-2024-11233.patch b/php-cve-2024-11233.patch
new file mode 100644
index 0000000..119dc2e
--- /dev/null
+++ b/php-cve-2024-11233.patch
@@ -0,0 +1,158 @@
+From 0a651c02701268532a9754542f629af85e28ae02 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 6/9] 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)
+(cherry picked from commit 2cee10a1206f5bc7724232d3988be2cfcb0bc9df)
+(cherry picked from commit 44a5975f83a02eb8169d12af912e6222b28216d0)
+(cherry picked from commit 7065fa31a468139f07b40f7036ce4761037dafd2)
+---
+ 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 03e5e11df8..26850c46a8 100644
+--- a/ext/standard/filters.c
++++ b/ext/standard/filters.c
+@@ -1122,6 +1122,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;
+@@ -1135,15 +1138,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 0000000000..8fdcce8ff2
+--- /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
+
+From d149a44b005e0d24208b0bd0f7179dfbbfffefb1 Mon Sep 17 00:00:00 2001
+From: "Christoph M. Becker" <cmbecker69@gmx.de>
+Date: Mon, 8 Jun 2020 23:19:43 +0200
+Subject: [PATCH 7/9] Fix #74267: segfault with streams and invalid data
+
+If the current character is a line break character, it cannot be a tab
+or space character, so we would always fail with an invalid sequence
+error. Obviously, these `scan_stat == 4` conditions are meant to be
+exclusive.
+
+Furthermore, if `in_pp == NULL || in_left_p == NULL` is true, we hit a
+segfault if we are not returning right away. Obviously, the additional
+constraints don't make sense, so we remove them.
+
+(cherry picked from commit 12c59f6660706321f9d42c55421ff6864439c8b7)
+---
+ ext/standard/filters.c | 7 +++----
+ ext/standard/tests/filters/bug74267.phpt | 26 ++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 4 deletions(-)
+ create mode 100644 ext/standard/tests/filters/bug74267.phpt
+
+diff --git a/ext/standard/filters.c b/ext/standard/filters.c
+index 26850c46a8..2b58c65ea5 100644
+--- a/ext/standard/filters.c
++++ b/ext/standard/filters.c
+@@ -788,7 +788,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
+ lb_ptr = inst->lb_ptr;
+ lb_cnt = inst->lb_cnt;
+
+- if ((in_pp == NULL || in_left_p == NULL) && (lb_ptr >=lb_cnt)) {
++ if (in_pp == NULL || in_left_p == NULL) {
+ return PHP_CONV_ERR_SUCCESS;
+ }
+
+@@ -1016,7 +1016,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
+ lb_ptr = inst->lb_ptr;
+ lb_cnt = inst->lb_cnt;
+
+- if ((in_pp == NULL || in_left_p == NULL) && lb_cnt == lb_ptr) {
++ if (in_pp == NULL || in_left_p == NULL) {
+ if (inst->scan_stat != 0) {
+ return PHP_CONV_ERR_UNEXPECTED_EOS;
+ }
+@@ -1113,8 +1113,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
+ *ps == (unsigned char)inst->lbchars[lb_cnt]) {
+ lb_cnt++;
+ scan_stat = 5;
+- }
+- if (*ps != '\t' && *ps != ' ') {
++ } else if (*ps != '\t' && *ps != ' ') {
+ err = PHP_CONV_ERR_INVALID_SEQ;
+ goto out;
+ }
+diff --git a/ext/standard/tests/filters/bug74267.phpt b/ext/standard/tests/filters/bug74267.phpt
+new file mode 100644
+index 0000000000..17d7996b7f
+--- /dev/null
++++ b/ext/standard/tests/filters/bug74267.phpt
+@@ -0,0 +1,26 @@
++--TEST--
++Bug #74267 (segfault with streams and invalid data)
++--FILE--
++<?php
++$stream = fopen('php://memory', 'w');
++stream_filter_append($stream, 'convert.quoted-printable-decode', STREAM_FILTER_WRITE, ['line-break-chars' => "\r\n"]);
++
++$lines = [
++ "\r\n",
++ " -=()\r\n",
++ " -=\r\n",
++ "\r\n"
++ ];
++
++foreach ($lines as $line) {
++ fwrite($stream, $line);
++}
++
++fclose($stream);
++echo "done\n";
++?>
++--EXPECTF--
++Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d
++
++Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d
++done
+--
+2.47.0
+
diff --git a/php-cve-2024-11234.patch b/php-cve-2024-11234.patch
new file mode 100644
index 0000000..7106136
--- /dev/null
+++ b/php-cve-2024-11234.patch
@@ -0,0 +1,97 @@
+From 11787051a17d2fcea427cd66c3fcc5e99ab94a03 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Fri, 8 Nov 2024 23:43:47 +0100
+Subject: [PATCH 4/9] Fix GHSA-c5f2-jwm7-mmq2: stream HTTP fulluri CRLF
+ injection
+
+(cherry picked from commit 426a6d4539ebee34879ac5de857036bb6ff0e732)
+(cherry picked from commit bc1f192102dd8cbda028e40aa31604c4885d387c)
+(cherry picked from commit 8d130e16fbfda7d154fedfa0f1ff1d5ad5e26815)
+(cherry picked from commit 494de65139592da0e5e5b6fdf198c2f9c762f4d6)
+(cherry picked from commit dcb89ed9d0217510f3906ce0c517f704e6bd80dc)
+---
+ 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 be23679d2d..e125364923 100644
+--- a/ext/standard/http_fopen_wrapper.c
++++ b/ext/standard/http_fopen_wrapper.c
+@@ -176,6 +176,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 && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
+ /* choose default ports */
+ if (use_ssl && resource->port == 0)
+@@ -195,6 +200,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);
++ efree(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
+@@ -375,12 +387,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 0000000000..6e68f67654
+--- /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
+
diff --git a/php-cve-2024-11236.patch b/php-cve-2024-11236.patch
new file mode 100644
index 0000000..1122989
--- /dev/null
+++ b/php-cve-2024-11236.patch
@@ -0,0 +1,150 @@
+From c6ee9a7d0385e4cd6cf9dcd0104dd6714e2a968d 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/9] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the dblib
+ quoter causing OOB writes
+
+(cherry picked from commit d9baa9fed8c3ba692a36b388c0c7762e5102e2e0)
+(cherry picked from commit 5d9e54065ed18c51e4f25d8900635f90810c7394)
+(cherry picked from commit 97546df8d6900b115536c17af9213f1da837b82e)
+(cherry picked from commit 5e7cd3e7ed7c894550ca35514708ffe1874a31ad)
+---
+ 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 13526092ea..6fa650e4da 100644
+--- a/ext/pdo_dblib/dblib_driver.c
++++ b/ext/pdo_dblib/dblib_driver.c
+@@ -156,6 +156,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) {
+@@ -170,7 +171,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;
+ }
+
+@@ -178,6 +179,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 0000000000..431c61951e
+--- /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 8a4f389396493a43f9de9ba48920b6a82b6d1370 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/9] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the firebird
+ quoter causing OOB writes
+
+(cherry picked from commit 69c5f68fdc3deed9ebce2cc44b4bf5e0c47cd28f)
+(cherry picked from commit b4f73be75dbdde970a18cc7a636898b10400fb3f)
+(cherry picked from commit 0530cbfe5c3044537de52d8382eba5d69dbac726)
+(cherry picked from commit 72d4c4e435544c2d87d634188d480099345b601b)
+---
+ 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 1e2e7746fa..b238ea630e 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -243,7 +243,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;
+
+@@ -258,6 +258,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
+
+From ff868946218d6d1661a0c35757e2058cb3ed23ec Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Fri, 22 Nov 2024 15:24:16 +0100
+Subject: [PATCH 3/9] backport ZSTR_MAX_LEN
+
+(cherry picked from commit 37056ad634d9c44bac0d6c8e730eafaec1344840)
+---
+ Zend/zend_string.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/Zend/zend_string.h b/Zend/zend_string.h
+index 784b88ea6a..5f7a9ea2b3 100644
+--- a/Zend/zend_string.h
++++ b/Zend/zend_string.h
+@@ -74,6 +74,9 @@ END_EXTERN_C()
+
+ #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
+
++#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
++#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
++
+ #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
+ (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
+ GC_REFCOUNT(str) = 1; \
+--
+2.47.0
+
diff --git a/php-cve-2024-2756.patch b/php-cve-2024-2756.patch
new file mode 100644
index 0000000..6e13a30
--- /dev/null
+++ b/php-cve-2024-2756.patch
@@ -0,0 +1,197 @@
+From c213de619a532d35e8f7abe4a245433dbf21c960 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Sun, 17 Mar 2024 21:04:47 +0100
+Subject: [PATCH 1/4] Fix GHSA-wpj3-hf5j-x4v4: __Host-/__Secure- cookie bypass
+ due to partial CVE-2022-31629 fix
+
+The check happened too early as later code paths may perform more
+mangling rules. Move the check downwards right before adding the actual
+variable.
+
+(cherry picked from commit 093c08af25fb323efa0c8e6154aa9fdeae3d3b53)
+(cherry picked from commit 2e07a3acd7a6b53c55325b94bed97748d7697b53)
+(cherry picked from commit a6c1c62a25ac23b08a86af11d68f0e2eaafc102b)
+(cherry picked from commit 46b570a1e4aeb4a414898fcc09503ac388d16256)
+---
+ ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt | 63 +++++++++++++++++++++
+ main/php_variables.c | 41 +++++++++-----
+ 2 files changed, 90 insertions(+), 14 deletions(-)
+ create mode 100644 ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt
+
+diff --git a/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt
+new file mode 100644
+index 0000000000..77fcb68089
+--- /dev/null
++++ b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt
+@@ -0,0 +1,63 @@
++--TEST--
++ghsa-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix)
++--COOKIE--
++..Host-test=ignore_1;
++._Host-test=ignore_2;
++.[Host-test=ignore_3;
++_.Host-test=ignore_4;
++__Host-test=ignore_5;
++_[Host-test=ignore_6;
++[.Host-test=ignore_7;
++[_Host-test=ignore_8;
++[[Host-test=ignore_9;
++..Host-test[]=ignore_10;
++._Host-test[]=ignore_11;
++.[Host-test[]=ignore_12;
++_.Host-test[]=ignore_13;
++__Host-test[]=legitimate_14;
++_[Host-test[]=legitimate_15;
++[.Host-test[]=ignore_16;
++[_Host-test[]=ignore_17;
++[[Host-test[]=ignore_18;
++..Secure-test=ignore_1;
++._Secure-test=ignore_2;
++.[Secure-test=ignore_3;
++_.Secure-test=ignore_4;
++__Secure-test=ignore_5;
++_[Secure-test=ignore_6;
++[.Secure-test=ignore_7;
++[_Secure-test=ignore_8;
++[[Secure-test=ignore_9;
++..Secure-test[]=ignore_10;
++._Secure-test[]=ignore_11;
++.[Secure-test[]=ignore_12;
++_.Secure-test[]=ignore_13;
++__Secure-test[]=legitimate_14;
++_[Secure-test[]=legitimate_15;
++[.Secure-test[]=ignore_16;
++[_Secure-test[]=ignore_17;
++[[Secure-test[]=ignore_18;
++--FILE--
++<?php
++var_dump($_COOKIE);
++?>
++--EXPECT--
++array(3) {
++ ["__Host-test"]=>
++ array(1) {
++ [0]=>
++ string(13) "legitimate_14"
++ }
++ ["_"]=>
++ array(2) {
++ ["Host-test["]=>
++ string(13) "legitimate_15"
++ ["Secure-test["]=>
++ string(13) "legitimate_15"
++ }
++ ["__Secure-test"]=>
++ array(1) {
++ [0]=>
++ string(13) "legitimate_14"
++ }
++}
+diff --git a/main/php_variables.c b/main/php_variables.c
+index bd59134fc9..3e0e8d767e 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -59,6 +59,21 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, size_t str_len,
+ php_register_variable_ex(var, &new_entry, track_vars_array);
+ }
+
++/* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host-
++ * Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */
++static zend_bool php_is_forbidden_variable_name(const char *mangled_name, size_t mangled_name_len, const char *pre_mangled_name)
++{
++ if (mangled_name_len >= sizeof("__Host-")-1 && strncmp(mangled_name, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(pre_mangled_name, "__Host-", sizeof("__Host-")-1) != 0) {
++ return 1;
++ }
++
++ if (mangled_name_len >= sizeof("__Secure-")-1 && strncmp(mangled_name, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(pre_mangled_name, "__Secure-", sizeof("__Secure-")-1) != 0) {
++ return 1;
++ }
++
++ return 0;
++}
++
+ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)
+ {
+ char *p = NULL;
+@@ -109,20 +124,6 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ }
+ var_len = p - var;
+
+- /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */
+- if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) {
+- zval_ptr_dtor_nogc(val);
+- free_alloca(var_orig, use_heap);
+- return;
+- }
+-
+- /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */
+- if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) {
+- zval_ptr_dtor_nogc(val);
+- free_alloca(var_orig, use_heap);
+- return;
+- }
+-
+ if (var_len==0) { /* empty variable name, or variable name with a space in it */
+ zval_dtor(val);
+ free_alloca(var_orig, use_heap);
+@@ -220,6 +221,12 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
+ return;
+ }
+ } else {
++ if (php_is_forbidden_variable_name(index, index_len, var_name)) {
++ zval_ptr_dtor_nogc(val);
++ free_alloca(var_orig, use_heap);
++ return;
++ }
++
+ gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
+ if (!gpc_element_p) {
+ zval tmp;
+@@ -258,6 +265,12 @@ plain_var:
+ zval_ptr_dtor(&gpc_element);
+ }
+ } else {
++ if (php_is_forbidden_variable_name(index, index_len, var_name)) {
++ zval_ptr_dtor_nogc(val);
++ free_alloca(var_orig, use_heap);
++ return;
++ }
++
+ /*
+ * According to rfc2965, more specific paths are listed above the less specific ones.
+ * If we encounter a duplicate cookie name, we should skip it, since it is not possible
+--
+2.44.0
+
+From ee591001f7a3db7405b4fa027659768c2355df6d Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 10 Apr 2024 08:59:32 +0200
+Subject: [PATCH 2/4] NEWS
+
+(cherry picked from commit 366cc249b7d54707572beb7096e8f6c65ee79719)
+(cherry picked from commit dcdd49ef3bfbd8ccc778850d6a0f9b98adf625d4)
+(cherry picked from commit 8642473b624f809b768180b104c013f74e3a99a0)
+---
+ NEWS | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 286f3df0f4..e55195bc56 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.28
++
++- Standard:
++ . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to
++ partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos)
++
+ Backported from 8.0.30
+
+ - Libxml:
+--
+2.44.0
+
diff --git a/php-cve-2024-3096.patch b/php-cve-2024-3096.patch
new file mode 100644
index 0000000..ca137c6
--- /dev/null
+++ b/php-cve-2024-3096.patch
@@ -0,0 +1,85 @@
+From d22d9ebb29dce86edd622205dd1196a2796c08c7 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Fri, 29 Mar 2024 15:27:59 +0000
+Subject: [PATCH 3/4] Fix bug GHSA-q6x7-frmf-grcw: password_verify can
+ erroneously return true
+
+Disallow null character in bcrypt password
+
+(cherry picked from commit 0ba5229a3f7572846e91c8f5382e87785f543826)
+(cherry picked from commit 81794c73068d9a44bf109bbcc9793e7b56a1c051)
+(cherry picked from commit 4a7ceb9d6427f8d368f1a8739267b1f8310ec201)
+(cherry picked from commit 747100905eceffb1f67096b437001e42900eb6bb)
+---
+ ext/standard/password.c | 5 +++++
+ ext/standard/tests/password/password_bcrypt_errors.phpt | 6 ++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/ext/standard/password.c b/ext/standard/password.c
+index c92925b903..4944369ba8 100644
+--- a/ext/standard/password.c
++++ b/ext/standard/password.c
+@@ -438,6 +438,11 @@ PHP_FUNCTION(password_hash)
+ cost = zval_get_long(option_buffer);
+ }
+
++ if (memchr(ZSTR_VAL(password), '\0', ZSTR_LEN(password))) {
++ php_error_docref(NULL, E_WARNING, "Bcrypt password must not contain null character");
++ RETURN_NULL();
++ }
++
+ if (cost < 4 || cost > 31) {
+ php_error_docref(NULL, E_WARNING, "Invalid bcrypt cost parameter specified: " ZEND_LONG_FMT, cost);
+ RETURN_NULL();
+diff --git a/ext/standard/tests/password/password_bcrypt_errors.phpt b/ext/standard/tests/password/password_bcrypt_errors.phpt
+index a0826080e6..f95b72670a 100644
+--- a/ext/standard/tests/password/password_bcrypt_errors.phpt
++++ b/ext/standard/tests/password/password_bcrypt_errors.phpt
+@@ -16,6 +16,8 @@ var_dump(password_hash("foo", PASSWORD_BCRYPT, array("salt" => 123)));
+
+ var_dump(password_hash("foo", PASSWORD_BCRYPT, array("cost" => "foo")));
+
++var_dump(password_hash("null\0password", PASSWORD_BCRYPT));
++
+ ?>
+ --EXPECTF--
+ Warning: password_hash(): Invalid bcrypt cost parameter specified: 3 in %s on line %d
+@@ -41,3 +43,7 @@ NULL
+
+ Warning: password_hash(): Invalid bcrypt cost parameter specified: 0 in %s on line %d
+ NULL
++
++Warning: password_hash(): Bcrypt password must not contain null character in %s on line %d
++NULL
++
+--
+2.44.0
+
+From be830600a8e4c33a25e965d0782903e885e91c6d Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Wed, 10 Apr 2024 09:01:09 +0200
+Subject: [PATCH 4/4] NEWS
+
+(cherry picked from commit 24f77904ee2259d722559f129f96a1f145a2367b)
+(cherry picked from commit 027bdbc636632be49ecfad8d4191509faacb34ac)
+(cherry picked from commit fbeed182bb0b0c4c453e064198b5cc3814a10de0)
+---
+ NEWS | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index e55195bc56..7d99fb7d60 100644
+--- a/NEWS
++++ b/NEWS
+@@ -6,6 +6,8 @@ Backported from 8.1.28
+ - Standard:
+ . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to
+ partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos)
++ . Fixed bug GHSA-h746-cjrr-wfmr (password_verify can erroneously return true,
++ opening ATO risk). (CVE-2024-3096) (Jakub Zelenka)
+
+ Backported from 8.0.30
+
+--
+2.44.0
+
diff --git a/php-cve-2024-5458.patch b/php-cve-2024-5458.patch
new file mode 100644
index 0000000..d64bccd
--- /dev/null
+++ b/php-cve-2024-5458.patch
@@ -0,0 +1,184 @@
+From 87a7b8dab75e221a1fcd74cf34dc650f7253c12c Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Wed, 22 May 2024 22:25:02 +0200
+Subject: [PATCH 1/2] Fix GHSA-w8qr-v226-r27w
+
+We should not early-out with success status if we found an ipv6
+hostname, we should keep checking the rest of the conditions.
+Because integrating the if-check of the ipv6 hostname in the
+"Validate domain" if-check made the code hard to read, I extracted the
+condition out to a separate function. This also required to make
+a few pointers const in order to have some clean code.
+
+(cherry picked from commit 4066610b47e22c24cbee91be434a94357056a479)
+(cherry picked from commit 08be64e40197fc12dca5f802d16748d9c3cb4cb4)
+(cherry picked from commit 76362f9526afbd5565003d981f9507aaf62337f2)
+---
+ ext/filter/logical_filters.c | 35 ++++++++++---------
+ ext/filter/tests/ghsa-w8qr-v226-r27w.phpt | 41 +++++++++++++++++++++++
+ 2 files changed, 61 insertions(+), 15 deletions(-)
+ create mode 100644 ext/filter/tests/ghsa-w8qr-v226-r27w.phpt
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index 6894fa2551..f91aa12da4 100644
+--- a/ext/filter/logical_filters.c
++++ b/ext/filter/logical_filters.c
+@@ -81,7 +81,7 @@
+ #define FORMAT_IPV4 4
+ #define FORMAT_IPV6 6
+
+-static int _php_filter_validate_ipv6(char *str, size_t str_len);
++static int _php_filter_validate_ipv6(const char *str, size_t str_len);
+
+ static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
+ zend_long ctx_value;
+@@ -532,6 +532,14 @@ static int is_userinfo_valid(char *str)
+ return 1;
+ }
+
++static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l)
++{
++ const char *e = s + l;
++ const char *t = e - 1;
++
++ return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2);
++}
++
+ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+ {
+ php_url *url;
+@@ -551,7 +559,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+ }
+
+ if (url->scheme != NULL && (!strcasecmp(url->scheme, "http") || !strcasecmp(url->scheme, "https"))) {
+- char *e, *s, *t;
++ const char *s;
+ size_t l;
+
+ if (url->host == NULL) {
+@@ -560,17 +568,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+
+ s = url->host;
+ l = strlen(s);
+- e = url->host + l;
+- t = e - 1;
+-
+- /* An IPv6 enclosed by square brackets is a valid hostname */
+- if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) {
+- php_url_free(url);
+- return;
+- }
+
+- // Validate domain
+- if (!_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME)) {
++ if (
++ /* An IPv6 enclosed by square brackets is a valid hostname.*/
++ !php_filter_is_valid_ipv6_hostname(s, l) &&
++ /* Validate domain.
++ * This includes a loose check for an IPv4 address. */
++ !_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME)
++ ) {
+ php_url_free(url);
+ RETURN_VALIDATION_FAILED
+ }
+@@ -701,15 +706,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
+ }
+ /* }}} */
+
+-static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
++static int _php_filter_validate_ipv6(const char *str, size_t str_len) /* {{{ */
+ {
+ int compressed = 0;
+ int blocks = 0;
+ int n;
+ char *ipv4;
+- char *end;
++ const char *end;
+ int ip4elm[4];
+- char *s = str;
++ const char *s = str;
+
+ if (!memchr(str, ':', str_len)) {
+ return 0;
+diff --git a/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt
+new file mode 100644
+index 0000000000..0092408ee5
+--- /dev/null
++++ b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt
+@@ -0,0 +1,41 @@
++--TEST--
++GHSA-w8qr-v226-r27w
++--EXTENSIONS--
++filter
++--FILE--
++<?php
++
++function test(string $input) {
++ var_dump(filter_var($input, FILTER_VALIDATE_URL));
++}
++
++echo "--- These ones should fail ---\n";
++test("http://t[est@127.0.0.1");
++test("http://t[est@[::1]");
++test("http://t[est@[::1");
++test("http://t[est@::1]");
++test("http://php.net\\@aliyun.com/aaa.do");
++test("http://test[@2001:db8:3333:4444:5555:6666:1.2.3.4]");
++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4]");
++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4");
++
++echo "--- These ones should work ---\n";
++test("http://test@127.0.0.1");
++test("http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]");
++test("http://test@[::1]");
++
++?>
++--EXPECT--
++--- These ones should fail ---
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++--- These ones should work ---
++string(21) "http://test@127.0.0.1"
++string(50) "http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]"
++string(17) "http://test@[::1]"
+--
+2.45.1
+
+From 6b6444a1b72d6249cfa592f20395efe67ca55f73 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Tue, 4 Jun 2024 16:48:08 +0200
+Subject: [PATCH 2/2] NEWS
+
+(cherry picked from commit a1ff81b786bd519597e770795be114f5171f0648)
+(cherry picked from commit ec1d5e6468479e64acc7fb8cb955f053b64ea9a0)
+(cherry picked from commit cfe1b1acead13b6af163f3ce947d3a1dbded82a0)
+---
+ NEWS | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 7d99fb7d60..3bb175ea25 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.29
++
++- Filter:
++ . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL).
++ (CVE-2024-5458) (nielsdos)
++
+ Backported from 8.1.28
+
+ - Standard:
+--
+2.45.1
+
diff --git a/php-cve-2024-8925.patch b/php-cve-2024-8925.patch
new file mode 100644
index 0000000..031bfc3
--- /dev/null
+++ b/php-cve-2024-8925.patch
@@ -0,0 +1,236 @@
+From 5731a40507feea683591addf3599d210cd7a1fd9 Mon Sep 17 00:00:00 2001
+From: Arnaud Le Blanc <arnaud.lb@gmail.com>
+Date: Mon, 9 Sep 2024 15:22:07 +0200
+Subject: [PATCH 3/8] Fix GHSA-9pqp-7h25-4f32
+
+multipart/form-data boundaries larger than the read buffer result in erroneous
+parsing, which violates data integrity.
+
+Limit boundary size, as allowed by RFC 1521:
+
+ Encapsulation boundaries [...] must be no longer than 70 characters, not
+ counting the two leading hyphens.
+
+We correctly parse payloads with boundaries of length up to
+FILLUNIT-strlen("\r\n--") bytes, so allow this for BC.
+
+(cherry picked from commit 19b49258d0c5a61398d395d8afde1123e8d161e0)
+(cherry picked from commit 2b0daf421c162376892832588eccdfa9a286ed09)
+(cherry picked from commit a24ac172f52e75101913f3946cfa5515f723c99f)
+(cherry picked from commit 08f0adf0700f8bbaa4fd75b7a694bbd9ae45300d)
+---
+ main/rfc1867.c | 7 ++
+ tests/basic/GHSA-9pqp-7h25-4f32.inc | 3 +
+ tests/basic/GHSA-9pqp-7h25-4f32.phpt | 100 +++++++++++++++++++++++++++
+ 3 files changed, 110 insertions(+)
+ create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.inc
+ create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.phpt
+
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index 14813a300c..43b94c056a 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -769,6 +769,13 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ boundary_len = boundary_end-boundary;
+ }
+
++ /* Boundaries larger than FILLUNIT-strlen("\r\n--") characters lead to
++ * erroneous parsing */
++ if (boundary_len > FILLUNIT-strlen("\r\n--")) {
++ sapi_module.sapi_error(E_WARNING, "Boundary too large in multipart/form-data POST data");
++ return;
++ }
++
+ /* Initialize the buffer */
+ if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
+ sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
+diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.inc b/tests/basic/GHSA-9pqp-7h25-4f32.inc
+new file mode 100644
+index 0000000000..adf72a361a
+--- /dev/null
++++ b/tests/basic/GHSA-9pqp-7h25-4f32.inc
+@@ -0,0 +1,3 @@
++<?php
++print "Hello world\n";
++var_dump($_POST);
+diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+new file mode 100644
+index 0000000000..af81916370
+--- /dev/null
++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+@@ -0,0 +1,100 @@
++--TEST--
++GHSA-9pqp-7h25-4f32
++--SKIPIF--
++<?php
++if (!getenv('TEST_PHP_CGI_EXECUTABLE')) {
++ die("skip php-cgi not available");
++}
++?>
++--FILE--
++<?php
++
++const FILLUNIT = 5 * 1024;
++
++function test($boundaryLen) {
++ printf("Boundary len: %d\n", $boundaryLen);
++
++ $cmd = [
++ getenv('TEST_PHP_CGI_EXECUTABLE'),
++ '-C',
++ '-n',
++ __DIR__ . '/GHSA-9pqp-7h25-4f32.inc',
++ ];
++
++ $boundary = str_repeat('A', $boundaryLen);
++ $body = ""
++ . "--$boundary\r\n"
++ . "Content-Disposition: form-data; name=\"koko\"\r\n"
++ . "\r\n"
++ . "BBB\r\n--" . substr($boundary, 0, -1) . "CCC\r\n"
++ . "--$boundary--\r\n"
++ ;
++
++ $env = array_merge($_ENV, [
++ 'REDIRECT_STATUS' => '1',
++ 'CONTENT_TYPE' => "multipart/form-data; boundary=$boundary",
++ 'CONTENT_LENGTH' => strlen($body),
++ 'REQUEST_METHOD' => 'POST',
++ 'SCRIPT_FILENAME' => __DIR__ . '/GHSA-9pqp-7h25-4f32.inc',
++ ]);
++
++ $spec = [
++ 0 => ['pipe', 'r'],
++ 1 => STDOUT,
++ 2 => STDOUT,
++ ];
++
++ $pipes = [];
++
++ print "Starting...\n";
++
++ $handle = proc_open($cmd, $spec, $pipes, getcwd(), $env);
++
++ fwrite($pipes[0], $body);
++
++ $status = proc_close($handle);
++
++ print "\n";
++}
++
++for ($offset = -1; $offset <= 1; $offset++) {
++ test(FILLUNIT - strlen("\r\n--") + $offset);
++}
++
++?>
++--EXPECTF--
++Boundary len: 5115
++Starting...
++X-Powered-By: %s
++Content-type: text/html; charset=UTF-8
++
++Hello world
++array(1) {
++ ["koko"]=>
++ string(5124) "BBB
++--AAA%sCCC"
++}
++
++Boundary len: 5116
++Starting...
++X-Powered-By: %s
++Content-type: text/html; charset=UTF-8
++
++Hello world
++array(1) {
++ ["koko"]=>
++ string(5125) "BBB
++--AAA%sCCC"
++}
++
++Boundary len: 5117
++Starting...
++X-Powered-By: %s
++Content-type: text/html; charset=UTF-8
++
++<br />
++<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br />
++Hello world
++array(0) {
++}
++
+--
+2.46.1
+
+From 0c9258e4914695ca21b3d0cd3b1746bfc926f02e Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Mon, 23 Sep 2024 18:54:31 +0100
+Subject: [PATCH 6/8] Skip GHSA-9pqp-7h25-4f32 test on Windows
+
+(cherry picked from commit c70e25630832fa10d421328eed2b8e1a36af7a64)
+(cherry picked from commit c75683864f6e4188439e8ca2adbb05824918be12)
+(cherry picked from commit 2fd1b83817d20523e72bef3ad524cd5797f51acf)
+(cherry picked from commit 79eace3a64544088738d2fd341407cc32fe3ecaf)
+---
+ tests/basic/GHSA-9pqp-7h25-4f32.phpt | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+index af81916370..29bcb6557d 100644
+--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt
++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+@@ -5,6 +5,9 @@ GHSA-9pqp-7h25-4f32
+ if (!getenv('TEST_PHP_CGI_EXECUTABLE')) {
+ die("skip php-cgi not available");
+ }
++if (substr(PHP_OS, 0, 3) == 'WIN') {
++ die("skip not for Windows in CI - probably resource issue");
++}
+ ?>
+ --FILE--
+ <?php
+--
+2.46.1
+
+From d97de82afe8696b6d76cc11bc7b6d6c2652d06d9 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 26 Sep 2024 15:49:03 +0200
+Subject: [PATCH 8/8] adapt GHSA-9pqp-7h25-4f32 test for 7.x
+
+(cherry picked from commit 29065f33f37f99ba33254cb23c941647bcd7372c)
+(cherry picked from commit 87ed9429a17e38daec4dcfd7a3c3db194197ccb3)
+---
+ tests/basic/GHSA-9pqp-7h25-4f32.phpt | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+index 29bcb6557d..b913edc1c4 100644
+--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt
++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt
+@@ -21,8 +21,10 @@ function test($boundaryLen) {
+ getenv('TEST_PHP_CGI_EXECUTABLE'),
+ '-C',
+ '-n',
++ '-dlog_errors=1',
+ __DIR__ . '/GHSA-9pqp-7h25-4f32.inc',
+ ];
++ $cmd = implode(' ', $cmd);
+
+ $boundary = str_repeat('A', $boundaryLen);
+ $body = ""
+@@ -92,11 +94,10 @@ array(1) {
+
+ Boundary len: 5117
+ Starting...
++PHP Warning: Boundary too large in multipart/form-data POST data in Unknown on line 0
+ X-Powered-By: %s
+ Content-type: text/html; charset=UTF-8
+
+-<br />
+-<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br />
+ Hello world
+ array(0) {
+ }
+--
+2.46.1
+
diff --git a/php-cve-2024-8926.patch b/php-cve-2024-8926.patch
new file mode 100644
index 0000000..8ef88ce
--- /dev/null
+++ b/php-cve-2024-8926.patch
@@ -0,0 +1,204 @@
+From 669f8524ad99a6b9220ea2cee1a07a9de3964776 Mon Sep 17 00:00:00 2001
+From: Jan Ehrhardt <github@ehrhardt.nl>
+Date: Wed, 5 Jun 2024 20:28:45 +0200
+Subject: [PATCH 1/8] Fix GHSA-3qgc-jrrr-25jv
+
+---
+ sapi/cgi/cgi_main.c | 23 ++++++++++++++-
+ sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt | 38 +++++++++++++++++++++++++
+ 2 files changed, 60 insertions(+), 1 deletion(-)
+ create mode 100644 sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index 16bb2126d2..970950a657 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1881,8 +1881,13 @@ int main(int argc, char *argv[])
+ }
+ }
+
++ /* Apache CGI will pass the query string to the command line if it doesn't contain a '='.
++ * This can create an issue where a malicious request can pass command line arguments to
++ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode,
++ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`.
++ * Therefore, this code only prevents passing arguments if the query string starts with a '-'.
++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */
+ if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
+- /* we've got query string that has no = - apache CGI will pass it to command line */
+ unsigned char *p;
+ decoded_query_string = strdup(query_string);
+ php_url_decode(decoded_query_string, strlen(decoded_query_string));
+@@ -1892,6 +1897,22 @@ int main(int argc, char *argv[])
+ if(*p == '-') {
+ skip_getopt = 1;
+ }
++
++ /* On Windows we have to take into account the "best fit" mapping behaviour. */
++#ifdef PHP_WIN32
++ if (*p >= 0x80) {
++ wchar_t wide_buf[1];
++ wide_buf[0] = *p;
++ char char_buf[4];
++ size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
++ size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
++ if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
++ || char_buf[0] == '-') {
++ skip_getopt = 1;
++ }
++ }
++#endif
++
+ free(decoded_query_string);
+ }
+
+diff --git a/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+new file mode 100644
+index 0000000000..fd2fcdfbf8
+--- /dev/null
++++ b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+@@ -0,0 +1,38 @@
++--TEST--
++GHSA-3qgc-jrrr-25jv
++--SKIPIF--
++<?php
++include 'skipif.inc';
++if (PHP_OS_FAMILY !== "Windows") die("skip Only for Windows");
++
++$codepage = trim(shell_exec("powershell Get-ItemPropertyValue HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage ACP"));
++if ($codepage !== '932' && $codepage !== '936' && $codepage !== '950') die("skip Wrong codepage");
++?>
++--FILE--
++<?php
++include 'include.inc';
++
++$filename = __DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php";
++$script = '<?php echo "hello "; echo "world"; ?>';
++file_put_contents($filename, $script);
++
++$php = get_cgi_path();
++reset_env_vars();
++
++putenv("SERVER_NAME=Test");
++putenv("SCRIPT_FILENAME=$filename");
++putenv("QUERY_STRING=%ads");
++putenv("REDIRECT_STATUS=1");
++
++passthru("$php -s");
++
++?>
++--CLEAN--
++<?php
++@unlink(__DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php");
++?>
++--EXPECTF--
++X-Powered-By: PHP/%s
++Content-type: %s
++
++hello world
+--
+2.46.1
+
+From cc70fdedb5b362b6d666bc6604658aac70c1aec0 Mon Sep 17 00:00:00 2001
+From: Jan Ehrhardt <github@ehrhardt.nl>
+Date: Sun, 9 Jun 2024 20:12:52 +0200
+Subject: [PATCH 2/8] NEWS: Add backport from 8.1.29
+
+---
+ NEWS | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 3bb175ea25..c52661abc3 100644
+--- a/NEWS
++++ b/NEWS
+@@ -3,6 +3,10 @@ PHP NEWS
+
+ Backported from 8.1.29
+
++- CGI:
++ . Fixed bug GHSA-3qgc-jrrr-25jv (Bypass of CVE-2012-1823, Argument Injection
++ in PHP-CGI). (CVE-2024-4577) (nielsdos)
++
+ - Filter:
+ . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL).
+ (CVE-2024-5458) (nielsdos)
+--
+2.46.1
+
+From 53a0269aa1d952eec1c65e0e0d3e9800e0427ded Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 14 Jun 2024 19:49:22 +0200
+Subject: [PATCH 4/8] Fix GHSA-p99j-rfp4-xqvq
+
+It's no use trying to work around whatever the operating system and Apache
+do because we'll be fighting that until eternity.
+Change the skip_getopt condition such that when we're running in
+CGI or FastCGI mode we always skip the argument parsing.
+This is a BC break, but this seems to be the only way to get rid of this
+class of issues.
+
+(cherry picked from commit abcfd980bfa03298792fd3aba051c78d52f10642)
+(cherry picked from commit 2d2552e092b6ff32cd823692d512f126ee629842)
+(cherry picked from commit 1158d06f0b20532ab7309cb20f0be843f9662e3c)
+(cherry picked from commit 89c66773413267949de995671bfb4bd03c34fbf9)
+---
+ sapi/cgi/cgi_main.c | 26 ++++++++------------------
+ 1 file changed, 8 insertions(+), 18 deletions(-)
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index 970950a657..be273676ce 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1830,7 +1830,6 @@ int main(int argc, char *argv[])
+ int status = 0;
+ #endif
+ char *query_string;
+- char *decoded_query_string;
+ int skip_getopt = 0;
+
+ #ifdef HAVE_SIGNAL_H
+@@ -1886,10 +1885,15 @@ int main(int argc, char *argv[])
+ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode,
+ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`.
+ * Therefore, this code only prevents passing arguments if the query string starts with a '-'.
+- * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */
++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue.
++ * However, Windows has lots of conversion rules and command line parsing rules that
++ * are too difficult and dangerous to reliably emulate. */
+ if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
++#ifdef PHP_WIN32
++ skip_getopt = cgi || fastcgi;
++#else
+ unsigned char *p;
+- decoded_query_string = strdup(query_string);
++ char *decoded_query_string = strdup(query_string);
+ php_url_decode(decoded_query_string, strlen(decoded_query_string));
+ for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) {
+ /* skip all leading spaces */
+@@ -1898,22 +1902,8 @@ int main(int argc, char *argv[])
+ skip_getopt = 1;
+ }
+
+- /* On Windows we have to take into account the "best fit" mapping behaviour. */
+-#ifdef PHP_WIN32
+- if (*p >= 0x80) {
+- wchar_t wide_buf[1];
+- wide_buf[0] = *p;
+- char char_buf[4];
+- size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
+- size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
+- if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
+- || char_buf[0] == '-') {
+- skip_getopt = 1;
+- }
+- }
+-#endif
+-
+ free(decoded_query_string);
++#endif
+ }
+
+ while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
+--
+2.46.1
+
diff --git a/php-cve-2024-8927.patch b/php-cve-2024-8927.patch
new file mode 100644
index 0000000..61470ea
--- /dev/null
+++ b/php-cve-2024-8927.patch
@@ -0,0 +1,98 @@
+From 74f1553070cb6237e25945407be7f75a43736113 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Tue, 18 Jun 2024 21:28:26 +0200
+Subject: [PATCH 5/8] Fix GHSA-94p6-54jq-9mwp
+
+Apache only generates REDIRECT_STATUS, so explicitly check for that
+if the server name is Apache, don't allow other variable names.
+Furthermore, redirect.so and Netscape no longer exist, so
+remove those entries as we can't check their server name anymore.
+
+We now also check for the configuration override *first* such that it
+always take precedence. This would allow for a mitigation path if
+something like this happens in the future.
+
+(cherry picked from commit 48808d98f4fc2a05193cdcc1aedd6c66816450f1)
+(cherry picked from commit 8aa748ee0657cdee8d883ba50d04b68bc450f686)
+(cherry picked from commit c7308ba7cd0533501b40eba255602bb5e085550f)
+(cherry picked from commit 21e2b0ab382a898f627c97d39f5e5afc2431afe7)
+---
+ sapi/cgi/cgi_main.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index be273676ce..205d559f6d 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1992,18 +1992,17 @@ int main(int argc, char *argv[])
+
+ /* check force_cgi after startup, so we have proper output */
+ if (cgi && CGIG(force_redirect)) {
+- /* Apache will generate REDIRECT_STATUS,
+- * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS.
+- * redirect.so and installation instructions available from
+- * http://www.koehntopp.de/php.
+- * -- kk@netuse.de
+- */
+- if (!getenv("REDIRECT_STATUS") &&
+- !getenv ("HTTP_REDIRECT_STATUS") &&
+- /* this is to allow a different env var to be configured
+- * in case some server does something different than above */
+- (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env)))
+- ) {
++ /* This is to allow a different environment variable to be configured
++ * in case the we cannot auto-detect which environment variable to use.
++ * Checking this first to allow user overrides in case the environment
++ * variable can be set by an untrusted party. */
++ const char *redirect_status_env = CGIG(redirect_status_env);
++ if (!redirect_status_env) {
++ /* Apache will generate REDIRECT_STATUS. */
++ redirect_status_env = "REDIRECT_STATUS";
++ }
++
++ if (!getenv(redirect_status_env)) {
+ zend_try {
+ SG(sapi_headers).http_response_code = 400;
+ PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\
+--
+2.46.1
+
+From e80cb90b00aa403a5aa995f612ecb358323e9572 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Thu, 26 Sep 2024 11:50:54 +0200
+Subject: [PATCH 7/8] NEWS for 8.1.30 backports
+
+(cherry picked from commit af3fb385e7b328ab89db26ec712d89c7096f0743)
+(cherry picked from commit 1154fbd3ddfa418bf2492c5366adaefb47c47737)
+(cherry picked from commit b4667e4ebe241d95775962b1e8b24788e7945de2)
+---
+ NEWS | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index c52661abc3..ced91f9577 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,19 @@
+ PHP NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
++Backported from 8.1.30
++
++- CGI:
++ . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection
++ Vulnerability). (CVE-2024-8926) (nielsdos)
++ . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is
++ bypassable due to the environment variable collision). (CVE-2024-8927)
++ (nielsdos)
++
++- SAPI:
++ . Fixed bug GHSA-9pqp-7h25-4f32 (Erroneous parsing of multipart form data).
++ (CVE-2024-8925) (Arnaud)
++
+ Backported from 8.1.29
+
+ - CGI:
+--
+2.46.1
+
diff --git a/php-cve-2024-8932.patch b/php-cve-2024-8932.patch
new file mode 100644
index 0000000..2737c79
--- /dev/null
+++ b/php-cve-2024-8932.patch
@@ -0,0 +1,141 @@
+From f8756a7a1d185727a5bfd212b1442a6d153a9471 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 5/9] Fix GHSA-g665-fm4p-vhff: OOB access in ldap_escape
+
+(cherry picked from commit f9ecf90070a11dad09ca7671a712f81cc2a7d52f)
+(cherry picked from commit 9f367d847989b339c33369737daf573e30bab5f1)
+(cherry picked from commit 50e9e72530a4805980384b8ea6672877af816145)
+(cherry picked from commit 9822bfae85607dffc13848d40a2340daf090f39b)
+---
+ ext/ldap/ldap.c | 21 ++++++++++++++--
+ ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt | 28 ++++++++++++++++++++++
+ ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt | 29 +++++++++++++++++++++++
+ 3 files changed, 76 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 3839f871a9..533c78138d 100644
+--- a/ext/ldap/ldap.c
++++ b/ext/ldap/ldap.c
+@@ -54,6 +54,7 @@
+
+ #include "ext/standard/php_string.h"
+ #include "ext/standard/info.h"
++#include "Zend/zend_exceptions.h"
+
+ #ifdef HAVE_LDAP_SASL_H
+ #include <sasl.h>
+@@ -3005,13 +3006,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;
+ }
+
+@@ -3078,7 +3089,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_throw_exception(NULL, "Argument #1 ($value) is too long", 0);
++ return;
++ }
++
++ 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 0000000000..734bbe91d4
+--- /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 (Exception $e) {
++ echo $e->getMessage(), "\n";
++}
++
++try {
++ ldap_escape(str_repeat("#", 1431655758).' ', "", LDAP_ESCAPE_DN);
++} catch (Exception $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 0000000000..5c1b0fb661
+--- /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 (Exception $e) {
++ echo $e->getMessage(), "\n";
++}
++
++// would allocate a string of length 2
++try {
++ ldap_escape(str_repeat("*", 1431655766), "", LDAP_ESCAPE_FILTER);
++} catch (Exception $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-ghsa-4w77-75f9-2c8w.patch b/php-ghsa-4w77-75f9-2c8w.patch
new file mode 100644
index 0000000..a93a3b3
--- /dev/null
+++ b/php-ghsa-4w77-75f9-2c8w.patch
@@ -0,0 +1,139 @@
+From b7c951d47acae54aab5ce896b8ec151d661c8fd0 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 8/9] Fix GHSA-4w77-75f9-2c8w
+
+(cherry picked from commit 7dd336ae838bbf2c62dc47e3c900d657d3534c02)
+(cherry picked from commit 462092a48aa0dbad24d9fa8a4a9d418faa14d309)
+(cherry picked from commit 56488a8a4ec68e58eecc9e78dd75e41adf56984c)
+(cherry picked from commit 6b8357c22f83a93104c2682d5cba9104c8de636d)
+---
+ 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 cdcd93ac72..5de98ad1c7 100644
+--- a/sapi/cli/php_cli_server.c
++++ b/sapi/cli/php_cli_server.c
+@@ -1801,8 +1801,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;
+@@ -1810,9 +1808,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 0000000000..44667e8389
+--- /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 . "/", false, $context);
++
++$options = [
++ "http" => [
++ "method" => "POST",
++ ],
++];
++$context = stream_context_create($options);
++
++echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", false, $context);
++?>
++--EXPECT--
++string(5) "AAAAA"
++string(0) ""
+--
+2.47.0
+
+From 46f3d442aae8d8caca33a4d4ff9c9470568aee80 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi@remirepo.net>
+Date: Fri, 22 Nov 2024 08:58:10 +0100
+Subject: [PATCH 9/9] NEWS for 8.1.31 backports
+
+(cherry picked from commit 22bdb43da0ecd6e72d63b63aa6c1f3a25d1bca3a)
+(cherry picked from commit d8d682d3d6a4d027771806c8fc77128cae078d29)
+(cherry picked from commit b97a41a47f77df92771b3c01fbf7cf445c0e7a1b)
+---
+ NEWS | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index ced91f9577..cc2d877d94 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 b5318b2..0774fa8 100644
--- a/php-keyring.gpg
+++ b/php-keyring.gpg
@@ -1,320 +1,780 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
-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
-jZkkGZj3BY/7ApoLq4mwqzbh+CpLXwNn20tFNvSXfb8RdeXvVEb7Scx+W9qYpiau
-n2iXJgCVH8fgpZpR856ulT1q6uCG++CXubEvip/eJkZl93/84h04KQJwsgOrAh0O
-m3OePRn8Pr+++0LNS0EL8uX/YHeTOGOnnmTqYTeySBVFdov6L4mepddfjekicKQq
-hL7mZh/xuq29JijT0uNNX8v4vDWQDu5dlAcdd+uB3gcXMD/PginD11zp+6wtrWCm
-/+yBqpvDwXQX5PGUnwvbRfl7Ay3MmwmoXiecZMg0dwTSc7e0lhB4HGRHZdBMJB4r
-HUVGdzqujK/ctOvrAAMFB/0Utb76Qe6sCMlHxVAmeE/fbo7Pi05btZ/x01r67dHf
-aMSP0riCKJ7M0OW+jAXtu9+z/BVnYisW67WWfxl2cS5tZDgiHgJARXWUOO72+sSc
-HP8KQmTl1z16gyKbwY3SmyBkwcpOL35nhUWNLy93syPoY6sZUTikr2bZYukHDQ33
-XBPs4e6MbWKfsa9qaVmnlOF3k5UqChjutfHaEa4Q7VP4wBIpphHBi9MI16oJIzzB
-PbGl2uoedjwiZ6QeQZnSuOVYZxU2d3lRA8PrtfFN1VSlpEm/VcAvtieHUYWHN0wO
-u+cp3Slr5XJVNjTjJhl28SlinMME54mKAGf2Ldr/dRwXiGEEGBEIAAkFAk9mqaAC
-GwwACgkQL3lWvF2gS126EQD/VVd3FgjLKglClRQPzdfU847tqDK4zJjbmRv5vLLw
-oE0A+wbrQs7jVGU3NrS0AIl5vUmewpp2BKzSkepy23nWmejwmQINBFjxRtoBEADk
-S6+Q7afwYDPFnqJXuyF2ZIvXysDBrpr/xbre4jVeiC/HIELaQedOJqO1V+BgnTRk
-fhor+Yq3mZ1un+6zJIiFcm5Kp7sPZjh15JF96PsA4e2Eh5eCeJzjXHj1nAKXfn5+
-CgpYEyL30r1/ACkmo9TKIiUxIDZRkZvxjY4UKeo+EoJo0ViutV8mvSTgxaz9gzPh
-Z5OJR8zECT8j3T8d+tBD8wWxxmGZ0veOu/MBew1C/BDr8RqTCXDywUbyNuSsdb3a
-5aLuIuLekSJVSCcFwPIje1WrX4FyC42+elOp0SXpjWzdb08NXX4DEY8zVyVXI1Sc
-SpTbslffcFkY60NJhjpP7t856L9vTLRfHIM9BIdSYH/ar5mEQ0vyJbiNfkx5tIMn
-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
-RbbnRGir0GxlvcmpWMLo+2IqeVyRrbY=
-=jKsj
+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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
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/php72.spec b/php72.spec
index 2761438..7822248 100644
--- a/php72.spec
+++ b/php72.spec
@@ -25,16 +25,16 @@
%global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock)
-%if 0%{?rhel} == 6
-%ifarch x86_64
-%global oraclever 18.5
-%else
-%global oraclever 18.3
-%endif
-%global oraclelib 18.1
-%else
-%global oraclever 19.6
+%ifarch aarch64
+%global oraclever 19.24
+%global oraclemax 20
%global oraclelib 19.1
+%global oracledir 19.24
+%else
+%global oraclever 23.6
+%global oraclemax 24
+%global oraclelib 23.1
+%global oracledir 23
%endif
# Build for LiteSpeed Web Server (LSAPI)
@@ -61,7 +61,11 @@
%global with_sqlite3 1
# Build ZTS extension or only NTS
+%ifarch x86_64
%global with_zts 1
+%else
+%global with_zts 0
+%endif
# Debuild build
%global with_debug %{?_with_debug:1}%{!?_with_debug:0}
@@ -102,17 +106,11 @@
%global with_nginx 0
%endif
-# until firebird available in EPEL
-%if 0%{?rhel} == 8
-%global with_firebird 0
-%else
%global with_firebird 1
-%endif
-
-%global with_dtrace 1
-%global with_libgd 1
-%global with_libzip 1
-%global with_zip 0
+%global with_dtrace 1
+%global with_libgd 1
+%global with_libzip 1
+%global with_zip 0
%if 0%{?fedora} < 18 && 0%{?rhel} < 7
%global db_devel db4-devel
@@ -120,13 +118,12 @@
%global db_devel libdb-devel
%endif
-%global upver 7.2.33
-#global rcver RC1
+%global upver 7.2.34
Summary: PHP scripting language for creating dynamic web sites
Name: php
Version: %{upver}%{?rcver:~%{rcver}}
-Release: 1%{?dist}
+Release: 25%{?dist}
# All files licensed under PHP version 3.01, except
# Zend is licensed under Zend
# TSRM is licensed under BSD
@@ -163,6 +160,7 @@ Source99: php-fpm.init
# Build fixes
Patch1: php-7.1.7-httpd.patch
+Patch2: php-7.1.33-intl.patch
Patch5: php-7.2.0-includedir.patch
Patch6: php-5.6.3-embed.patch
Patch7: php-5.3.0-recode.patch
@@ -192,6 +190,37 @@ Patch91: php-7.2.0-oci8conf.patch
# Upstream fixes (100+)
# Security fixes (200+)
+Patch200: php-bug77423.patch
+Patch201: php-bug80672.patch
+Patch202: php-bug80710.patch
+Patch203: php-bug81122.patch
+Patch204: php-bug76450.patch
+Patch205: php-bug81211.patch
+Patch206: php-bug81026.patch
+Patch207: php-bug79971.patch
+Patch208: php-bug81719.patch
+Patch209: php-bug81720.patch
+Patch210: php-bug81727.patch
+Patch211: php-bug81726.patch
+Patch212: php-bug81738.patch
+Patch213: php-bug81740.patch
+Patch214: php-bug81744.patch
+Patch215: php-bug81746.patch
+Patch216: php-cve-2023-0662.patch
+Patch217: php-cve-2023-3247.patch
+Patch218: php-cve-2023-3823.patch
+Patch219: php-cve-2023-3824.patch
+Patch220: php-cve-2024-2756.patch
+Patch221: php-cve-2024-3096.patch
+Patch222: php-cve-2024-5458.patch
+Patch223: php-cve-2024-8925.patch
+Patch224: php-cve-2024-8926.patch
+Patch225: php-cve-2024-8927.patch
+Patch226: php-cve-2024-11236.patch
+Patch227: php-cve-2024-11234.patch
+Patch228: php-cve-2024-8932.patch
+Patch229: php-cve-2024-11233.patch
+Patch230: php-ghsa-4w77-75f9-2c8w.patch
# Fixes for tests (300+)
# Factory is droped from system tzdata
@@ -227,6 +256,7 @@ BuildRequires: bzip2
BuildRequires: perl
BuildRequires: autoconf
BuildRequires: automake
+BuildRequires: make
BuildRequires: %{?dtsprefix}gcc
BuildRequires: %{?dtsprefix}gcc-c++
BuildRequires: libtool
@@ -311,7 +341,7 @@ Group: Development/Languages
Summary: The interactive PHP debugger
Requires: php-common%{?_isa} = %{version}-%{release}
%if 0%{?rhel}
-Obsoletes: php56u-dbg, php56w-dbg, php70u-dbg, php70w-phpdbg, php71u-dbg, php71w-phpdbg, php72u-dbg, php72w-phpdbg
+Obsoletes: php56u-dbg, php56w-phpdbg, php70u-dbg, php70w-phpdbg, php71u-dbg, php71w-phpdbg, php72u-dbg, php72w-phpdbg
%endif
%description dbg
The php-dbg package contains the interactive PHP debugger.
@@ -322,7 +352,6 @@ Group: Development/Languages
Summary: PHP FastCGI Process Manager
BuildRequires: libacl-devel
Requires: php-common%{?_isa} = %{version}-%{release}
-Requires(pre): /usr/sbin/useradd
%if %{with_systemd}
BuildRequires: systemd-devel
%{?systemd_requires}
@@ -343,6 +372,8 @@ Requires(pre): httpd-filesystem
Requires: httpd-filesystem >= 2.4.10
# php engine for Apache httpd webserver
Provides: php(httpd)
+%else
+Requires(pre): /usr/sbin/useradd
%endif
%if %{with_nginx}
# for /etc/nginx ownership
@@ -439,6 +470,7 @@ Requires: php-cli%{?_isa} = %{version}-%{release}
# always needed to build extension
Requires: autoconf
Requires: automake
+Requires: make
Requires: gcc
Requires: gcc-c++
Requires: libtool
@@ -699,15 +731,20 @@ Summary: A module for PHP applications that use OCI8 databases
Group: Development/Languages
# All files licensed under PHP version 3.01
License: PHP
-BuildRequires: oracle-instantclient-devel >= %{oraclever}
+%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: php-pdo%{?_isa} = %{version}-%{release}
Provides: php_database
Provides: php-pdo_oci, php-pdo_oci%{?_isa}
Obsoletes: php-pecl-oci8 <= %{oci8ver}
Conflicts: php-pecl-oci8 > %{oci8ver}
Provides: php-pecl(oci8) = %{oci8ver}, php-pecl(oci8)%{?_isa} = %{oci8ver}
-# Should requires libclntsh.so.18.3, but it's not provided by Oracle RPM.
-AutoReq: 0
%if 0%{?rhel}
Obsoletes: php53-oci8, php53u-oci8, php54-oci8, php54w-oci8, php55u-oci8, php55w-oci8, php56u-oci8, php56w-oci8
Obsoletes: php70u-oci8, php70w-oci8, php71u-oci8, php71w-oci8, php72u-oci8, php72w-oci8
@@ -721,13 +758,9 @@ The extension is linked with Oracle client libraries %{oraclever}
(Oracle Instant Client). For details, see Oracle's note
"Oracle Client / Server Interoperability Support" (ID 207303.1).
-You must install libclntsh.so.%{oraclelib} to use this package, provided
-in the database installation, or in the free Oracle Instant Client
-available from Oracle.
-
-Notice:
-- php-oci8 provides oci8 and pdo_oci extensions from php sources.
-- php-pecl-oci8 only provides oci8 extension.
+You must install libclntsh.so.%{oraclelib} to use this package,
+provided by Oracle Instant Client RPM available from Oracle on:
+https://www.oracle.com/database/technologies/instant-client/downloads.html
Documentation is at http://php.net/oci8 and http://php.net/pdo_oci
%endif
@@ -830,12 +863,7 @@ License: PHP and BSD
%endif
Requires: php-common%{?_isa} = %{version}-%{release}
%if %{with_libgd}
-BuildRequires: gd-devel >= 2.1.1
-%if 0%{?fedora} <= 19 && 0%{?rhel} <= 7
-Requires: gd-last%{?_isa} >= 2.1.1
-%else
-Requires: gd%{?_isa} >= 2.1.1
-%endif
+BuildRequires: gd-devel >= 2.3.3
%else
# Required to build the bundled GD library
BuildRequires: libjpeg-devel
@@ -994,11 +1022,13 @@ Group: System Environment/Libraries
# All files licensed under PHP version 3.01
License: PHP
Requires: php-common%{?_isa} = %{version}-%{release}
-# Upstream requires 4.0, we require 50 to ensure use of libicu-last / libicu62
-BuildRequires: libicu-devel >= 50
%if 0%{?rhel}
+# Upstream requires 4.0, we require 69.1 to ensure use of libicu69
+BuildRequires: libicu-devel = 69.1
Obsoletes: php53-intl, php53u-intl, php54-intl, php54w-intl, php55u-intl, php55w-intl, php56u-intl, php56w-intl
Obsoletes: php70u-intl, php70w-intl, php71u-intl, php71w-intl, php72u-intl, php72w-intl
+%else
+BuildRequires: libicu-devel
%endif
%description intl
@@ -1098,49 +1128,81 @@ low-level PHP extension for the libsodium cryptographic library.
%setup -q -n php-%{upver}%{?rcver}
-%patch1 -p1 -b .mpmcheck
-%patch5 -p1 -b .includedir
-%patch6 -p1 -b .embed
-%patch7 -p1 -b .recode
-%patch8 -p1 -b .libdb
+%patch -P1 -p1 -b .mpmcheck
+%patch -P2 -p1 -b .true
+%patch -P5 -p1 -b .includedir
+%patch -P6 -p1 -b .embed
+%patch -P7 -p1 -b .recode
+%patch -P8 -p1 -b .libdb
%if 0%{?rhel}
-%patch9 -p1 -b .curltls
+%patch -P9 -p1 -b .curltls
%endif
-%patch40 -p1 -b .dlopen
+%patch -P40 -p1 -b .dlopen
%if 0%{?fedora} >= 28 || 0%{?rhel} >= 6
-%patch42 -p1 -b .systzdata
+%patch -P42 -p1 -b .systzdata
%endif
-%patch43 -p1 -b .headers
+%patch -P43 -p1 -b .headers
%if 0%{?fedora} >= 18 || 0%{?rhel} >= 7
-%patch45 -p1 -b .ldap_r
+%patch -P45 -p1 -b .ldap_r
%endif
-%patch46 -p1 -b .fixheader
-%patch47 -p1 -b .phpinfo
-%patch48 -p1 -b .getallheaders
-%patch49 -p1 -b .pdooci
+%patch -P46 -p1 -b .fixheader
+%patch -P47 -p1 -b .phpinfo
+%patch -P48 -p1 -b .getallheaders
+%patch -P49 -p1 -b .pdooci
-%patch91 -p1 -b .remi-oci8
+%patch -P91 -p1 -b .remi-oci8
# upstream patches
# security patches
+%patch -P200 -p1 -b .bug77423
+%patch -P201 -p1 -b .bug80672
+%patch -P202 -p1 -b .bug80710
+%patch -P203 -p1 -b .bug81122
+%patch -P204 -p1 -b .bug76450
+%patch -P205 -p1 -b .bug81211
+%patch -P206 -p1 -b .bug81026
+%patch -P207 -p1 -b .bug79971
+%patch -P208 -p1 -b .bug81719
+%patch -P209 -p1 -b .bug81720
+%patch -P210 -p1 -b .bug81727
+%patch -P211 -p1 -b .bug81726
+%patch -P212 -p1 -b .bug81738
+%patch -P213 -p1 -b .bug81740
+%patch -P214 -p1 -b .bug81744
+%patch -P215 -p1 -b .bug81746
+%patch -P216 -p1 -b .cve0662
+%patch -P217 -p1 -b .cve3247
+%patch -P218 -p1 -b .cve3823
+%patch -P219 -p1 -b .cve3824
+%patch -P220 -p1 -b .cve2756
+%patch -P221 -p1 -b .cve3096
+%patch -P222 -p1 -b .cve5458
+%patch -P223 -p1 -b .cve8925
+%patch -P224 -p1 -b .cve8926
+%patch -P225 -p1 -b .cve8927
+%patch -P226 -p1 -b .cve11236
+%patch -P227 -p1 -b .cve11234
+%patch -P228 -p1 -b .cve8932
+%patch -P229 -p1 -b .cve11233
+%patch -P230 -p1 -b .ghsa4w77
# Fixes for tests
%if 0%{?fedora} >= 25 || 0%{?rhel} >= 6
-%patch300 -p1 -b .datetests
+%patch -P300 -p1 -b .datetests
%endif
%if %{with_libpcre}
if ! pkg-config libpcre --atleast-version 8.34 ; then
# Only apply when system libpcre < 8.34
-%patch301 -p1 -b .pcre834
+%patch -P301 -p1 -b .pcre834
fi
%endif
# WIP patch
# Prevent %%doc confusion over LICENSE files
-cp Zend/LICENSE Zend/ZEND_LICENSE
+cp Zend/LICENSE ZEND_LICENSE
cp TSRM/LICENSE TSRM_LICENSE
%if ! %{with_libgd}
cp ext/gd/libgd/README libgd_README
@@ -1426,13 +1488,8 @@ build --libdir=%{_libdir}/php \
--with-mysqli=shared,mysqlnd \
--with-mysql-sock=%{mysql_sock} \
%if %{with_oci8}
-%ifarch x86_64
- --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \
- --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \
-%else
- --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client/lib,%{oraclever} \
- --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client/lib,%{oraclever} \
-%endif
+ --with-oci8=shared,instantclient,%{_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \
+ --with-pdo-oci=shared,instantclient,%{_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \
%endif
%if %{with_firebird}
--with-interbase=shared \
@@ -1582,13 +1639,8 @@ build --includedir=%{_includedir}/php-zts \
--with-mysql-sock=%{mysql_sock} \
--enable-mysqlnd-threading \
%if %{with_oci8}
-%ifarch x86_64
- --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \
- --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \
-%else
- --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client/lib,%{oraclever} \
- --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client/lib,%{oraclever} \
-%endif
+ --with-oci8=shared,instantclient,%{_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \
+ --with-pdo-oci=shared,instantclient,%{_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \
%endif
%if %{with_firebird}
--with-interbase=shared \
@@ -1658,7 +1710,7 @@ popd
%check
%if %runselftest
-cd build-apache
+cd build-fpm
# Run tests, using the CLI SAPI
export NO_INTERACTION=1 REPORT_EXIT_STATUS=1 MALLOC_CHECK_=2
@@ -1797,8 +1849,8 @@ install -m 755 -d $RPM_BUILD_ROOT/run/php-fpm
install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/php-fpm.service.d
install -Dm 644 %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}/php-fpm.service
%if 0%{?fedora} >= 27 || 0%{?rhel} >= 8
-install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/httpd.service.d/php-fpm.conf
-install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/nginx.service.d/php-fpm.conf
+install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/httpd.service.d/php-fpm.conf
+install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/nginx.service.d/php-fpm.conf
%endif
%else
sed -ne '1,2p' -i $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/php-fpm
@@ -1951,7 +2003,7 @@ sed -e "s/@PHP_APIVER@/%{apiver}%{isasuffix}/" \
%endif
< %{SOURCE3} > macros.php
%if 0%{?fedora} >= 24 || 0%{?rhel} >= 8
-echo '%pecl_xmldir %{_localstatedir}/lib/php/peclxml' >>macros.php
+echo '%%pecl_xmldir %%{_localstatedir}/lib/php/peclxml' >>macros.php
%endif
install -m 644 -D macros.php \
$RPM_BUILD_ROOT%{macrosdir}/macros.php
@@ -2047,6 +2099,19 @@ fi
%endif
+%posttrans common
+cat << EOF
+=====================================================================
+
+ WARNING : PHP 7.2 have reached its "End of Life" in
+ November 2020. Even, if this package includes some of
+ the important security fixes, backported from 8.1, the
+ UPGRADE to a maintained version is very strongly RECOMMENDED.
+
+=====================================================================
+EOF
+
+
%{!?_licensedir:%global license %%doc}
%files
@@ -2065,7 +2130,7 @@ fi
%files common -f files.common
%doc CODING_STANDARDS CREDITS EXTENSIONS NEWS README*
-%license LICENSE TSRM_LICENSE
+%license LICENSE TSRM_LICENSE ZEND_LICENSE
%license libmagic_LICENSE
%license phar_LICENSE
%license timelib_LICENSE
@@ -2090,20 +2155,22 @@ fi
%files cli
%{_bindir}/php
-%{_bindir}/zts-php
%{_bindir}/php-cgi
%{_bindir}/phar.phar
%{_bindir}/phar
# provides phpize here (not in -devel) for pecl command
%{_bindir}/phpize
%{_mandir}/man1/php.1*
-%{_mandir}/man1/zts-php.1*
%{_mandir}/man1/php-cgi.1*
%{_mandir}/man1/phar.1*
%{_mandir}/man1/phar.phar.1*
%{_mandir}/man1/phpize.1*
-%{_mandir}/man1/zts-phpize.1*
%doc sapi/cgi/README* sapi/cli/README
+%if %{with_zts}
+%{_bindir}/zts-php
+%{_mandir}/man1/zts-php.1*
+%{_mandir}/man1/zts-phpize.1*
+%endif
%files dbg
%{_bindir}/phpdbg
@@ -2138,8 +2205,8 @@ fi
%if %{with_systemd}
%{_unitdir}/php-fpm.service
%if 0%{?fedora} >= 27 || 0%{?rhel} >= 8
-%{_unitdir}/httpd.service.d/%{?scl_prefix}php-fpm.conf
-%{_unitdir}/nginx.service.d/%{?scl_prefix}php-fpm.conf
+%config(noreplace) %{_sysconfdir}/systemd/system/httpd.service.d/%{?scl_prefix}php-fpm.conf
+%config(noreplace) %{_sysconfdir}/systemd/system/nginx.service.d/%{?scl_prefix}php-fpm.conf
%endif
%dir %{_sysconfdir}/systemd/system/php-fpm.service.d
%dir %ghost /run/php-fpm
@@ -2169,9 +2236,9 @@ fi
%{_includedir}/php-zts
%{_bindir}/zts-phpize
%{_libdir}/php-zts/build
+%{_mandir}/man1/zts-php-config.1*
%endif
%{_mandir}/man1/php-config.1*
-%{_mandir}/man1/zts-php-config.1*
%{macrosdir}/macros.php
%files embedded
@@ -2213,7 +2280,9 @@ fi
%files mysqlnd -f files.mysqlnd
%files opcache -f files.opcache
%config(noreplace) %{_sysconfdir}/php.d/opcache-default.blacklist
+%if %{with_zts}
%config(noreplace) %{_sysconfdir}/php-zts.d/opcache-default.blacklist
+%endif
%if %{with_oci8}
%files oci8 -f files.oci8
%endif
@@ -2225,10 +2294,133 @@ fi
%changelog
-* Tue Aug 4 2021 Remi Collet <remi@remirepo.net> - 7.2.33-1
+* Tue Nov 26 2024 Remi Collet <remi@remirepo.net> - 7.2.34-25
+- 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> - 7.2.34-24
+- Fix Bypass of CVE-2012-1823, Argument Injection in PHP-CGI
+ CVE-2024-4577
+- Fix Bypass of CVE-2024-4577, Parameter Injection Vulnerability
+ CVE-2024-8926
+- Fix cgi.force_redirect configuration is bypassable due to the environment variable collision
+ CVE-2024-8927
+- Fix Erroneous parsing of multipart form data
+ CVE-2024-8925
+
+* Wed Jul 31 2024 Remi Collet <remi@remirepo.net> - 7.2.34-23
+- use oracle client library version 23.5 on x86_64
+
+* Tue Jun 4 2024 Remi Collet <remi@remirepo.net> - 7.2.34-22
+- Fix filter bypass in filter_var FILTER_VALIDATE_URL
+ CVE-2024-5458
+
+* Wed Apr 10 2024 Remi Collet <remi@remirepo.net> - 7.2.34-21
+- use oracle client library version 21.13 on x86_64, 19.19 on aarch64
+- Fix __Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix
+ CVE-2024-2756
+- Fix password_verify can erroneously return true opening ATO risk
+ CVE-2024-3096
+
+* Thu Sep 21 2023 Remi Collet <remi@remirepo.net> - 7.2.34-20
+- use oracle client library version 21.11 on x86_64, 19.19 on aarch64
+- use official Oracle Instant Client RPM
+
+* Tue Aug 1 2023 Remi Collet <remi@remirepo.net> - 7.2.34-19
+- Fix Security issue with external entity loading in XML without enabling it
+ GHSA-3qrf-m4j2-pcrr CVE-2023-3823
+- Fix Buffer mismanagement in phar_dir_read()
+ GHSA-jqcx-ccgc-xwhv CVE-2023-3824
+- move httpd/nginx wants directive to config files in /etc
+
+* Tue Jun 20 2023 Remi Collet <remi@remirepo.net> - 7.2.34-18
+- fix possible buffer overflow in date
+
+* Wed Jun 7 2023 Remi Collet <remi@remirepo.net> - 7.2.34-17
+- Fix Missing error check and insufficient random bytes in HTTP Digest
+ authentication for SOAP
+ GHSA-76gg-c692-v2mw CVE-2023-3247
+- use oracle client library version 21.10
+- define __phpize and __phpconfig
+
+* Tue Feb 14 2023 Remi Collet <remi@remirepo.net> - 7.2.34-16
+- fix #81744: Password_verify() always return true with some hash
+ CVE-2023-0567
+- fix #81746: 1-byte array overrun in common path resolve code
+ CVE-2023-0568
+- fix DOS vulnerability when parsing multipart request body
+ CVE-2023-0662
+
+* Mon Dec 19 2022 Remi Collet <remi@remirepo.net> - 7.2.34-15
+- pdo: fix #81740: PDO::quote() may return unquoted string
+ CVE-2022-31631
+- use oracle client library version 21.8
+
+* Mon Oct 24 2022 Remi Collet <remi@remirepo.net> - 7.2.34-14
+- hash: fix #81738: buffer overflow in hash_update() on long parameter.
+ CVE-2022-37454
+
+* Tue Sep 27 2022 Remi Collet <remi@remirepo.net> - 7.2.34-13
+- phar: fix #81726 DOS when using quine gzip file. CVE-2022-31628
+- core: fix #81727 Don't mangle HTTP variable names that clash with ones
+ that have a specific semantic meaning. CVE-2022-31629
+- use oracle client library version 21.7
+
+* Tue Jun 7 2022 Remi Collet <remi@remirepo.net> - 7.2.34-11
+- use oracle client library version 21.6
+- mysqlnd: fix #81719: mysqlnd/pdo password buffer overflow. CVE-2022-31626
+- pgsql: fix #81720: Uninitialized array in pg_query_params(). CVE-2022-31625
+
+* Mon Nov 15 2021 Remi Collet <remi@remirepo.net> - 7.2.34-10
+- Fix #79971 special character is breaking the path in xml function
+ CVE-2021-21707
+
+* Wed Oct 20 2021 Remi Collet <remi@remirepo.net> - 7.2.34-9
+- fix PHP-FPM oob R/W in root process leading to priv escalation
+ CVE-2021-21703
+- use libicu version 69
+- use oracle client library version 21.3
+
+* Wed Aug 25 2021 Remi Collet <remi@remirepo.net> - 7.2.34-7
+- Fix #81211 Symlinks are followed when creating PHAR archive
+
+* Mon Jun 28 2021 Remi Collet <remi@remirepo.net> - 7.2.34-6
+- Fix #81122 SSRF bypass in FILTER_VALIDATE_URL
+ CVE-2021-21705
+- Fix #76448 Stack buffer overflow in firebird_info_cb
+- Fix #76449 SIGSEGV in firebird_handle_doer
+- Fix #76450 SIGSEGV in firebird_stmt_execute
+- Fix #76452 Crash while parsing blob data in firebird_fetch_blob
+ CVE-2021-21704
+
+* Wed Apr 28 2021 Remi Collet <remi@remirepo.net> - 7.2.34-4
+- Fix #80710 imap_mail_compose() header injection
+- use oracle client library version 21.1
+
+* Wed Feb 3 2021 Remi Collet <remi@remirepo.net> - 7.2.34-3
+- Fix #80672 Null Dereference in SoapClient
+ CVE-2021-21702
+- better fix for #77423
+
+* Mon Jan 4 2021 Remi Collet <remi@remirepo.net> - 7.2.34-2
+- Fix #77423 FILTER_VALIDATE_URL accepts URLs with invalid userinfo
+ CVE-2020-7071
+
+* Wed Sep 30 2020 Remi Collet <remi@remirepo.net> - 7.2.34-1
+- Update to 7.2.34 - http://www.php.net/releases/7_2_34.php
+
+* Tue Aug 4 2020 Remi Collet <remi@remirepo.net> - 7.2.33-1
- Update to 7.2.33 - http://www.php.net/releases/7_2_33.php
-* Wed Jul 7 2021 Remi Collet <remi@remirepo.net> - 7.2.32-1
+* Tue Jul 7 2020 Remi Collet <remi@remirepo.net> - 7.2.32-1
- Update to 7.2.32 (no change)
- display build system and provider in phpinfo (from 8.0)