[packages/php/PHP_7_1] Rel 28; security fixes from shivammathur/php-src-backports (Homebrew php at 7.1) and Debian ELTS 7.0/7.

arekm arekm at pld-linux.org
Thu Oct 22 11:46:49 CEST 2026


commit 516f27c2ccf8218e9afcb02c9e8b6f0cfa0104ea
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Thu Oct 22 11:46:02 2026 +0200

    Rel 28; security fixes from shivammathur/php-src-backports (Homebrew php at 7.1) and Debian ELTS 7.0/7.3
    CVE-2026-109618/109619 with the full session upload progress fix from upstream 3584a98bda0f

 php-bug74267.patch                      |   86 ++
 php-bug77569.patch                      |   55 +
 php-bug79091.patch                      |   99 ++
 php-bug79330.patch                      |   31 +
 php-bug79877.patch                      |   45 +
 php-bug80710.patch                      |  339 +++++
 php-bug81211.patch                      |  114 ++
 php-cve-2019-11045.patch                |   70 +
 php-cve-2019-11046.patch                |   50 +
 php-cve-2019-11047.patch                |   83 ++
 php-cve-2019-11048.patch                |   75 ++
 php-cve-2019-11050.patch                |   46 +
 php-cve-2019-18218.patch                |   49 +
 php-cve-2020-7059.patch                 |  168 +++
 php-cve-2020-7062.patch                 |   82 ++
 php-cve-2020-7063.patch                 |  115 ++
 php-cve-2020-7064.patch                 |   72 +
 php-cve-2020-7066.patch                 |   24 +
 php-cve-2020-7067.patch                 |   33 +
 php-cve-2020-7068.patch                 |  Bin 0 -> 1945 bytes
 php-cve-2020-7069.patch                 |  197 +++
 php-cve-2020-7070.patch                 |  116 ++
 php-cve-2020-7071.patch                 |  102 ++
 php-cve-2021-21702.patch                |  200 +++
 php-cve-2021-21703.patch                |  397 ++++++
 php-cve-2021-21704.patch                |  Bin 0 -> 12893 bytes
 php-cve-2021-21705.patch                |   65 +
 php-cve-2021-21707.patch                |  136 ++
 php-cve-2022-31625.patch                |   74 ++
 php-cve-2022-31626.patch                |   27 +
 php-cve-2022-31628.patch                |  Bin 0 -> 4325 bytes
 php-cve-2022-31629.patch                |   59 +
 php-cve-2022-31631.patch                |   53 +
 php-cve-2023-0567.patch                 |  179 +++
 php-cve-2023-0568.patch                 |   66 +
 php-cve-2023-0662.patch                 |   83 ++
 php-cve-2023-3247.patch                 |   98 ++
 php-cve-2023-3823.patch                 |  368 +++++
 php-cve-2023-3824.patch                 |   89 ++
 php-cve-2024-11233.patch                |   68 +
 php-cve-2024-11234.patch                |   94 ++
 php-cve-2024-11236.patch                |  110 ++
 php-cve-2024-2756.patch                 |  162 +++
 php-cve-2024-3096.patch                 |   55 +
 php-cve-2024-5458.patch                 |  150 +++
 php-cve-2024-8925.patch                 |  187 +++
 php-cve-2024-8927.patch                 |   58 +
 php-cve-2024-8929.patch                 | 2211 +++++++++++++++++++++++++++++++
 php-cve-2024-8932.patch                 |  138 ++
 php-cve-2025-1217.patch                 |  905 +++++++++++++
 php-cve-2025-1219.patch                 |  350 +++++
 php-cve-2025-1220.patch                 |  150 +++
 php-cve-2025-14181.patch                |  397 ++++++
 php-cve-2025-1734.patch                 |  296 +++++
 php-cve-2025-1735.patch                 |  452 +++++++
 php-cve-2025-1736.patch                 |  450 +++++++
 php-cve-2025-1861.patch                 |  342 +++++
 php-cve-2025-6491.patch                 |  100 ++
 php-cve-2026-109618-post_max_size.patch |   35 +
 php-cve-2026-109618-session.patch       |  932 +++++++++++++
 php-cve-2026-109618.patch               |  813 ++++++++++++
 php-cve-2026-14355.patch                |   92 ++
 php-cve-2026-17543.patch                |  199 +++
 php-cve-2026-6103.patch                 |  394 ++++++
 php-cve-2026-6722.patch                 |  108 ++
 php-cve-2026-6735.patch                 |  291 ++++
 php-cve-2026-7258.patch                 | 1583 ++++++++++++++++++++++
 php-cve-2026-7260.patch                 |  Bin 0 -> 240377 bytes
 php-cve-2026-7261.patch                 |  117 ++
 php-cve-2026-7262.patch                 |   78 ++
 php-cve-2026-7568.patch                 |   83 ++
 php-cve-2026-91765.patch                |  437 ++++++
 php-cve-2026-91766.patch                |  563 ++++++++
 php-cve-2026-91767.patch                |  113 ++
 php-cve-2026-91768.patch                |  143 ++
 php-cve-2026-91769.patch                |  374 ++++++
 php-cve-2026-92842.patch                |   85 ++
 php-cve-2026-9672.patch                 |   44 +
 php-gh23467.patch                       |  144 ++
 php-ghsa-4w77-75f9-2c8w.patch           |   87 ++
 php-ghsa-ch8v-r6jh-4vvr.patch           |   49 +
 php-ghsa-wg4p-4hqh-c3g9.patch           |   92 ++
 php-tests-firebird-payload-server.patch |  141 ++
 php-tests-fpm-logtool.patch             |   29 +
 php-tests-http-server-8.0.patch         |  140 ++
 php-tests-openssl-certgen.patch         |  415 ++++++
 php-tests-openssl-server-8.1.patch      |  218 +++
 php-zstr_max_len.patch                  |   26 +
 php.spec                                |  188 ++-
 89 files changed, 18632 insertions(+), 1 deletion(-)
---
diff --git a/php.spec b/php.spec
index 3c5fbf2..273afd2 100644
--- a/php.spec
+++ b/php.spec
@@ -151,7 +151,7 @@ Summary(ru.UTF-8):	PHP Версии 7 - язык препроцессирова
 Summary(uk.UTF-8):	PHP Версії 7 - мова препроцесування HTML-файлів, виконувана на сервері
 Name:		%{orgname}%{php_suffix}
 Version:	7.1.33
-Release:	27
+Release:	28
 Epoch:		4
 # All files licensed under PHP version 3.01, except
 # Zend is licensed under Zend
@@ -225,6 +225,102 @@ Patch78:	includes.patch
 Patch79:	configure.patch
 Patch80:	ac_prog_sed.patch
 Patch81:	opcache-revalidate-path-once.patch
+# Patch200+: security backports for EOL 7.1, one file per advisory, in this order:
+# https://github.com/shivammathur/php-src-backports/tree/PHP-7.1-security-backports
+# (also used by Homebrew php at 7.1), then Debian ELTS php7.0 7.0.33-0+deb9u26 and
+# php7.3 7.3.31-1~deb10u16, https://deb.freexian.com/extended-lts/pool/main/p/;
+# the source of each part is named in the patch header
+Patch200:	php-cve-2019-18218.patch
+Patch201:	php-cve-2019-11046.patch
+Patch202:	php-cve-2019-11045.patch
+Patch203:	php-cve-2019-11050.patch
+Patch204:	php-cve-2019-11047.patch
+Patch205:	php-bug79091.patch
+Patch206:	php-cve-2020-7059.patch
+Patch207:	php-bug77569.patch
+Patch208:	php-cve-2020-7062.patch
+Patch209:	php-cve-2020-7063.patch
+Patch210:	php-cve-2020-7064.patch
+Patch211:	php-cve-2020-7066.patch
+Patch212:	php-bug79330.patch
+Patch213:	php-cve-2020-7067.patch
+Patch214:	php-cve-2019-11048.patch
+Patch215:	php-cve-2020-7068.patch
+Patch216:	php-bug79877.patch
+Patch217:	php-cve-2020-7069.patch
+Patch218:	php-cve-2020-7070.patch
+Patch219:	php-cve-2020-7071.patch
+Patch220:	php-cve-2021-21702.patch
+Patch221:	php-bug80710.patch
+Patch222:	php-cve-2021-21705.patch
+Patch223:	php-cve-2021-21704.patch
+Patch224:	php-bug81211.patch
+Patch225:	php-cve-2021-21703.patch
+Patch226:	php-cve-2021-21707.patch
+Patch227:	php-cve-2022-31625.patch
+Patch228:	php-cve-2022-31626.patch
+Patch229:	php-cve-2022-31629.patch
+Patch230:	php-cve-2022-31628.patch
+Patch231:	php-cve-2022-31631.patch
+Patch232:	php-cve-2023-0567.patch
+Patch233:	php-cve-2023-0568.patch
+Patch234:	php-cve-2023-0662.patch
+Patch235:	php-cve-2023-3247.patch
+Patch236:	php-cve-2023-3824.patch
+Patch237:	php-cve-2023-3823.patch
+Patch238:	php-cve-2024-2756.patch
+Patch239:	php-cve-2024-3096.patch
+Patch240:	php-cve-2024-5458.patch
+Patch241:	php-cve-2024-8927.patch
+Patch242:	php-cve-2024-8925.patch
+Patch243:	php-cve-2024-11236.patch
+Patch244:	php-zstr_max_len.patch
+Patch245:	php-cve-2024-11234.patch
+Patch246:	php-cve-2024-8932.patch
+Patch247:	php-cve-2024-11233.patch
+Patch248:	php-bug74267.patch
+Patch249:	php-ghsa-4w77-75f9-2c8w.patch
+Patch250:	php-cve-2026-6722.patch
+Patch251:	php-cve-2026-7261.patch
+Patch252:	php-cve-2026-7262.patch
+Patch253:	php-cve-2026-7568.patch
+Patch254:	php-cve-2026-6735.patch
+Patch255:	php-cve-2026-14355.patch
+Patch256:	php-cve-2024-8929.patch
+Patch257:	php-tests-http-server-8.0.patch
+Patch258:	php-tests-openssl-server-8.1.patch
+Patch259:	php-cve-2025-1217.patch
+Patch260:	php-cve-2025-1219.patch
+Patch261:	php-cve-2025-1734.patch
+Patch262:	php-cve-2025-1736.patch
+Patch263:	php-cve-2025-1861.patch
+Patch264:	php-ghsa-wg4p-4hqh-c3g9.patch
+Patch265:	php-cve-2025-1220.patch
+Patch266:	php-cve-2025-1735.patch
+Patch267:	php-cve-2025-6491.patch
+Patch268:	php-cve-2026-7258.patch
+Patch269:	php-cve-2026-9672.patch
+Patch270:	php-cve-2026-17543.patch
+Patch271:	php-cve-2026-7260.patch
+Patch272:	php-cve-2026-92842.patch
+Patch273:	php-tests-fpm-logtool.patch
+Patch274:	php-cve-2026-91768.patch
+Patch275:	php-cve-2026-91769.patch
+Patch276:	php-cve-2026-91767.patch
+Patch277:	php-cve-2026-91766.patch
+Patch278:	php-cve-2026-91765.patch
+Patch279:	php-cve-2025-14181.patch
+Patch280:	php-cve-2026-6103.patch
+Patch281:	php-ghsa-ch8v-r6jh-4vvr.patch
+Patch282:	php-gh23467.patch
+Patch283:	php-cve-2026-109618.patch
+# post_max_size part of https://github.com/php/php-src/commit/01a40e89fbfc499936e3b05888d8f00bfde886df, missing in the minimal EOL fix
+Patch284:	php-cve-2026-109618-post_max_size.patch
+# session part of https://github.com/php/php-src/commit/3584a98bda0f instead of disabling upload progress
+Patch285:	php-cve-2026-109618-session.patch
+# test infrastructure the backported firebird and openssl SAN tests need
+Patch286:	php-tests-firebird-payload-server.patch
+Patch287:	php-tests-openssl-certgen.patch
 URL:		https://www.php.net/
 %{?with_interbase:%{!?with_interbase_inst:BuildRequires:	Firebird-devel >= 1.0.2.908-2}}
 %{?with_pspell:BuildRequires:	aspell-devel >= 2:0.50.0}
@@ -280,6 +376,8 @@ BuildRequires:	pam-devel
 BuildRequires:	pkgconfig
 %{?with_pgsql:BuildRequires:	postgresql-devel}
 BuildRequires:	readline-devel
+# security patches change *.re scanners without the generated *.c
+BuildRequires:	re2c >= 0.13.4
 %{?with_recode:BuildRequires:	recode-devel >= 3.5d-3}
 BuildRequires:	rpm >= 4.4.9-56
 BuildRequires:	rpm-build >= 4.4.0
@@ -2057,6 +2155,94 @@ cp -p php.ini-production php.ini
 %patch -P79 -p1
 %patch -P80 -p1
 %patch -P81 -p1
+%patch -P200 -p1
+%patch -P201 -p1
+%patch -P202 -p1
+%patch -P203 -p1
+%patch -P204 -p1
+%patch -P205 -p1
+%patch -P206 -p1
+%patch -P207 -p1
+%patch -P208 -p1
+%patch -P209 -p1
+%patch -P210 -p1
+%patch -P211 -p1
+%patch -P212 -p1
+%patch -P213 -p1
+%patch -P214 -p1
+%patch -P215 -p1
+%patch -P216 -p1
+%patch -P217 -p1
+%patch -P218 -p1
+%patch -P219 -p1
+%patch -P220 -p1
+%patch -P221 -p1
+%patch -P222 -p1
+%patch -P223 -p1
+%patch -P224 -p1
+%patch -P225 -p1
+%patch -P226 -p1
+%patch -P227 -p1
+%patch -P228 -p1
+%patch -P229 -p1
+%patch -P230 -p1
+%patch -P231 -p1
+%patch -P232 -p1
+%patch -P233 -p1
+%patch -P234 -p1
+%patch -P235 -p1
+%patch -P236 -p1
+%patch -P237 -p1
+%patch -P238 -p1
+%patch -P239 -p1
+%patch -P240 -p1
+%patch -P241 -p1
+%patch -P242 -p1
+%patch -P243 -p1
+%patch -P244 -p1
+%patch -P245 -p1
+%patch -P246 -p1
+%patch -P247 -p1
+%patch -P248 -p1
+%patch -P249 -p1
+%patch -P250 -p1
+%patch -P251 -p1
+%patch -P252 -p1
+%patch -P253 -p1
+%patch -P254 -p1
+%patch -P255 -p1
+%patch -P256 -p1
+%patch -P257 -p1
+%patch -P258 -p1
+%patch -P259 -p1
+%patch -P260 -p1
+%patch -P261 -p1
+%patch -P262 -p1
+%patch -P263 -p1
+%patch -P264 -p1
+%patch -P265 -p1
+%patch -P266 -p1
+%patch -P267 -p1
+%patch -P268 -p1
+%patch -P269 -p1
+%patch -P270 -p1
+%patch -P271 -p1
+%patch -P272 -p1
+%patch -P273 -p1
+%patch -P274 -p1
+%patch -P275 -p1
+%patch -P276 -p1
+%patch -P277 -p1
+%patch -P278 -p1
+%patch -P279 -p1
+%patch -P280 -p1
+%patch -P281 -p1
+%patch -P282 -p1
+%patch -P283 -p1
+%patch -P284 -p1
+%patch -P285 -p1
+%patch -P286 -p1
+%patch -P287 -p1
 
 sed -E -i -e '1s,#!\s*/usr/bin/env\s+(.*),#!%{__bindir}\1,' \
       run-tests.php
diff --git a/php-bug74267.patch b/php-bug74267.patch
new file mode 100644
index 0000000..5d0d549
--- /dev/null
+++ b/php-bug74267.patch
@@ -0,0 +1,86 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 8 Jun 2020 23:19:43 +0200
+Subject: 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)
+(cherry picked from commit d149a44b005e0d24208b0bd0f7179dfbbfffefb1)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/c173da70f301433a5d49df1d53a7930f92974820
+---
+ ext/standard/filters.c                   |  7 +++----
+ ext/standard/tests/filters/bug74267.phpt | 26 ++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 4 deletions(-)
+
+diff --git a/ext/standard/filters.c b/ext/standard/filters.c
+index e4f25a60..f212ac22 100644
+--- a/ext/standard/filters.c
++++ b/ext/standard/filters.c
+@@ -793,7 +793,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;
+ 	}
+ 
+@@ -1021,7 +1021,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;
+ 		}
+@@ -1118,8 +1118,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 00000000..17d7996b
+--- /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
diff --git a/php-bug77569.patch b/php-bug77569.patch
new file mode 100644
index 0000000..42e77f9
--- /dev/null
+++ b/php-bug77569.patch
@@ -0,0 +1,55 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Thu, 13 Feb 2020 15:13:26 +0100
+Subject: Fix #77569: Write Acess Violation in DomImplementation
+
+We must not assume that the zval IS_STRING.
+
+(cherry picked from commit cec8b24c848bab8562c82422f3692c193f0afcdb)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/2ee92db814827e4484d997c91b75034995e6f99e
+
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Fri, 14 Feb 2020 09:21:13 +0100
+Subject: Fix typo in recent bugfix
+
+(cherry picked from commit 8308196c97418ba4c8381bed0962ae160623027a)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/08374ddcc45940dc341afc68de505599f1839e64
+---
+ ext/dom/document.c          |  2 +-
+ ext/dom/tests/bug77569.phpt | 14 ++++++++++++++
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/ext/dom/document.c b/ext/dom/document.c
+index c9e1802f..11ef4aa8 100644
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -341,7 +341,7 @@ int dom_document_encoding_write(dom_object *obj, zval *newval)
+ 
+ 	str = zval_get_string(newval);
+ 
+-	handler = xmlFindCharEncodingHandler(Z_STRVAL_P(newval));
++	handler = xmlFindCharEncodingHandler(ZSTR_VAL(str));
+ 
+     if (handler != NULL) {
+ 		xmlCharEncCloseFunc(handler);
+diff --git a/ext/dom/tests/bug77569.phpt b/ext/dom/tests/bug77569.phpt
+new file mode 100644
+index 00000000..9eef2af6
+--- /dev/null
++++ b/ext/dom/tests/bug77569.phpt
+@@ -0,0 +1,14 @@
++--TEST--
++Bug #77569 (Write Access Violation in DomImplementation)
++--SKIPIF--
++<?php
++if (!extension_loaded('dom')) die('skip dom extension not available');
++?>
++--FILE--
++<?php
++$imp = new DOMImplementation;
++$dom = $imp->createDocument("", "");
++$dom->encoding = null;
++?>
++--EXPECTF--
++Warning: main(): Invalid Document Encoding in %s on line %d
diff --git a/php-bug79091.patch b/php-bug79091.patch
new file mode 100644
index 0000000..b1a4816
--- /dev/null
+++ b/php-bug79091.patch
@@ -0,0 +1,99 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 20 Jan 2020 18:05:00 +0100
+Subject: Fix #79091: heap use-after-free in session_create_id()
+
+If the `new_id` is released, we must not use it again.
+
+(cherry picked from commit f79c7742746907d676989cb7f97fb4f7cd26789f)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/35c8a53c098cd828413a80ed7964146d50161c6c
+---
+ ext/session/session.c           |  1 +
+ ext/session/tests/bug79091.phpt | 67 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+)
+
+diff --git a/ext/session/session.c b/ext/session/session.c
+index 8d60ac24..44ecb85f 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -2049,6 +2049,7 @@ static PHP_FUNCTION(session_create_id)
+ 				/* Detect collision and retry */
+ 				if (PS(mod)->s_validate_sid(&PS(mod_data), new_id) == FAILURE) {
+ 					zend_string_release(new_id);
++					new_id = NULL;
+ 					continue;
+ 				}
+ 				break;
+diff --git a/ext/session/tests/bug79091.phpt b/ext/session/tests/bug79091.phpt
+new file mode 100644
+index 00000000..1d144271
+--- /dev/null
++++ b/ext/session/tests/bug79091.phpt
+@@ -0,0 +1,67 @@
++--TEST--
++Bug #79091 (heap use-after-free in session_create_id())
++--SKIPIF--
++<?php
++if (!extension_loaded('session')) die('skip session extension not available');
++?>
++--FILE--
++<?php
++class MySessionHandler implements SessionHandlerInterface, SessionIdInterface, SessionUpdateTimestampHandlerInterface
++{
++    public function close()
++    {
++        return true;
++    }
++
++    public function destroy($session_id)
++    {
++        return true;
++    }
++
++    public function gc($maxlifetime)
++    {
++        return true;
++    }
++
++    public function open($save_path, $session_name)
++    {
++        return true;
++    }
++
++    public function read($session_id)
++    {
++        return '';
++    }
++
++    public function write($session_id, $session_data)
++    {
++        return true;
++    }
++
++    public function create_sid()
++    {
++        return uniqid();
++    }
++
++    public function updateTimestamp($key, $val)
++    {
++        return true;
++    }
++
++    public function validateId($key)
++    {
++        return false;
++    }
++}
++
++ob_start();
++var_dump(session_set_save_handler(new MySessionHandler()));
++var_dump(session_start());
++ob_flush();
++session_create_id();
++?>
++--EXPECTF--
++bool(true)
++bool(true)
++
++Warning: session_create_id(): Failed to create new ID in %s on line %d
diff --git a/php-bug79330.patch b/php-bug79330.patch
new file mode 100644
index 0000000..cbfd98b
--- /dev/null
+++ b/php-bug79330.patch
@@ -0,0 +1,31 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 13 Apr 2020 21:00:44 -0700
+Subject: Fix bug #79330 - make all execution modes consistent in rejecting \0
+
+(cherry picked from commit 14fcc813948254b84f382ff537247d8a7e5e0e62)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/edd1ff390be461e9ae5c69237358beddee4655a4
+---
+ ext/standard/exec.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/ext/standard/exec.c b/ext/standard/exec.c
+index 8af11801..02d9539f 100644
+--- a/ext/standard/exec.c
++++ b/ext/standard/exec.c
+@@ -524,6 +524,15 @@ PHP_FUNCTION(shell_exec)
+ 		return;
+ 	}
+ 
++	if (!command_len) {
++		php_error_docref(NULL, E_WARNING, "Cannot execute a blank command");
++		RETURN_FALSE;
++	}
++	if (strlen(command) != command_len) {
++		php_error_docref(NULL, E_WARNING, "NULL byte detected. Possible attack");
++		RETURN_FALSE;
++	}
++
+ #ifdef PHP_WIN32
+ 	if ((in=VCWD_POPEN(command, "rt"))==NULL) {
+ #else
diff --git a/php-bug79877.patch b/php-bug79877.patch
new file mode 100644
index 0000000..e7850ae
--- /dev/null
+++ b/php-bug79877.patch
@@ -0,0 +1,45 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Tue, 21 Jul 2020 11:07:43 +0200
+Subject: Fix #79877: getimagesize function silently truncates after a null byte
+
+We have to check for NUL bytes if `getimagesize()` has been called.
+
+(cherry picked from commit ff577b04c0d250473a0ef46f8e332960fec3ca2c)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/2c27d6bdd38bd8c4a27da5aded3477457e72c639
+---
+ ext/standard/image.c                   | 5 +++++
+ ext/standard/tests/image/bug79877.phpt | 9 +++++++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/ext/standard/image.c b/ext/standard/image.c
+index 6c613382..94985717 100644
+--- a/ext/standard/image.c
++++ b/ext/standard/image.c
+@@ -1474,6 +1474,11 @@ static void php_getimagesize_from_any(INTERNAL_FUNCTION_PARAMETERS, int mode) {
+ 			return;
+ 	}
+ 
++	if (mode == FROM_PATH && CHECK_NULL_PATH(input, input_len)) {
++		php_error_docref(NULL, E_WARNING, "Invalid path");
++		return;
++	}
++
+ 	if (argc == 2) {
+ 		zval_dtor(info);
+ 		array_init(info);
+diff --git a/ext/standard/tests/image/bug79877.phpt b/ext/standard/tests/image/bug79877.phpt
+new file mode 100644
+index 00000000..92e93e59
+--- /dev/null
++++ b/ext/standard/tests/image/bug79877.phpt
+@@ -0,0 +1,9 @@
++--TEST--
++Bug #79877 (getimagesize function silently truncates after a null byte)
++--FILE--
++<?php
++var_dump(getimagesize("/tmp/a.png\0xx"));
++?>
++--EXPECTF--
++Warning: getimagesize(): Invalid path in %s on line %d
++NULL
diff --git a/php-bug80710.patch b/php-bug80710.patch
new file mode 100644
index 0000000..23a614e
--- /dev/null
+++ b/php-bug80710.patch
@@ -0,0 +1,339 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Fri, 5 Feb 2021 22:51:41 +0100
+Subject: 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)
+(cherry picked from commit 9017896cccefe000938f80b49361b1c183849922)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b259bf84d8ee47c5d0fd990dbf67d3930572f49d
+---
+ 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(+)
+
+diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
+index 6ce4b781..7de074ae 100644
+--- a/ext/imap/php_imap.c
++++ b/ext/imap/php_imap.c
+@@ -3531,6 +3531,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)
+@@ -3551,6 +3568,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"); \
+@@ -3559,46 +3583,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));
+ 	}
+ 
+@@ -3608,6 +3643,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);
+@@ -3640,6 +3676,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");
+@@ -3650,9 +3687,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;
+@@ -3663,18 +3702,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);
+ 			}
+@@ -3682,9 +3725,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;
+@@ -3713,6 +3758,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) {
+@@ -3743,6 +3789,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);
+@@ -3754,9 +3801,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;
+@@ -3767,18 +3816,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);
+ 			}
+@@ -3786,9 +3839,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;
+@@ -3817,6 +3872,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 00000000..5cdee034
+--- /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 at example.com\n From : X-INJECTED";
++$envelope["to"]  = "foo at example.com\nFrom: X-INJECTED";
++$envelope["cc"]  = "bar at example.com\nFrom: X-INJECTED";
++$envelope["subject"]  = "bar at example.com\n\n From : X-INJECTED";
++$envelope["x-remail"]  = "bar at example.com\nFrom: X-INJECTED";
++$envelope["something"]  = "bar at 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 00000000..b9f2fa85
+--- /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 at example.com\n From : X-INJECTED";
++$envelope["to"]  = "foo at example.com\nFrom: X-INJECTED";
++$envelope["cc"]  = "bar at example.com\nFrom: X-INJECTED";
++$envelope["subject"]  = "bar at 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 at 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
diff --git a/php-bug81211.patch b/php-bug81211.patch
new file mode 100644
index 0000000..6f27f68
--- /dev/null
+++ b/php-bug81211.patch
@@ -0,0 +1,114 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 23 Aug 2021 13:42:17 +0200
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/44cd62fa4427934a511f9d0c6423e9dc471009c5
+
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 23 Aug 2021 23:43:32 -0700
+Subject: Fix test
+
+(cherry picked from commit b815645aac76b494dc119fa6b88de32fa9bcccf1)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/072295b550665a57bc4dd7e7a0bd7511c5ba3631
+---
+ ext/phar/phar_object.c                           |  3 +-
+ ext/phar/tests/bug81211.phpt                     | 45 ++++++++++++++++++++++
+ ext/standard/tests/file/windows_links/common.inc |  9 ++++-
+ 3 files changed, 55 insertions(+), 2 deletions(-)
+
+diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
+index b22a6acf..d639c3b1 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 00000000..96b1401b
+--- /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
++ at unlink(__DIR__ . '/bug81211/archive.tar');
++ at unlink(__DIR__ . '/bug81211/foo/symlink');
++ at unlink(__DIR__ . '/bug81211/foobar/file');
++ at rmdir(__DIR__ . '/bug81211/foo');
++ at rmdir(__DIR__ . '/bug81211/foobar');
++ at rmdir(__DIR__ . '/bug81211');
++?>
++--EXPECTF--
++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"
+diff --git a/ext/standard/tests/file/windows_links/common.inc b/ext/standard/tests/file/windows_links/common.inc
+index 505368b8..caa3758d 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');
++	}
++}
diff --git a/php-cve-2019-11045.patch b/php-cve-2019-11045.patch
new file mode 100644
index 0000000..e675bba
--- /dev/null
+++ b/php-cve-2019-11045.patch
@@ -0,0 +1,70 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 25 Nov 2019 16:56:34 +0100
+Subject: Fix #78863: DirectoryIterator class silently truncates after a null byte
+
+Since the constructor of DirectoryIterator and friends is supposed to
+accepts paths (i.e. strings without NUL bytes), we must not accept
+arbitrary strings.
+
+(cherry picked from commit a5a15965da23c8e97657278fc8dfbf1dfb20c016)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/e7d893348f02c662b6b3283ec77eb3c3cbc9a46e
+---
+ ext/spl/spl_directory.c     |  4 ++--
+ ext/spl/tests/bug78863.phpt | 31 +++++++++++++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 2 deletions(-)
+
+diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
+index 748b1549..636e26a5 100644
+--- a/ext/spl/spl_directory.c
++++ b/ext/spl/spl_directory.c
+@@ -685,10 +685,10 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long cto
+ 
+ 	if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
+ 		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
+-		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &len, &flags);
++		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);
+ 	} else {
+ 		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
+-		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &path, &len);
++		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len);
+ 	}
+ 	if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
+ 		flags |= SPL_FILE_DIR_SKIPDOTS;
+diff --git a/ext/spl/tests/bug78863.phpt b/ext/spl/tests/bug78863.phpt
+new file mode 100644
+index 00000000..dc88d98d
+--- /dev/null
++++ b/ext/spl/tests/bug78863.phpt
+@@ -0,0 +1,31 @@
++--TEST--
++Bug #78863 (DirectoryIterator class silently truncates after a null byte)
++--FILE--
++<?php
++$dir = __DIR__ . '/bug78863';
++mkdir($dir);
++touch("$dir/bad");
++mkdir("$dir/sub");
++touch("$dir/sub/good");
++
++$it = new DirectoryIterator(__DIR__ . "/bug78863\0/sub");
++foreach ($it as $fileinfo) {
++    if (!$fileinfo->isDot()) {
++        var_dump($fileinfo->getFilename());
++    }
++}
++?>
++--EXPECTF--
++Fatal error: Uncaught UnexpectedValueException: DirectoryIterator::__construct() expects parameter 1 to be a valid path, string given in %s:%d
++Stack trace:
++#0 %s(%d): DirectoryIterator->__construct('%s')
++#1 {main}
++  thrown in %s on line %d
++--CLEAN--
++<?php
++$dir = __DIR__ . '/bug78863';
++unlink("$dir/sub/good");
++rmdir("$dir/sub");
++unlink("$dir/bad");
++rmdir($dir);
++?>
diff --git a/php-cve-2019-11046.patch b/php-cve-2019-11046.patch
new file mode 100644
index 0000000..1f14ade
--- /dev/null
+++ b/php-cve-2019-11046.patch
@@ -0,0 +1,50 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Tue, 17 Dec 2019 10:46:45 +0100
+Subject: Fix #78878: Buffer underflow in bc_shift_addsub
+
+We must not rely on `isdigit()` to detect digits, since we only support
+decimal ASCII digits in the following processing.
+
+(cherry picked from commit eb23c6008753b1cdc5359dead3a096dce46c9018)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/fc9982062527b1a58206d826449273dd2bd850cf
+---
+ ext/bcmath/libbcmath/src/str2num.c |  4 ++--
+ ext/bcmath/tests/bug78878.phpt     | 13 +++++++++++++
+ 2 files changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c
+index f38d3415..03aec159 100644
+--- a/ext/bcmath/libbcmath/src/str2num.c
++++ b/ext/bcmath/libbcmath/src/str2num.c
+@@ -57,9 +57,9 @@ bc_str2num (bc_num *num, char *str, int scale)
+   zero_int = FALSE;
+   if ( (*ptr == '+') || (*ptr == '-'))  ptr++;  /* Sign */
+   while (*ptr == '0') ptr++;			/* Skip leading zeros. */
+-  while (isdigit((int)*ptr)) ptr++, digits++;	/* digits */
++  while (*ptr >= '0' && *ptr <= '9') ptr++, digits++;	/* digits */
+   if (*ptr == '.') ptr++;			/* decimal point */
+-  while (isdigit((int)*ptr)) ptr++, strscale++;	/* digits */
++  while (*ptr >= '0' && *ptr <= '9') ptr++, strscale++;	/* digits */
+   if ((*ptr != '\0') || (digits+strscale == 0))
+     {
+       *num = bc_copy_num (BCG(_zero_));
+diff --git a/ext/bcmath/tests/bug78878.phpt b/ext/bcmath/tests/bug78878.phpt
+new file mode 100644
+index 00000000..2c9d72b9
+--- /dev/null
++++ b/ext/bcmath/tests/bug78878.phpt
+@@ -0,0 +1,13 @@
++--TEST--
++Bug #78878 (Buffer underflow in bc_shift_addsub)
++--SKIPIF--
++<?php
++if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
++?>
++--FILE--
++<?php
++print @bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4));
++?>
++--EXPECT--
++bc math warning: non-zero scale in modulus
++0
diff --git a/php-cve-2019-11047.patch b/php-cve-2019-11047.patch
new file mode 100644
index 0000000..fee3e1d
--- /dev/null
+++ b/php-cve-2019-11047.patch
@@ -0,0 +1,83 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 16 Dec 2019 00:10:39 -0800
+Subject: Fixed bug #78910
+
+(cherry picked from commit d348cfb96f2543565691010ade5e0346338be5a7)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/e5c13f8716507a1210bd0ed6550c3b29fb8b2117
+
+From: Remi Collet <remi at remirepo.net>
+Date: Tue, 17 Dec 2019 15:07:18 +0100
+Subject: relax tests
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/0d68020ffa1eef58df2bf845f8638646e840a86f
+---
+ ext/exif/exif.c              |  3 ++-
+ ext/exif/tests/bug76557.phpt |  2 +-
+ ext/exif/tests/bug78910.phpt | 17 +++++++++++++++++
+ ext/spl/tests/bug54291.phpt  |  2 +-
+ 4 files changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index c9ebaa7b..406fee4f 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2749,7 +2749,8 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
+ 			continue;
+ 		if (maker_note->model && (!ImageInfo->model || strcmp(maker_note->model, ImageInfo->model)))
+ 			continue;
+-		if (maker_note->id_string && strncmp(maker_note->id_string, value_ptr, maker_note->id_string_len))
++		if (maker_note->id_string && value_len >= maker_note->id_string_len
++				&& strncmp(maker_note->id_string, value_ptr, maker_note->id_string_len))
+ 			continue;
+ 		break;
+ 	}
+diff --git a/ext/exif/tests/bug76557.phpt b/ext/exif/tests/bug76557.phpt
+index 4553b627..08bd2d73 100644
+--- a/ext/exif/tests/bug76557.phpt
++++ b/ext/exif/tests/bug76557.phpt
+@@ -70,7 +70,7 @@ Warning: exif_read_data(bug76557.jpg): Process tag(x3030=UndefinedTa): Illegal f
+ 
+ Warning: exif_read_data(bug76557.jpg): Process tag(x3030=UndefinedTa): Illegal format code 0x3030, suppose BYTE in %sbug76557.php on line %d
+ 
+-Warning: exif_read_data(bug76557.jpg): Process tag(x3030=UndefinedTa): Illegal pointer offset(x30303030 + x30303030 = x60606060 > x00EE) in %sbug76557.php on line %d
++Warning: exif_read_data(bug76557.jpg): Process tag(x3030=UndefinedTa): Illegal pointer offset(x30303030 + x30303030 = x60606060 > x%s) in %sbug76557.php on line %d
+ 
+ Warning: exif_read_data(bug76557.jpg): File structure corrupted in %sbug76557.php on line %d
+ 
+diff --git a/ext/exif/tests/bug78910.phpt b/ext/exif/tests/bug78910.phpt
+new file mode 100644
+index 00000000..7770df51
+--- /dev/null
++++ b/ext/exif/tests/bug78910.phpt
+@@ -0,0 +1,17 @@
++--TEST--
++Bug #78910: Heap-buffer-overflow READ in exif (OSS-Fuzz #19044)
++--FILE--
++<?php
++
++var_dump(exif_read_data('data:image/jpg;base64,TU0AKgAAAAwgICAgAAIBDwAEAAAAAgAAACKSfCAgAAAAAEZVSklGSUxN'));
++
++?>
++--EXPECTF--
++Notice: exif_read_data(%s): Read from TIFF: tag(0x927C, MakerNote  ): Illegal format code 0x2020, switching to BYTE in %s on line %d
++
++Warning: exif_read_data(%s): Process tag(x927C=MakerNote  ): Illegal format code 0x2020, suppose BYTE in %s on line %d
++
++Warning: exif_read_data(%s): IFD data too short: 0x0000 offset 0x000C in %s on line %d
++
++Warning: exif_read_data(%s): Invalid TIFF file in %s on line %d
++bool(false)
+diff --git a/ext/spl/tests/bug54291.phpt b/ext/spl/tests/bug54291.phpt
+index b15a3723..655291fd 100644
+--- a/ext/spl/tests/bug54291.phpt
++++ b/ext/spl/tests/bug54291.phpt
+@@ -5,7 +5,7 @@ Bug #54291 (Crash iterating DirectoryIterator for dir name starting with \0)
+ $dir = new DirectoryIterator("\x00/abc");
+ $dir->isFile();
+ --EXPECTF--
+-Fatal error: Uncaught UnexpectedValueException: Failed to open directory "" in %s:%d
++Fatal error: Uncaught UnexpectedValueException: %s in %s:%d
+ Stack trace:
+ #0 %s(%d): DirectoryIterator->__construct('\x00/abc')
+ #1 {main}
diff --git a/php-cve-2019-11048.patch b/php-cve-2019-11048.patch
new file mode 100644
index 0000000..c731c36
--- /dev/null
+++ b/php-cve-2019-11048.patch
@@ -0,0 +1,75 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Wed, 18 Mar 2020 10:26:53 +0100
+Subject: Fix #78875: Long filenames cause OOM and temp files are not cleaned
+
+We must not cast `size_t` to `int` (unless the `size_t` value is
+guaranteed to be less than or equal to `INT_MAX`).  In this case we can
+declare `array_len` as `size_t` in the first place.
+
+(cherry picked from commit 1c9bd513ac5c7c1d13d7f0dfa7c16a7ad2ce0f87)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/d856f7b27eef0249abc6fd2f87cca379b48b815e
+
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Wed, 18 Mar 2020 10:57:42 +0100
+Subject: Fix #78876: Long variables cause OOM and temp files are not cleaned
+
+We use the proper type for size calculations, which is `size_t`.
+
+(cherry picked from commit 3c8582ca4b8e84e5647220b647914876d2c3b124)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/29b3876a0aad27a65e853fd0be4bdc7647dee444
+---
+ main/rfc1867.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index b930e07a..1742b9c0 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -616,7 +616,7 @@ static void *php_ap_memstr(char *haystack, int haystacklen, char *needle, int ne
+ }
+ 
+ /* read until a boundary condition */
+-static int multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes, int *end)
++static size_t multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes, int *end)
+ {
+ 	size_t len, max;
+ 	char *bound;
+@@ -655,7 +655,7 @@ static int multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes
+ 		self->buf_begin += len;
+ 	}
+ 
+-	return (int)len;
++	return len;
+ }
+ 
+ /*
+@@ -665,7 +665,7 @@ static int multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes
+ static char *multipart_buffer_read_body(multipart_buffer *self, size_t *len)
+ {
+ 	char buf[FILLUNIT], *out=NULL;
+-	int total_bytes=0, read_bytes=0;
++	size_t total_bytes=0, read_bytes=0;
+ 
+ 	while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL))) {
+ 		out = erealloc(out, total_bytes + read_bytes + 1);
+@@ -692,7 +692,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ 	char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
+ 	char *lbuf = NULL, *abuf = NULL;
+ 	zend_string *temp_filename = NULL;
+-	int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0;
++	int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0;
++	size_t array_len = 0;
+ 	int64_t total_bytes = 0, max_file_size = 0;
+ 	int skip_upload = 0, anonindex = 0, is_anonymous;
+ 	HashTable *uploaded_files = NULL;
+@@ -1126,7 +1127,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ 			is_arr_upload =	(start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');
+ 
+ 			if (is_arr_upload) {
+-				array_len = (int)strlen(start_arr);
++				array_len = strlen(start_arr);
+ 				if (array_index) {
+ 					efree(array_index);
+ 				}
diff --git a/php-cve-2019-11050.patch b/php-cve-2019-11050.patch
new file mode 100644
index 0000000..5e6fdc7
--- /dev/null
+++ b/php-cve-2019-11050.patch
@@ -0,0 +1,46 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 16 Dec 2019 01:14:38 -0800
+Subject: Fix bug #78793
+
+(cherry picked from commit c14eb8de974fc8a4d74f3515424c293bc7a40fba)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/020d208284f3bfa87b3b983f59a6a2eb7d4dae87
+---
+ ext/exif/exif.c              |  5 +++--
+ ext/exif/tests/bug78793.phpt | 12 ++++++++++++
+ 2 files changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 77e4427b..c9ebaa7b 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2821,8 +2821,9 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
+ 	}
+ 
+ 	for (de=0;de<NumDirEntries;de++) {
+-		if (!exif_process_IFD_TAG(ImageInfo, dir_start + 2 + 12 * de,
+-								  offset_base, data_len, displacement, section_index, 0, maker_note->tag_table)) {
++		size_t offset = 2 + 12 * de;
++		if (!exif_process_IFD_TAG(ImageInfo, dir_start + offset,
++								  offset_base, data_len - offset, displacement, section_index, 0, maker_note->tag_table)) {
+ 			return FALSE;
+ 		}
+ 	}
+diff --git a/ext/exif/tests/bug78793.phpt b/ext/exif/tests/bug78793.phpt
+new file mode 100644
+index 00000000..033f255a
+--- /dev/null
++++ b/ext/exif/tests/bug78793.phpt
+@@ -0,0 +1,12 @@
++--TEST--
++Bug #78793: Use-after-free in exif parsing under memory sanitizer
++--FILE--
++<?php
++$f = "ext/exif/tests/bug77950.tiff";
++for ($i = 0; $i < 10; $i++) {
++    @exif_read_data($f);
++}
++?>
++===DONE===
++--EXPECT--
++===DONE===
diff --git a/php-cve-2019-18218.patch b/php-cve-2019-18218.patch
new file mode 100644
index 0000000..3b46825
--- /dev/null
+++ b/php-cve-2019-18218.patch
@@ -0,0 +1,49 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 27 Oct 2019 16:30:38 -0700
+Subject: Fix libmagic buffer overflow issue (CVE-2019-18218)
+
+Ported from https://github.com/file/file/commit/46a8443f76cec4b41ec736eca396984c74664f84
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/469820048df558040f6dec7c39471ad11e2a7cfb
+---
+ ext/fileinfo/libmagic/cdf.c | 7 +++----
+ ext/fileinfo/libmagic/cdf.h | 1 +
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/ext/fileinfo/libmagic/cdf.c b/ext/fileinfo/libmagic/cdf.c
+index 28084fbe..01af1e4e 100644
+--- a/ext/fileinfo/libmagic/cdf.c
++++ b/ext/fileinfo/libmagic/cdf.c
+@@ -872,8 +872,9 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
+ 		    i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
+ 		if (inp[i].pi_type & CDF_VECTOR) {
+ 			nelements = CDF_GETUINT32(q, 1);
+-			if (nelements == 0) {
+-				DPRINTF(("CDF_VECTOR with nelements == 0\n"));
++			if (nelements > CDF_ELEMENT_LIMIT || nelements == 0) {
++				DPRINTF(("CDF_VECTOR with nelements == %"
++				    SIZE_T_FORMAT "u\n", nelements));
+ 				goto out;
+ 			}
+ 			o = 2;
+@@ -948,8 +949,6 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
+ 				*info = inp;
+ 				inp = *info + nelem;
+ 			}
+-			DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n",
+-			    nelements));
+ 			for (j = 0; j < nelements && i < sh.sh_properties;
+ 			    j++, i++)
+ 			{
+diff --git a/ext/fileinfo/libmagic/cdf.h b/ext/fileinfo/libmagic/cdf.h
+index 9006a686..6ad5bceb 100644
+--- a/ext/fileinfo/libmagic/cdf.h
++++ b/ext/fileinfo/libmagic/cdf.h
+@@ -50,6 +50,7 @@
+ typedef int32_t cdf_secid_t;
+ 
+ #define CDF_LOOP_LIMIT					10000
++#define CDF_ELEMENT_LIMIT				100000
+ 
+ #define CDF_SECID_NULL					0
+ #define CDF_SECID_FREE					-1
diff --git a/php-cve-2020-7059.patch b/php-cve-2020-7059.patch
new file mode 100644
index 0000000..59a2610
--- /dev/null
+++ b/php-cve-2020-7059.patch
@@ -0,0 +1,168 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 20 Jan 2020 21:33:17 -0800
+Subject: Fix #79099: OOB read in php_strip_tags_ex
+
+(cherry picked from commit 0f79b1bf301f455967676b5129240140c5c45b09)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/f18f20c032482e34d5f94d747da16f8ae029a017
+
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 20 Jan 2020 21:42:44 -0800
+Subject: Fix bug #79037 (global buffer-overflow in `mbfl_filt_conv_big5_wchar`)
+
+(cherry picked from commit 2bcbc95f033c31b00595ed39f79c3a99b4ed0501)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/6639124e6e1fbfe81a6afe5ee9f0a1fee24d0856
+
+From: Stanislav Malyshev <stas at php.net>
+Date: Wed, 22 Jan 2020 22:36:53 -0800
+Subject: More checks for php_strip_tags_ex
+
+(cherry picked from commit 2dc170e25d86a725fefd4c08f2bd8378820b28f5)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/a9620f5c7f2d55ca90552d3eb44d0980f10deec3
+---
+ ext/mbstring/libmbfl/filters/mbfilter_big5.c | 17 ++++++++++----
+ ext/mbstring/tests/bug79037.phpt             | 10 ++++++++
+ ext/standard/string.c                        | 10 ++++----
+ ext/standard/tests/file/bug79099.phpt        | 32 ++++++++++++++++++++++++++
+ 4 files changed, 59 insertions(+), 10 deletions(-)
+
+diff --git a/ext/mbstring/libmbfl/filters/mbfilter_big5.c b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+index f5ab8809..5e1ca815 100644
+--- a/ext/mbstring/libmbfl/filters/mbfilter_big5.c
++++ b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+@@ -138,6 +138,17 @@ static unsigned short cp950_pua_tbl[][4] = {
+ 	{0xf70f,0xf848,0xc740,0xc8fe},
+ };
+ 
++static inline int is_in_cp950_pua(int c1, int c) {
++	if ((c1 >= 0xfa && c1 <= 0xfe) || (c1 >= 0x8e && c1 <= 0xa0) ||
++			(c1 >= 0x81 && c1 <= 0x8d) || (c1 >= 0xc7 && c1 <= 0xc8)) {
++		return (c >=0x40 && c <= 0x7e) || (c >= 0xa1 && c <= 0xfe);
++	}
++	if (c1 == 0xc6) {
++		return c >= 0xa1 && c <= 0xfe;
++	}
++	return 0;
++}
++
+ /*
+  * Big5 => wchar
+  */
+@@ -186,11 +197,7 @@ mbfl_filt_conv_big5_wchar(int c, mbfl_convert_filter *filter)
+ 
+ 			if (filter->from->no_encoding == mbfl_no_encoding_cp950) {
+ 				/* PUA for CP950 */
+-				if (w <= 0 &&
+-					(((c1 >= 0xfa && c1 <= 0xfe) || (c1 >= 0x8e && c1 <= 0xa0) ||
+-					  (c1 >= 0x81 && c1 <= 0x8d) ||(c1 >= 0xc7 && c1 <= 0xc8))
+-					 && ((c > 0x39 && c < 0x7f) || (c > 0xa0 && c < 0xff))) ||
+-					((c1 == 0xc6) && (c > 0xa0 && c < 0xff))) {
++				if (w <= 0 && is_in_cp950_pua(c1, c)) {
+ 					c2 = c1 << 8 | c;
+ 					for (k = 0; k < sizeof(cp950_pua_tbl)/(sizeof(unsigned short)*4); k++) {
+ 						if (c2 >= cp950_pua_tbl[k][2] && c2 <= cp950_pua_tbl[k][3]) {
+diff --git a/ext/mbstring/tests/bug79037.phpt b/ext/mbstring/tests/bug79037.phpt
+new file mode 100644
+index 00000000..94ff01a4
+--- /dev/null
++++ b/ext/mbstring/tests/bug79037.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++Bug #79037: global buffer-overflow in `mbfl_filt_conv_big5_wchar`
++--FILE--
++<?php
++
++var_dump(mb_convert_encoding("\x81\x3a", "UTF-8", "CP950"));
++
++?>
++--EXPECT--
++string(1) "?"
+diff --git a/ext/standard/string.c b/ext/standard/string.c
+index 922d4fce..018e919c 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -4731,7 +4731,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
+ 				switch (state) {
+ 					case 1: /* HTML/XML */
+ 						lc = '>';
+-						if (is_xml && *(p -1) == '-') {
++						if (is_xml && p >= buf + 1 && *(p-1) == '-') {
+ 							break;
+ 						}
+ 						in_q = state = is_xml = 0;
+@@ -4752,7 +4752,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
+ 						break;
+ 
+ 					case 2: /* PHP */
+-						if (!br && lc != '\"' && *(p-1) == '?') {
++						if (!br && lc != '\"' && p >= buf + 1 && *(p-1) == '?') {
+ 							in_q = state = 0;
+ 							tp = tbuf;
+ 						}
+@@ -4781,7 +4781,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
+ 				if (state == 4) {
+ 					/* Inside <!-- comment --> */
+ 					break;
+-				} else if (state == 2 && *(p-1) != '\\') {
++				} else if (state == 2 && p >= buf + 1 && *(p-1) != '\\') {
+ 					if (lc == c) {
+ 						lc = '\0';
+ 					} else if (lc != '\\') {
+@@ -4808,7 +4808,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
+ 
+ 			case '!':
+ 				/* JavaScript & Other HTML scripting languages */
+-				if (state == 1 && *(p-1) == '<') {
++				if (state == 1 && p >= buf + 1 && *(p-1) == '<') {
+ 					state = 3;
+ 					lc = c;
+ 				} else {
+@@ -4835,7 +4835,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
+ 
+ 			case '?':
+ 
+-				if (state == 1 && *(p-1) == '<') {
++				if (state == 1 && p >= buf + 1 && *(p-1) == '<') {
+ 					br=0;
+ 					state=2;
+ 					break;
+diff --git a/ext/standard/tests/file/bug79099.phpt b/ext/standard/tests/file/bug79099.phpt
+new file mode 100644
+index 00000000..7c842f46
+--- /dev/null
++++ b/ext/standard/tests/file/bug79099.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++Bug #79099 (OOB read in php_strip_tags_ex)
++--FILE--
++<?php
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<?\n\"\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<\0\n!\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<\0\n?\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++?>
++--EXPECT--
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
diff --git a/php-cve-2020-7062.patch b/php-cve-2020-7062.patch
new file mode 100644
index 0000000..d45755a
--- /dev/null
+++ b/php-cve-2020-7062.patch
@@ -0,0 +1,82 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sat, 15 Feb 2020 20:52:19 -0800
+Subject: Fix bug #79221 - Null Pointer Dereference in PHP Session Upload Progress
+
+(cherry picked from commit d76f7c6c636b8240e06a1fa29eebb98ad005008a)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/4438b2844e80d9533587d558f4411f29d17de2c1
+---
+ ext/session/session.c           |  8 ++++---
+ ext/session/tests/bug79221.phpt | 45 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+), 3 deletions(-)
+
+diff --git a/ext/session/session.c b/ext/session/session.c
+index 44ecb85f..ee52d24f 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -2999,9 +2999,11 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
+ 				if (PS(rfc1867_cleanup)) {
+ 					php_session_rfc1867_cleanup(progress);
+ 				} else {
+-					add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1);
+-					Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+-					php_session_rfc1867_update(progress, 1);
++					if (!Z_ISUNDEF(progress->data)) {
++						add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1);
++						Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
++						php_session_rfc1867_update(progress, 1);
++					}
+ 				}
+ 				php_rshutdown_session_globals();
+ 			}
+diff --git a/ext/session/tests/bug79221.phpt b/ext/session/tests/bug79221.phpt
+new file mode 100644
+index 00000000..b0972c46
+--- /dev/null
++++ b/ext/session/tests/bug79221.phpt
+@@ -0,0 +1,45 @@
++--TEST--
++Null Pointer Dereference in PHP Session Upload Progress
++--INI--
++error_reporting=0
++file_uploads=1
++upload_max_filesize=1024
++session.save_path=
++session.name=PHPSESSID
++session.serialize_handler=php
++session.use_strict_mode=0
++session.use_cookies=1
++session.use_only_cookies=0
++session.upload_progress.enabled=1
++session.upload_progress.cleanup=0
++session.upload_progress.prefix=upload_progress_
++session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
++session.upload_progress.freq=1%
++session.upload_progress.min_freq=0.000000001
++--COOKIE--
++PHPSESSID=session-upload
++--POST_RAW--
++Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; name="PHPSESSID"
++
++session-upload
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
++
++ryat
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; file="file"; ryat="filename"
++
++1
++-----------------------------20896060251896012921717172737--
++--FILE--
++<?php
++
++session_start();
++var_dump($_SESSION);
++session_destroy();
++
++--EXPECTF--
++array(0) {
++}
diff --git a/php-cve-2020-7063.patch b/php-cve-2020-7063.patch
new file mode 100644
index 0000000..de2980a
--- /dev/null
+++ b/php-cve-2020-7063.patch
@@ -0,0 +1,115 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sat, 15 Feb 2020 22:17:14 -0800
+Subject: Fix bug #79082 - Files added to tar with Phar::buildFromIterator have all-access permissions
+
+(cherry picked from commit e5c95234d87fcb8f6b7569a96a89d1e1544749a6)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/d1b4f9477f43c55cfb631e7c60d5b3568bdc889c
+---
+ ext/phar/phar_object.c                       | 11 ++++++
+ ext/phar/tests/bug79082.phpt                 | 52 ++++++++++++++++++++++++++
+ ext/phar/tests/test79082/test79082-testfile  |  1 +
+ ext/phar/tests/test79082/test79082-testfile2 |  1 +
+ 4 files changed, 65 insertions(+)
+
+diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
+index c1ba97a1..b22a6acf 100644
+--- a/ext/phar/phar_object.c
++++ b/ext/phar/phar_object.c
+@@ -1439,6 +1439,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
+ 	char *str_key;
+ 	zend_class_entry *ce = p_obj->c;
+ 	phar_archive_object *phar_obj = p_obj->p;
++	php_stream_statbuf ssb;
+ 
+ 	value = iter->funcs->get_current_data(iter);
+ 
+@@ -1718,6 +1719,16 @@ after_open_fp:
+ 		php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
+ 		data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
+ 			php_stream_tell(p_obj->fp) - data->internal_file->offset;
++		if (php_stream_stat(fp, &ssb) != -1) {
++			data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
++		} else {
++#ifndef _WIN32
++			mode_t mask;
++			mask = umask(0);
++			umask(mask);
++			data->internal_file->flags &= ~mask;
++#endif
++		}
+ 	}
+ 
+ 	if (close_fp) {
+diff --git a/ext/phar/tests/bug79082.phpt b/ext/phar/tests/bug79082.phpt
+new file mode 100644
+index 00000000..ca453d1b
+--- /dev/null
++++ b/ext/phar/tests/bug79082.phpt
+@@ -0,0 +1,52 @@
++--TEST--
++Phar: Bug #79082: Files added to tar with Phar::buildFromIterator have all-access permissions
++--SKIPIF--
++<?php 
++if (!extension_loaded("phar")) die("skip"); 
++if (defined("PHP_WINDOWS_VERSION_MAJOR")) die("skip not for Windows")
++?>
++--FILE--
++<?php
++umask(022);
++var_dump(decoct(umask()));
++chmod(__DIR__ . '/test79082/test79082-testfile', 0644);
++chmod(__DIR__ . '/test79082/test79082-testfile2', 0400);
++
++foreach([Phar::TAR => 'tar', Phar::ZIP => 'zip'] as $mode => $ext) {
++	clearstatcache();
++	$phar = new PharData(__DIR__ . '/test79082.' . $ext, null, null, $mode);
++	$phar->buildFromIterator(new \RecursiveDirectoryIterator(__DIR__ . '/test79082', \FilesystemIterator::SKIP_DOTS), __DIR__ . '/test79082');
++	$phar->extractTo(__DIR__);
++	var_dump(decoct(stat(__DIR__ . '/test79082-testfile')['mode']));
++	var_dump(decoct(stat(__DIR__ . '/test79082-testfile2')['mode']));
++	unlink(__DIR__ . '/test79082-testfile');
++	unlink(__DIR__ . '/test79082-testfile2');
++}
++foreach([Phar::TAR => 'tar', Phar::ZIP => 'zip'] as $mode => $ext) {
++	clearstatcache();
++	$phar = new PharData(__DIR__ . '/test79082-d.' . $ext, null, null, $mode);
++	$phar->buildFromDirectory(__DIR__ . '/test79082');
++	$phar->extractTo(__DIR__);
++	var_dump(decoct(stat(__DIR__ . '/test79082-testfile')['mode']));
++	var_dump(decoct(stat(__DIR__ . '/test79082-testfile2')['mode']));
++	unlink(__DIR__ . '/test79082-testfile');
++	unlink(__DIR__ . '/test79082-testfile2');
++}
++?>
++--CLEAN--
++<?
++unlink(__DIR__ . '/test79082.tar');
++unlink(__DIR__ . '/test79082.zip');
++unlink(__DIR__ . '/test79082-d.tar');
++unlink(__DIR__ . '/test79082-d.zip');
++?>
++--EXPECT--
++string(2) "22"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
+diff --git a/ext/phar/tests/test79082/test79082-testfile b/ext/phar/tests/test79082/test79082-testfile
+new file mode 100644
+index 00000000..9daeafb9
+--- /dev/null
++++ b/ext/phar/tests/test79082/test79082-testfile
+@@ -0,0 +1 @@
++test
+diff --git a/ext/phar/tests/test79082/test79082-testfile2 b/ext/phar/tests/test79082/test79082-testfile2
+new file mode 100644
+index 00000000..9daeafb9
+--- /dev/null
++++ b/ext/phar/tests/test79082/test79082-testfile2
+@@ -0,0 +1 @@
++test
diff --git a/php-cve-2020-7064.patch b/php-cve-2020-7064.patch
new file mode 100644
index 0000000..49fa5c6
--- /dev/null
+++ b/php-cve-2020-7064.patch
@@ -0,0 +1,72 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 15 Mar 2020 17:26:00 -0700
+Subject: Fixed bug #79282
+
+(cherry picked from commit 41f66e2a2cfd611e35be5ac3bf747f0b56161216)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/8577fa5891220dac40d42b2f745fa159dcd871ad
+
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 15 Mar 2020 17:55:28 -0700
+Subject: Fix test
+
+(cherry picked from commit 2c081b7e269d0f63cd9d60a40997f18b5cf793be)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/ad05ad4dbafc29dd23828760d4bfa2be12ccbb1c
+
+From: Remi Collet <remi at remirepo.net>
+Date: Tue, 17 Mar 2020 07:23:32 +0100
+Subject: fix test
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b42b6d0ff774fdced1155cb0c721d91914d619f5
+---
+ ext/exif/exif.c              |  7 ++++++-
+ ext/exif/tests/bug79282.phpt | 15 +++++++++++++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 406fee4f..9130ceaf 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3243,6 +3243,11 @@ static void exif_process_TIFF_in_JPEG(image_info_type *ImageInfo, char *CharBuf,
+ {
+ 	unsigned exif_value_2a, offset_of_ifd;
+ 
++	if (length < 2) {
++		exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Missing TIFF alignment marker");
++		return;
++	}
++
+ 	/* set the thumbnail stuff to nothing so we can test to see if they get set up */
+ 	if (memcmp(CharBuf, "II", 2) == 0) {
+ 		ImageInfo->motorola_intel = 0;
+@@ -3395,7 +3400,7 @@ static int exif_scan_JPEG_header(image_info_type *ImageInfo)
+ 			return FALSE;
+ 		}
+ 
+-		sn = exif_file_sections_add(ImageInfo, marker, itemlen+1, NULL);
++		sn = exif_file_sections_add(ImageInfo, marker, itemlen, NULL);
+ 		Data = ImageInfo->file.list[sn].data;
+ 
+ 		/* Store first two pre-read bytes. */
+diff --git a/ext/exif/tests/bug79282.phpt b/ext/exif/tests/bug79282.phpt
+new file mode 100644
+index 00000000..142cf28a
+--- /dev/null
++++ b/ext/exif/tests/bug79282.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #79282: Use-of-uninitialized-value in exif
++--FILE--
++<?php
++
++var_dump(exif_read_data('data://image/jpeg;base64,/9jhAAlFeGlmAAAg'));
++
++?>
++--EXPECTF--
++Warning: exif_read_data(%s): Missing TIFF alignment marker in %s on line %d
++
++Warning: exif_read_data(%s): File structure corrupted in %s on line %d
++
++Warning: exif_read_data(%s): Invalid JPEG file in %s on line %d
++bool(false)
diff --git a/php-cve-2020-7066.patch b/php-cve-2020-7066.patch
new file mode 100644
index 0000000..22864f6
--- /dev/null
+++ b/php-cve-2020-7066.patch
@@ -0,0 +1,24 @@
+From: Remi Collet <remi at remirepo.net>
+Date: Tue, 17 Mar 2020 07:25:12 +0100
+Subject: Fix bug #79329 - get_headers should not accept \0
+
+From 0d139c5b94a5f485a66901919e51faddb0371c43
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b7b9302660a23a67285e204bc3d7fcf6ba7f6533
+---
+ ext/standard/url.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 0eac03ee..39e5b1b2 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -660,7 +660,7 @@ PHP_FUNCTION(get_headers)
+ 	zval *zcontext = NULL;
+ 	php_stream_context *context;
+ 
+-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lr!", &url, &url_len, &format, &zcontext) == FAILURE) {
++	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lr!", &url, &url_len, &format, &zcontext) == FAILURE) {
+ 		return;
+ 	}
+ 
diff --git a/php-cve-2020-7067.patch b/php-cve-2020-7067.patch
new file mode 100644
index 0000000..dcbe1f0
--- /dev/null
+++ b/php-cve-2020-7067.patch
@@ -0,0 +1,33 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Mon, 13 Apr 2020 21:07:04 -0700
+Subject: Fix bug #79465 - use unsigneds as indexes.
+
+(cherry picked from commit 9d6bf8221b05f86ce5875832f0f646c4c1f218be)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/3a81a8f4d47c1b628da3b3a2db433d8cc7146bba
+---
+ ext/standard/url.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 39e5b1b2..4cc1f77a 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -540,7 +540,7 @@ PHPAPI size_t php_url_decode(char *str, size_t len)
+ #ifndef CHARSET_EBCDIC
+ 			*dest = (char) php_htoi(data + 1);
+ #else
+-			*dest = os_toebcdic[(char) php_htoi(data + 1)];
++			*dest = os_toebcdic[(unsigned char) php_htoi(data + 1)];
+ #endif
+ 			data += 2;
+ 			len -= 2;
+@@ -632,7 +632,7 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len)
+ #ifndef CHARSET_EBCDIC
+ 			*dest = (char) php_htoi(data + 1);
+ #else
+-			*dest = os_toebcdic[(char) php_htoi(data + 1)];
++			*dest = os_toebcdic[(unsigned char) php_htoi(data + 1)];
+ #endif
+ 			data += 2;
+ 			len -= 2;
diff --git a/php-cve-2020-7068.patch b/php-cve-2020-7068.patch
new file mode 100644
index 0000000..a4e07f8
Binary files /dev/null and b/php-cve-2020-7068.patch differ
diff --git a/php-cve-2020-7069.patch b/php-cve-2020-7069.patch
new file mode 100644
index 0000000..3a10173
--- /dev/null
+++ b/php-cve-2020-7069.patch
@@ -0,0 +1,197 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sat, 26 Sep 2020 22:08:52 -0700
+Subject: Fix bug #79601 (Wrong ciphertext/tag in AES-CCM encryption for a 12 bytes IV)
+
+(cherry picked from commit 0216630ea2815a5789a24279a1211ac398d4de79)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/3528f51fe33944ba7bab263a47c49dd1d7dd12e3
+
+From: Jakub Zelenka <bukka at php.net>
+Date: Sun, 2 Jun 2019 19:10:56 +0100
+Subject: Fix bug #78079 (openssl_encrypt_ccm.phpt fails with OpenSSL 1.1.1c)
+
+It also fixes invalid setting of tag length
+
+(cherry picked from commit 2e025794745e09f7d0c72822ad0238bf6d67b2e8)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/74495ac743e1896c3b33c954fcef54b412f87ac9
+---
+ ext/openssl/openssl.c                      | 15 ++++++-----
+ ext/openssl/tests/cipher_tests.inc         | 21 +++++++++++++++
+ ext/openssl/tests/openssl_decrypt_ccm.phpt | 22 ++++++++++------
+ ext/openssl/tests/openssl_encrypt_ccm.phpt | 38 +++++++++++++++++++---------
+ 4 files changed, 70 insertions(+), 26 deletions(-)
+
+diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
+index 4b7f1d69..533cc1b5 100644
+--- a/ext/openssl/openssl.c
++++ b/ext/openssl/openssl.c
+@@ -6218,11 +6218,6 @@ static int php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_requir
+ {
+ 	char *iv_new;
+ 
+-	/* Best case scenario, user behaved */
+-	if (*piv_len == iv_required_len) {
+-		return SUCCESS;
+-	}
+-
+ 	if (mode->is_aead) {
+ 		if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) != 1) {
+ 			php_error_docref(NULL, E_WARNING, "Setting of IV length for AEAD mode failed");
+@@ -6231,6 +6226,11 @@ static int php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_requir
+ 		return SUCCESS;
+ 	}
+ 
++	/* Best case scenario, user behaved */
++	if (*piv_len == iv_required_len) {
++		return SUCCESS;
++	}
++
+ 	iv_new = ecalloc(1, iv_required_len + 1);
+ 
+ 	if (*piv_len == 0) {
+@@ -6291,7 +6291,10 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
+ 		return FAILURE;
+ 	}
+ 	if (mode->is_single_run_aead && enc) {
+-		EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL);
++		if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL)) {
++			php_error_docref(NULL, E_WARNING, "Setting tag length for AEAD cipher failed");
++			return FAILURE;
++		}
+ 	} else if (!enc && tag && tag_len > 0) {
+ 		if (!mode->is_aead) {
+ 			php_error_docref(NULL, E_WARNING, "The tag cannot be used because the cipher method does not support AEAD");
+diff --git a/ext/openssl/tests/cipher_tests.inc b/ext/openssl/tests/cipher_tests.inc
+index b1e46b41..779bfa85 100644
+--- a/ext/openssl/tests/cipher_tests.inc
++++ b/ext/openssl/tests/cipher_tests.inc
+@@ -1,5 +1,26 @@
+ <?php
+ $php_openssl_cipher_tests = array(
++    'aes-128-ccm' => array(
++        array(
++            'key' => '404142434445464748494a4b4c4d4e4f',
++            'iv'  => '1011121314151617',
++            'aad' => '000102030405060708090a0b0c0d0e0f',
++            'tag' => '1fc64fbfaccd',
++            'pt'  => '202122232425262728292a2b2c2d2e2f',
++            'ct'  => 'd2a1f0e051ea5f62081a7792073d593d',
++        ),
++        array(
++            'key' => '404142434445464748494a4b4c4d4e4f',
++            'iv'  => '101112131415161718191a1b',
++            'aad' => '000102030405060708090a0b0c0d0e0f' .
++                     '10111213',
++            'tag' => '484392fbc1b09951',
++            'pt'  => '202122232425262728292a2b2c2d2e2f' .
++                     '3031323334353637',
++            'ct'  => 'e3b201a9f5b71a7a9b1ceaeccd97e70b' .
++                     '6176aad9a4428aa5',
++        ),
++    ),
+     'aes-256-ccm' => array(
+         array(
+             'key' => '1bde3251d41a8b5ea013c195ae128b21' .
+diff --git a/ext/openssl/tests/openssl_decrypt_ccm.phpt b/ext/openssl/tests/openssl_decrypt_ccm.phpt
+index 87b6d4b2..47911471 100644
+--- a/ext/openssl/tests/openssl_decrypt_ccm.phpt
++++ b/ext/openssl/tests/openssl_decrypt_ccm.phpt
+@@ -10,14 +10,16 @@ if (!in_array('aes-256-ccm', openssl_get_cipher_methods()))
+ --FILE--
+ <?php
+ require_once __DIR__ . "/cipher_tests.inc";
+-$method = 'aes-256-ccm';
+-$tests = openssl_get_cipher_tests($method);
++$methods = ['aes-128-ccm', 'aes-256-ccm'];
+ 
+-foreach ($tests as $idx => $test) {
+-    echo "TEST $idx\n";
+-    $pt = openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
+-        $test['iv'], $test['tag'], $test['aad']);
+-    var_dump($test['pt'] === $pt);
++foreach ($methods as $method) {
++    $tests = openssl_get_cipher_tests($method);
++    foreach ($tests as $idx => $test) {
++        echo "$method - TEST $idx\n";
++        $pt = openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
++            $test['iv'], $test['tag'], $test['aad']);
++        var_dump($test['pt'] === $pt);
++    }
+ }
+ 
+ // no IV
+@@ -32,7 +34,11 @@ var_dump(openssl_decrypt($test['ct'], $method, $test['key'], OPENSSL_RAW_DATA,
+ 
+ ?>
+ --EXPECTF--
+-TEST 0
++aes-128-ccm - TEST 0
++bool(true)
++aes-128-ccm - TEST 1
++bool(true)
++aes-256-ccm - TEST 0
+ bool(true)
+ 
+ Warning: openssl_decrypt(): Setting of IV length for AEAD mode failed in %s on line %d
+diff --git a/ext/openssl/tests/openssl_encrypt_ccm.phpt b/ext/openssl/tests/openssl_encrypt_ccm.phpt
+index c8610bc9..8c4c41f8 100644
+--- a/ext/openssl/tests/openssl_encrypt_ccm.phpt
++++ b/ext/openssl/tests/openssl_encrypt_ccm.phpt
+@@ -10,30 +10,44 @@ if (!in_array('aes-256-ccm', openssl_get_cipher_methods()))
+ --FILE--
+ <?php
+ require_once __DIR__ . "/cipher_tests.inc";
+-$method = 'aes-256-ccm';
+-$tests = openssl_get_cipher_tests($method);
++$methods = ['aes-128-ccm', 'aes-256-ccm'];
+ 
+-foreach ($tests as $idx => $test) {
+-    echo "TEST $idx\n";
+-    $ct = openssl_encrypt($test['pt'], $method, $test['key'], OPENSSL_RAW_DATA,
+-        $test['iv'], $tag, $test['aad'], strlen($test['tag']));
+-    var_dump($test['ct'] === $ct);
+-    var_dump($test['tag'] === $tag);
++foreach ($methods as $method) {
++    $tests = openssl_get_cipher_tests($method);
++    foreach ($tests as $idx => $test) {
++        echo "$method - TEST $idx\n";
++        $ct = openssl_encrypt($test['pt'], $method, $test['key'], OPENSSL_RAW_DATA,
++            $test['iv'], $tag, $test['aad'], strlen($test['tag']));
++        var_dump($test['ct'] === $ct);
++        var_dump($test['tag'] === $tag);
++    }
+ }
+ 
+ // Empty IV error
+ var_dump(openssl_encrypt('data', $method, 'password', 0, NULL, $tag, ''));
+ 
+-// Test setting different IV length and unlimeted tag
+-var_dump(openssl_encrypt('data', $method, 'password', 0, str_repeat('x', 10), $tag, '', 1024));
++// Test setting different IV length and tag length
++var_dump(openssl_encrypt('data', $method, 'password', 0, str_repeat('x', 10), $tag, '', 14));
+ var_dump(strlen($tag));
++
++// Test setting invalid tag length
++var_dump(openssl_encrypt('data', $method, 'password', 0, str_repeat('x', 16), $tag, '', 1024));
+ ?>
+ --EXPECTF--
+-TEST 0
++aes-128-ccm - TEST 0
++bool(true)
++bool(true)
++aes-128-ccm - TEST 1
++bool(true)
++bool(true)
++aes-256-ccm - TEST 0
+ bool(true)
+ bool(true)
+ 
+ Warning: openssl_encrypt(): Setting of IV length for AEAD mode failed in %s on line %d
+ bool(false)
+ string(8) "p/lvgA=="
+-int(1024)
++int(14)
++
++Warning: openssl_encrypt(): Setting of IV length for AEAD mode failed in %s on line %d
++bool(false)
diff --git a/php-cve-2020-7070.patch b/php-cve-2020-7070.patch
new file mode 100644
index 0000000..2e6a730
--- /dev/null
+++ b/php-cve-2020-7070.patch
@@ -0,0 +1,116 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 20 Sep 2020 18:08:55 -0700
+Subject: Do not decode cookie names anymore
+
+(cherry picked from commit 6559fe912661ca5ce5f0eeeb591d928451428ed0)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/72f993acb5de39ca5f01146ff33ff63dc110b8b4
+---
+ main/php_variables.c      |  8 ++++++--
+ tests/basic/022.phpt      | 10 +++++++---
+ tests/basic/023.phpt      |  4 +++-
+ tests/basic/bug79699.phpt | 22 ++++++++++++++++++++++
+ 4 files changed, 38 insertions(+), 6 deletions(-)
+
+diff --git a/main/php_variables.c b/main/php_variables.c
+index c56d2300..d0223df4 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -484,7 +484,9 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ 			size_t new_val_len;
+ 
+ 			*val++ = '\0';
+-			php_url_decode(var, strlen(var));
++			if (arg != PARSE_COOKIE) {
++				php_url_decode(var, strlen(var));
++			}
+ 			val_len = php_url_decode(val, strlen(val));
+ 			val = estrndup(val, val_len);
+ 			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
+@@ -495,7 +497,9 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ 			size_t val_len;
+ 			size_t new_val_len;
+ 
+-			php_url_decode(var, strlen(var));
++			if (arg != PARSE_COOKIE) {
++				php_url_decode(var, strlen(var));
++			}
+ 			val_len = 0;
+ 			val = estrndup("", val_len);
+ 			if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
+diff --git a/tests/basic/022.phpt b/tests/basic/022.phpt
+index 0ab70d4b..bd1db137 100644
+--- a/tests/basic/022.phpt
++++ b/tests/basic/022.phpt
+@@ -10,7 +10,7 @@ cookie1=val1  ; cookie2=val2%20; cookie3=val 3.; cookie 4= value 4 %3B; cookie1=
+ var_dump($_COOKIE);
+ ?>
+ --EXPECT--
+-array(10) {
++array(12) {
+   ["cookie1"]=>
+   string(6) "val1  "
+   ["cookie2"]=>
+@@ -19,11 +19,15 @@ array(10) {
+   string(6) "val 3."
+   ["cookie_4"]=>
+   string(10) " value 4 ;"
++  ["%20cookie1"]=>
++  string(6) "ignore"
++  ["+cookie1"]=>
++  string(6) "ignore"
+   ["cookie__5"]=>
+   string(7) "  value"
+-  ["cookie_6"]=>
++  ["cookie%206"]=>
+   string(3) "���"
+-  ["cookie_7"]=>
++  ["cookie+7"]=>
+   string(0) ""
+   ["$cookie_8"]=>
+   string(0) ""
+diff --git a/tests/basic/023.phpt b/tests/basic/023.phpt
+index ca5f1dcf..0e2e0ac6 100644
+--- a/tests/basic/023.phpt
++++ b/tests/basic/023.phpt
+@@ -10,9 +10,11 @@ c o o k i e=value; c o o k i e= v a l u e ;;c%20o+o k+i%20e=v;name="value","valu
+ var_dump($_COOKIE);
+ ?>
+ --EXPECT--
+-array(3) {
++array(4) {
+   ["c_o_o_k_i_e"]=>
+   string(5) "value"
++  ["c%20o+o_k+i%20e"]=>
++  string(1) "v"
+   ["name"]=>
+   string(24) ""value","value",UEhQIQ=="
+   ["UEhQIQ"]=>
+diff --git a/tests/basic/bug79699.phpt b/tests/basic/bug79699.phpt
+new file mode 100644
+index 00000000..fc3d3fed
+--- /dev/null
++++ b/tests/basic/bug79699.phpt
+@@ -0,0 +1,22 @@
++--TEST--
++Cookies Security Bug
++--INI--
++max_input_vars=1000
++filter.default=unsafe_raw
++--COOKIE--
++__%48ost-evil=evil; __Host-evil=good; %66oo=baz;foo=bar
++--FILE--
++<?php
++var_dump($_COOKIE);
++?>
++--EXPECT--
++array(4) {
++  ["__%48ost-evil"]=>
++  string(4) "evil"
++  ["__Host-evil"]=>
++  string(4) "good"
++  ["%66oo"]=>
++  string(3) "baz"
++  ["foo"]=>
++  string(3) "bar"
++}
diff --git a/php-cve-2020-7071.patch b/php-cve-2020-7071.patch
new file mode 100644
index 0000000..6902d7a
--- /dev/null
+++ b/php-cve-2020-7071.patch
@@ -0,0 +1,102 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Wed, 13 May 2020 09:36:52 +0200
+Subject: 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.
+
+(cherry picked from commit 2d3d72412a6734e19a38ed10f385227a6238e4a6)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/31459f94f2780e748e15d5c2951ba20adbba2366
+
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Tue, 19 Jan 2021 11:23:25 +0100
+Subject: 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)
+(cherry picked from commit 356f7008f36da60ec9794d48c55d117f1dd31903)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b5d4f109bab648c0d07273d2a52a5f2560e7832b
+---
+ ext/filter/logical_filters.c   | 25 +++++++++++++++++++++++++
+ ext/filter/tests/bug77423.phpt | 15 +++++++++++++++
+ 2 files changed, 40 insertions(+)
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index 52c9e285..1c51e6d2 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/filter/tests/bug77423.phpt b/ext/filter/tests/bug77423.phpt
+new file mode 100644
+index 00000000..761c7c35
+--- /dev/null
++++ b/ext/filter/tests/bug77423.phpt
+@@ -0,0 +1,15 @@
++--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));
++}
++?>
++--EXPECT--
++bool(false)
++bool(false)
diff --git a/php-cve-2021-21702.patch b/php-cve-2021-21702.patch
new file mode 100644
index 0000000..103ec4e
--- /dev/null
+++ b/php-cve-2021-21702.patch
@@ -0,0 +1,200 @@
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 31 Jan 2021 21:15:23 -0800
+Subject: Fix bug #80672 - Null Dereference in SoapClient
+
+(cherry picked from commit 3c939e3f69955d087e0bb671868f7267dfb2a502)
+(cherry picked from commit f1e2cfa008d1596251968d13eb9a8539dba6879f)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/e8cca879720c308fc1dca4fc4447addfaa910528
+
+From: Nikita Popov <nikita.ppv at gmail.com>
+Date: Mon, 1 Feb 2021 09:46:17 +0100
+Subject: Fix build
+
+(cherry picked from commit e5d767d27f94895e09f0321562fd3774d4656164)
+(cherry picked from commit 02352d5acc1896756dcb4645f54689ffdcc4ca52)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/64dd5c5f706372001c51188f3bf584745b629758
+---
+ ext/soap/php_sdl.c           | 26 ++++++++++++++------------
+ ext/soap/php_xml.c           |  4 ++--
+ ext/soap/tests/bug80672.phpt | 15 +++++++++++++++
+ ext/soap/tests/bug80672.xml  |  6 ++++++
+ 4 files changed, 37 insertions(+), 14 deletions(-)
+
+diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
+index b469177a..362e944a 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)?((const char *)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 bf76e237..1ac684eb 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 00000000..71e2b1d8
+--- /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 00000000..0fa185bf
+--- /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>
diff --git a/php-cve-2021-21703.patch b/php-cve-2021-21703.patch
new file mode 100644
index 0000000..f959a20
--- /dev/null
+++ b/php-cve-2021-21703.patch
@@ -0,0 +1,397 @@
+From: Jakub Zelenka <bukka at php.net>
+Date: Sat, 2 Oct 2021 22:53:41 +0100
+Subject: 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 at php.net>
+(cherry picked from commit cb2021e5f69da5e2868130a05bb53db0f9f89e4b)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/169a33e8d990d49c69b40a4dbab4b2f56721693f
+---
+ 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 bda85ef5..48380de5 100644
+--- a/sapi/fpm/fpm/fpm_children.c
++++ b/sapi/fpm/fpm/fpm_children.c
+@@ -239,7 +239,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);
+ 
+@@ -249,9 +249,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 */);
+@@ -317,7 +317,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;
+@@ -329,7 +329,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);
+ }
+@@ -342,10 +342,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 a4ace853..deaccf43 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 7a65fcbe..091efdc5 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 abce616d..6405abb7 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 1d78ebf8..45852a5b 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 90e15597..96b7ca50 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);
+ 	}
diff --git a/php-cve-2021-21704.patch b/php-cve-2021-21704.patch
new file mode 100644
index 0000000..a25afb6
Binary files /dev/null and b/php-cve-2021-21704.patch differ
diff --git a/php-cve-2021-21705.patch b/php-cve-2021-21705.patch
new file mode 100644
index 0000000..bbe94c8
--- /dev/null
+++ b/php-cve-2021-21705.patch
@@ -0,0 +1,65 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 14 Jun 2021 13:22:27 +0200
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/2ebad60c4ada6a49e5d5ab7abf20fd557c0f7764
+
+From: Stanislav Malyshev <stas at php.net>
+Date: Sun, 27 Jun 2021 21:57:58 -0700
+Subject: Fix warning
+
+(cherry picked from commit 190013787bbc424c240413d914e3a038f974ccef)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/7b18a837649c3b36bd51c46a7c3dc9525a69aba5
+---
+ ext/filter/logical_filters.c   |  4 +++-
+ ext/filter/tests/bug81122.phpt | 21 +++++++++++++++++++++
+ 2 files changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index 1c51e6d2..8b0d034e 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 00000000..d89d4114
+--- /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)
diff --git a/php-cve-2021-21707.patch b/php-cve-2021-21707.patch
new file mode 100644
index 0000000..049b1b7
--- /dev/null
+++ b/php-cve-2021-21707.patch
@@ -0,0 +1,136 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Tue, 1 Sep 2020 10:04:28 +0200
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/cdabc241c4f631ffa87e2652fe241184f519618f
+
+From: Remi Collet <remi at remirepo.net>
+Date: Mon, 15 Nov 2021 09:57:10 +0100
+Subject: fix new tests
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b21524ff3db15da5a7779cba73e3774eb5404d40
+---
+ 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(+)
+
+diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c
+index 28e35eb7..f4d1358b 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 00000000..01cd1235
+--- /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 (DIRECTORY_SEPARATOR !== '/') {
++    $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 e3e72552..aaceaca8 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 ||
+@@ -440,6 +444,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 00000000..464112c9
+--- /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 (DIRECTORY_SEPARATOR !== '/') {
++    $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 00000000..912bb76d
+--- /dev/null
++++ b/ext/simplexml/tests/bug79971_1.xml
+@@ -0,0 +1,2 @@
++<?xml version="1.0"?>
++<root></root>
diff --git a/php-cve-2022-31625.patch b/php-cve-2022-31625.patch
new file mode 100644
index 0000000..9092a9f
--- /dev/null
+++ b/php-cve-2022-31625.patch
@@ -0,0 +1,74 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Tue, 17 May 2022 12:59:23 +0200
+Subject: 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)
+(cherry picked from commit 310b17f5c8938389b1dbd7d8ff5a8144bfb9a351)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/9e7d6a2a1e8f43bdb86a0b6c1199f938f6ba78f5
+---
+ ext/pgsql/pgsql.c             |  4 ++--
+ ext/pgsql/tests/bug81720.phpt | 27 +++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 2 deletions(-)
+
+diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
+index 94100788..3039c26e 100644
+--- a/ext/pgsql/pgsql.c
++++ b/ext/pgsql/pgsql.c
+@@ -1982,7 +1982,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));
+@@ -5182,7 +5182,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 00000000..d79f1fcd
+--- /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
diff --git a/php-cve-2022-31626.patch b/php-cve-2022-31626.patch
new file mode 100644
index 0000000..a5735da
--- /dev/null
+++ b/php-cve-2022-31626.patch
@@ -0,0 +1,27 @@
+From: Stanislav Malyshev <smalyshev at gmail.com>
+Date: Mon, 6 Jun 2022 00:56:51 -0600
+Subject: Fix bug #81719: mysqlnd/pdo password buffer overflow
+
+(cherry picked from commit 58006537fc5f133ae8549efe5118cde418b3ace9)
+(cherry picked from commit 9433de72e291db518357fe55531cc15432d43ec4)
+(cherry picked from commit 1560224d3a26574f0195af3853e4d7e050b0b06f)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/5e1d9182748c5330c4bf2154da858206e76914b6
+---
+ 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 1e38b76f..610abf99 100644
+--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
++++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
+@@ -792,7 +792,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");
diff --git a/php-cve-2022-31628.patch b/php-cve-2022-31628.patch
new file mode 100644
index 0000000..4a3f5ab
Binary files /dev/null and b/php-cve-2022-31628.patch differ
diff --git a/php-cve-2022-31629.patch b/php-cve-2022-31629.patch
new file mode 100644
index 0000000..586bf24
--- /dev/null
+++ b/php-cve-2022-31629.patch
@@ -0,0 +1,59 @@
+From: Derick Rethans <github at derickrethans.nl>
+Date: Fri, 9 Sep 2022 16:54:03 +0100
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/ca3dd9335387e39c796c83b94b6a6359e22f3fe1
+---
+ ext/standard/tests/bug81727.phpt | 15 +++++++++++++++
+ main/php_variables.c             | 14 ++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/ext/standard/tests/bug81727.phpt b/ext/standard/tests/bug81727.phpt
+new file mode 100644
+index 00000000..71a9cb46
+--- /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 d0223df4..17a0b053 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -103,6 +103,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);
diff --git a/php-cve-2022-31631.patch b/php-cve-2022-31631.patch
new file mode 100644
index 0000000..2c25662
--- /dev/null
+++ b/php-cve-2022-31631.patch
@@ -0,0 +1,53 @@
+From: Christoph M. Becker <cmbecker69 at gmx.de>
+Date: Mon, 31 Oct 2022 17:20:23 +0100
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/b6caf64f9a0c0d9745962e37a57ba4dd32d6a712
+---
+ ext/pdo_sqlite/sqlite_driver.c     |  3 +++
+ ext/pdo_sqlite/tests/bug81740.phpt | 17 +++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
+index f9a2a4d0..ac466f48 100644
+--- a/ext/pdo_sqlite/sqlite_driver.c
++++ b/ext/pdo_sqlite/sqlite_driver.c
+@@ -232,6 +232,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 00000000..99fb07c3
+--- /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)
diff --git a/php-cve-2023-0567.patch b/php-cve-2023-0567.patch
new file mode 100644
index 0000000..3d4836b
--- /dev/null
+++ b/php-cve-2023-0567.patch
@@ -0,0 +1,179 @@
+From: Tim Düsterhus <tim at bastelstu.be>
+Date: Mon, 23 Jan 2023 21:15:24 +0100
+Subject: crypt: Fix validation of malformed BCrypt hashes
+
+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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/8cccd1d77222a08d42fbcd252f9ee948db8f676c
+
+From: Tim Düsterhus <tim at bastelstu.be>
+Date: Mon, 23 Jan 2023 22:13:57 +0100
+Subject: crypt: Fix possible buffer overread in php_crypt()
+
+(cherry picked from commit a92acbad873a05470af1a47cb785a18eadd827b5)
+(cherry picked from commit ed0281b588a6840cb95f3134a4e68847a3be5bb7)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/c2b9db02d6b889521004a39ba6bae975eeb095fb
+---
+ ext/standard/crypt.c                              |  1 +
+ ext/standard/crypt_blowfish.c                     |  8 --
+ ext/standard/tests/crypt/bcrypt_salt_dollar.phpt  | 82 +++++++++++++++++++++
+ .../tests/password/password_bcrypt_short.phpt     |  8 ++
+ 4 files changed, 91 insertions(+), 8 deletions(-)
+
+diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c
+index e6003678..d2ec9f76 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/crypt_blowfish.c b/ext/standard/crypt_blowfish.c
+index 5cf30671..e923b55e 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 00000000..32e335f4
+--- /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)
+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 00000000..085bc8a2
+--- /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)
diff --git a/php-cve-2023-0568.patch b/php-cve-2023-0568.patch
new file mode 100644
index 0000000..ee06d02
--- /dev/null
+++ b/php-cve-2023-0568.patch
@@ -0,0 +1,66 @@
+From: Niels Dossche <7771979+nielsdos at users.noreply.github.com>
+Date: Fri, 27 Jan 2023 19:28:27 +0100
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/bd523b8bbb516ee98528a4692601c2e35d3a729d
+---
+ 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 11ef4aa8..c212faa6 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 6c1da276..0f2b62ae 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 135b1491..e50a7354 100644
+--- a/main/fopen_wrappers.c
++++ b/main/fopen_wrappers.c
+@@ -137,10 +137,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;
+ 	int resolved_basedir_len;
+ 	int resolved_name_len;
diff --git a/php-cve-2023-0662.patch b/php-cve-2023-0662.patch
new file mode 100644
index 0000000..ca2d070
--- /dev/null
+++ b/php-cve-2023-0662.patch
@@ -0,0 +1,83 @@
+From: Jakub Zelenka <bukka at php.net>
+Date: Thu, 19 Jan 2023 14:11:18 +0000
+Subject: Fix repeated warning for file uploads limit exceeding
+
+(cherry picked from commit 3a2fdef1ae38881110006616ee1f0534b082ca45)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/cfc945efd1ad92d7c118ddf4e021f0a2e25969d4
+
+From: Jakub Zelenka <bukka at php.net>
+Date: Thu, 19 Jan 2023 14:31:25 +0000
+Subject: 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)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/d727c144435cb656f3636343a17c6bd48102ab95
+---
+ main/main.c    |  1 +
+ main/rfc1867.c | 16 +++++++++++++++-
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/main/main.c b/main/main.c
+index 7deb3010..e7edc035 100644
+--- a/main/main.c
++++ b/main/main.c
+@@ -627,6 +627,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 1742b9c0..1eb81827 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;
+ 			}
+@@ -932,7 +943,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 */
diff --git a/php-cve-2023-3247.patch b/php-cve-2023-3247.patch
new file mode 100644
index 0000000..bf0a392
--- /dev/null
+++ b/php-cve-2023-3247.patch
@@ -0,0 +1,98 @@
+From: Niels Dossche <7771979+nielsdos at users.noreply.github.com>
+Date: Sun, 16 Apr 2023 15:05:03 +0200
+Subject: Fix missing randomness check and insufficient random bytes for SOAP HTTP Digest
+
+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 at php.net>
+(cherry picked from commit 126d517ce240e9f638d9a5eaa509eaca49ef562a)
+(cherry picked from commit 0cfca9aa1395271833848daec0bace51d965531d)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/e91122cd59b6331574891a5603b3dc173a1ab205
+
+From: Remi Collet <remi at remirepo.net>
+Date: Tue, 6 Jun 2023 18:05:22 +0200
+Subject: Fix GH-11382 add missing hash header for bin2hex
+
+(cherry picked from commit 40439039c224bb8cdebd1b7b3d03b8cc11e7cce7)
+
+Origin: https://github.com/shivammathur/php-src-backports/commit/24842f1115d64176e545ad893ad95c4650456efa
+---
+ ext/soap/php_http.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
+index b894a1ea..2f281dd7 100644
+--- a/ext/soap/php_http.c
++++ b/ext/soap/php_http.c
+@@ -23,6 +23,7 @@
<Skipped 15299 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/php.git/commitdiff/516f27c2ccf8218e9afcb02c9e8b6f0cfa0104ea



More information about the pld-cvs-commit mailing list