[packages/php/PHP_8_1] Rel 7; security fixes backported for EOL 8.1

arekm arekm at pld-linux.org
Thu Oct 22 09:25:19 CEST 2026


commit 00fc6f8628d7d05eec9ee9e9be1ac1823842960e
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Thu Oct 22 09:24:23 2026 +0200

    Rel 7; security fixes backported for EOL 8.1
    
    From Remi Collet's scl-php81 (shivammathur/php-src-backports) and
    PHP 8.2.35: CVE-2025-1218, CVE-2025-14179, CVE-2025-14181,
    CVE-2026-6103, CVE-2026-6722, CVE-2026-6735, CVE-2026-7258,
    CVE-2026-7259, CVE-2026-7260, CVE-2026-7261, CVE-2026-7262,
    CVE-2026-7568, CVE-2026-9672, CVE-2026-14355, CVE-2026-17543,
    CVE-2026-91765, CVE-2026-91766, CVE-2026-91767, CVE-2026-91768,
    CVE-2026-91769, CVE-2026-92842, CVE-2026-93682, CVE-2026-109618,
    CVE-2026-109619, GHSA-ch8v-r6jh-4vvr.
    
    The 8.1 minimal fix for CVE-2026-109618 lacks the post_max_size limit
    for chunked bodies; added from 01a40e89fbfc. systzdata r22 fixes a
    3-byte heap overflow when UTC is missing from the zoneinfo index.

 php-8.1-cve-2026-109618.patch           | 1180 ++++++
 php-cve-2025-14179.patch                |  274 ++
 php-cve-2026-109618-post_max_size.patch |   30 +
 php-cve-2026-14355.patch                |  118 +
 php-cve-2026-17543.patch                |  223 ++
 php-cve-2026-6722.patch                 |  107 +
 php-cve-2026-6735.patch                 |  144 +
 php-cve-2026-7258.patch                 | 1719 ++++++++
 php-cve-2026-7259.patch                 |   66 +
 php-cve-2026-7260.patch                 |  101 +
 php-cve-2026-7261.patch                 |  111 +
 php-cve-2026-7262.patch                 |   77 +
 php-cve-2026-7568.patch                 |  101 +
 php-cve-2026-9672.patch                 |   46 +
 php-from-8.2.34-to-8.1.patch            | 6641 +++++++++++++++++++++++++++++++
 php-gh22643.patch                       |  133 +
 php-systzdata.patch                     |    3 +-
 php.spec                                |   43 +-
 zend_vm_gen-php85.patch                 |  149 +
 19 files changed, 11264 insertions(+), 2 deletions(-)
---
diff --git a/php.spec b/php.spec
index dd32e63..8f79c6f 100644
--- a/php.spec
+++ b/php.spec
@@ -149,7 +149,7 @@ Summary(ru.UTF-8):	PHP - язык препроцессирования HTML-фа
 Summary(uk.UTF-8):	PHP - мова препроцесування HTML-файлів, виконувана на сервері
 Name:		%{orgname}%{php_suffix}
 Version:	8.1.34
-Release:	6
+Release:	7
 Epoch:		4
 # All files licensed under PHP version 3.01, except
 # Zend is licensed under Zend
@@ -207,6 +207,28 @@ Patch68:	php-mysql-ssl-context.patch
 Patch71:	libdb-info.patch
 Patch72:	php-xml-attr-entity.patch
 Patch73:	opcache-revalidate-path-once.patch
+# https://github.com/php/php-src/commit/d3ef80649e66066fc675d707d0783b167aee19e0
+Patch74:	zend_vm_gen-php85.patch
+# post_max_size part of https://github.com/php/php-src/commit/01a40e89fbfc499936e3b05888d8f00bfde886df, missing in the 8.1 minimal fix
+Patch191:	php-cve-2026-109618-post_max_size.patch
+# Patch200+: security backports for EOL 8.1 by Remi Collet, numbered as in
+# https://git.remirepo.net/cgit/rpms/scl-php81/php.git/tree/php.spec
+# (same commits as https://github.com/shivammathur/php-src-backports/tree/PHP-8.1-security-backports)
+Patch200:	php-cve-2025-14179.patch
+Patch201:	php-cve-2026-6722.patch
+Patch202:	php-cve-2026-7261.patch
+Patch203:	php-cve-2026-7262.patch
+Patch204:	php-cve-2026-6735.patch
+Patch205:	php-cve-2026-7259.patch
+Patch206:	php-cve-2026-7568.patch
+Patch207:	php-cve-2026-7258.patch
+Patch208:	php-cve-2026-14355.patch
+Patch209:	php-cve-2026-9672.patch
+Patch210:	php-cve-2026-17543.patch
+Patch211:	php-cve-2026-7260.patch
+Patch212:	php-gh22643.patch
+Patch213:	php-from-8.2.34-to-8.1.patch
+Patch214:	php-8.1-cve-2026-109618.patch
 URL:		https://www.php.net/
 %{?with_pdo_firebird:%{!?with_interbase_inst:BuildRequires:	Firebird-devel >= 1.0.2.908-2}}
 %{?with_pspell:BuildRequires:	aspell-devel >= 2:0.50.0}
@@ -1907,6 +1929,23 @@ cp -p php.ini-production php.ini
 %patch -P71 -p1 -b .libdb-info
 %patch -P72 -p1 -b .attr-entity
 %patch -P73 -p1
+%patch -P74 -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 -P191 -p1
 
 sed -E -i -e '1s,#!\s*/usr/bin/env\s+(.*),#!%{__bindir}\1,' \
       ext/ext_skel.php \
@@ -2451,6 +2490,7 @@ libtool --mode=install install -p sapi/litespeed/php $RPM_BUILD_ROOT%{_sbindir}/
 %endif
 
 libtool --mode=install install -p libphp_common.la $RPM_BUILD_ROOT%{_libdir}
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/libphp_common.a
 
 # install CGI/FCGI
 %if %{with cgi}
@@ -2511,6 +2551,7 @@ cp -p %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/cli.d/php.ini
 cp -p %{SOURCE2} $RPM_BUILD_ROOT/etc/httpd/conf.d/70_mod_php.conf
 cp -p %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/apache2handler.d/php.ini
 %{__rm} -f $RPM_BUILD_ROOT%{_libdir}/apache/libphp8.la
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/apache/libphp8.a
 %endif
 
 # ensure that paths are correct for current php version and arch
diff --git a/php-8.1-cve-2026-109618.patch b/php-8.1-cve-2026-109618.patch
new file mode 100644
index 0000000..bf356a7
--- /dev/null
+++ b/php-8.1-cve-2026-109618.patch
@@ -0,0 +1,1180 @@
+From 1e06d14cdc77d28b88d2daa99bdfdd4dfaae831b Mon Sep 17 00:00:00 2001
+From: Arnaud Le Blanc <arnaud.lb at gmail.com>
+Date: Sun, 18 Oct 2026 20:12:35 +0200
+Subject: [PATCH] Avoid state corruption via bailout
+
+Minimal mitigation for EOL version.
+
+Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
+Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
+
+Co-authored-by: Ilija Tovilo <ilija.tovilo at me.com>
+(cherry picked from commit 7901b4f9b139d33151e7064b94a165beefa2a772)
+---
+ Zend/zend_API.h                              |  1 +
+ Zend/zend_alloc.c                            | 68 +++++++++-----
+ Zend/zend_alloc.h                            |  2 +
+ Zend/zend_execute_API.c                      | 15 ++++
+ Zend/zend_hash.c                             | 13 ++-
+ Zend/zend_hash.h                             |  1 +
+ Zend/zend_multiply.h                         |  4 +-
+ Zend/zend_strtod.c                           |  4 +-
+ Zend/zend_types.h                            | 26 +++---
+ Zend/zend_vm_def.h                           | 11 ++-
+ Zend/zend_vm_execute.h                       | 94 ++++++++++++++++++--
+ ext/opcache/ZendAccelerator.c                |  5 ++
+ ext/opcache/ZendAccelerator.h                | 11 ++-
+ ext/opcache/zend_file_cache.c                |  8 ++
+ ext/opcache/zend_persist.c                   | 67 ++++++++++++--
+ ext/session/session.c                        |  2 +-
+ ext/zend_test/tests/observer_bug81430_2.phpt |  2 -
+ ext/zend_test/tests/observer_bug81435.phpt   |  1 -
+ ext/zend_test/tests/observer_error_01.phpt   |  2 -
+ main/SAPI.c                                  |  5 ++
+ main/main.c                                  |  6 ++
+ main/php_variables.c                         |  8 +-
+ main/rfc1867.c                               | 28 ++++--
+ 23 files changed, 311 insertions(+), 73 deletions(-)
+
+diff --git a/Zend/zend_API.h b/Zend/zend_API.h
+index 9ed1a3fbabd..a32b83c0533 100644
+--- a/Zend/zend_API.h
++++ b/Zend/zend_API.h
+@@ -490,6 +490,7 @@ ZEND_API const char *zend_get_type_by_const(int type);
+ 
+ #define array_init(arg)				ZVAL_ARR((arg), zend_new_array(0))
+ #define array_init_size(arg, size)	ZVAL_ARR((arg), zend_new_array(size))
++#define array_init_singleton(arg)	ZVAL_ARR((arg), zend_new_array_singleton())
+ ZEND_API void object_init(zval *arg);
+ ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce);
+ ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties);
+diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
+index 61792b37c9c..7f43a7f6df0 100644
+--- a/Zend/zend_alloc.c
++++ b/Zend/zend_alloc.c
+@@ -57,6 +57,7 @@
+ #include "zend_operators.h"
+ #include "zend_multiply.h"
+ #include "zend_bitset.h"
++#include "zend_execute.h"
+ #include <signal.h>
+ 
+ #ifdef HAVE_UNISTD_H
+@@ -364,7 +365,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message)
+ #if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
+ 	kill(getpid(), SIGSEGV);
+ #endif
+-	exit(1);
++	_exit(1);
++}
++
++ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...)
++{
++	zend_string *script_filename = NULL;
++	uint32_t script_lineno = 0;
++
++	if (zend_is_executing()) {
++		script_filename = zend_get_executed_filename_ex();
++		script_lineno = zend_get_executed_lineno();
++	} else if (zend_is_compiling()) {
++		script_filename = zend_get_compiled_filename();
++		script_lineno = zend_get_compiled_lineno();
++	}
++
++	va_list args;
++	va_start(args, format);
++
++	char buf[1024];
++	vsnprintf(buf, sizeof(buf), format, args);
++
++	va_end(args);
++
++	fprintf(stderr,
++			"\nFatal error: %s in %s on line %d\n",
++			buf,
++			script_filename ? ZSTR_VAL(script_filename) : "Unknown",
++			script_lineno);
++
++	/* See http://support.microsoft.com/kb/190351 */
++# ifdef ZEND_WIN32
++	fflush(stderr);
++# endif
++
++	_exit(1);
+ }
+ 
+ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
+@@ -376,22 +412,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
+ #endif
+ 	size_t size)
+ {
++	(void) heap;
+ 
+-	heap->overflow = 1;
+-	zend_try {
+-		zend_error_noreturn(E_ERROR,
+-			format,
+-			limit,
++	zend_mm_safe_error_ex(format, limit,
+ #if ZEND_DEBUG
+-			filename,
+-			lineno,
++		filename,
++		lineno,
+ #endif
+-			size);
+-	} zend_catch {
+-	}  zend_end_try();
+-	heap->overflow = 0;
+-	zend_bailout();
+-	exit(1);
++		size);
+ }
+ 
+ #ifdef _WIN32
+@@ -1356,7 +1384,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
+ 	size = MAX(size, 1);
+ 	size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
+ 	if (UNEXPECTED(size < real_size)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ 		return NULL;
+ 	}
+ #endif
+@@ -1800,7 +1828,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
+ 	void *ptr;
+ 
+ 	if (UNEXPECTED(new_size < size)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment);
+ 	}
+ 
+ #if ZEND_MM_LIMIT
+@@ -2660,7 +2688,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_
+ 
+ 	length = strlen(s);
+ 	if (UNEXPECTED(length + 1 == 0)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ 	}
+ 	p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ 	memcpy(p, s, length+1);
+@@ -2672,7 +2700,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI
+ 	char *p;
+ 
+ 	if (UNEXPECTED(length + 1 == 0)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ 	}
+ 	p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ 	memcpy(p, s, length);
+@@ -2686,7 +2714,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length)
+ 	char *p;
+ 
+ 	if (UNEXPECTED(length + 1 == 0)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length);
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length);
+ 	}
+ 	p = (char *) malloc(length + 1);
+ 	if (UNEXPECTED(p == NULL)) {
+@@ -3084,7 +3112,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
+ static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void)
+ {
+ 	fprintf(stderr, "Out of memory\n");
+-	exit(1);
++	_exit(1);
+ }
+ 
+ ZEND_API void * __zend_malloc(size_t len)
+diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
+index 9603af8a27d..72becadc774 100644
+--- a/Zend/zend_alloc.h
++++ b/Zend/zend_alloc.h
+@@ -403,6 +403,8 @@ static void apc_init_heap(void)
+ size_t zend_mm_globals_size(void);
+ #endif
+ 
++ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...);
++
+ END_EXTERN_C()
+ 
+ #endif
+diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
+index 1e31934f158..82cea225a8e 100644
+--- a/Zend/zend_execute_API.c
++++ b/Zend/zend_execute_API.c
+@@ -385,6 +385,12 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
+ #endif
+ 	} else {
+ 		zend_hash_discard(EG(zend_constants), EG(persistent_constants_count));
++		/* may be used by zend_error_zstr_at before init_executor */
++		ZVAL_UNDEF(&EG(user_error_handler));
++		ZVAL_UNDEF(&EG(user_exception_handler));
++		memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting)));
++		memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers)));
++		memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers)));
+ 	}
+ 
+ 	zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
+@@ -406,6 +412,13 @@ void shutdown_executor(void) /* {{{ */
+ 
+ 	zend_shutdown_executor_values(fast_shutdown);
+ 
++	/* may be used by zend_error_zstr_at before init_executor */
++	EG(record_errors) = false;
++	EG(num_errors) = 0;
++	EG(errors) = NULL;
++	EG(error_handling) = EH_NORMAL;
++	EG(exception) = NULL;
++
+ 	zend_weakrefs_shutdown();
+ 	zend_max_execution_timer_shutdown();
+ 	zend_fiber_shutdown();
+@@ -422,6 +435,8 @@ void shutdown_executor(void) /* {{{ */
+ 		 */
+ 		zend_hash_discard(EG(function_table), EG(persistent_functions_count));
+ 		zend_hash_discard(EG(class_table), EG(persistent_classes_count));
++		EG(objects_store).object_buckets = NULL;
++		EG(objects_store).top = 1;
+ 	} else {
+ 		zend_vm_stack_destroy();
+ 
+diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
+index b96a9511011..65f31c2b9a2 100644
+--- a/Zend/zend_hash.c
++++ b/Zend/zend_hash.c
+@@ -119,7 +119,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
+ 	if (nSize <= HT_MIN_SIZE) {
+ 		return HT_MIN_SIZE;
+ 	} else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
+ 	}
+ 
+ #ifdef ZEND_WIN32
+@@ -276,6 +276,13 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void)
+ 	return ht;
+ }
+ 
++ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void)
++{
++	HashTable *ht = _zend_new_array_0();
++	ht->nTableSize = 1;
++	return ht;
++}
++
+ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize)
+ {
+ 	HashTable *ht = emalloc(sizeof(HashTable));
+@@ -307,7 +314,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
+ {
+ 	HT_ASSERT_RC1(ht);
+ 	if (ht->nTableSize >= HT_MAX_SIZE) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
+ 	}
+ 	uint32_t newTableSize = ht->nTableSize * 2;
+ 	HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(newTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT));
+@@ -1233,7 +1240,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
+ 		pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
+ 		zend_hash_rehash(ht);
+ 	} else {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
+ 	}
+ }
+ 
+diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
+index 092682d6771..09a7994d91d 100644
+--- a/Zend/zend_hash.h
++++ b/Zend/zend_hash.h
+@@ -314,6 +314,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht);
+ #endif
+ 
+ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void);
++ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void);
+ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size);
+ ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2);
+ ZEND_API uint32_t zend_array_count(HashTable *ht);
+diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
+index c6cd472a237..bfe1b8e8869 100644
+--- a/Zend/zend_multiply.h
++++ b/Zend/zend_multiply.h
+@@ -321,7 +321,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t
+ 	size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
+ 
+ 	if (UNEXPECTED(overflow)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
++		zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+ 		return 0;
+ 	}
+ 	return ret;
+@@ -334,7 +334,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si
+ 	size_t ret = zend_safe_address(nmemb, size, offset, &overflow);
+ 
+ 	if (UNEXPECTED(overflow)) {
+-		zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
++		zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset);
+ 		return 0;
+ 	}
+ 	return ret;
+diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
+index 3e7f90378ef..7f72c82f610 100644
+--- a/Zend/zend_strtod.c
++++ b/Zend/zend_strtod.c
+@@ -593,7 +593,7 @@ Balloc
+ 		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+ 		if (!rv) {
+ 			FREE_DTOA_LOCK(0);
+-			zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
++			zend_mm_safe_error_ex("Balloc() failed to allocate memory");
+ 		}
+ #else
+ 		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+@@ -606,7 +606,7 @@ Balloc
+ 			rv = (Bigint*)MALLOC(len*sizeof(double));
+ 			if (!rv) {
+ 				FREE_DTOA_LOCK(0);
+-				zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory");
++				zend_mm_safe_error_ex("Balloc() failed to allocate memory");
+ 			}
+ #endif
+ 		rv->k = k;
+diff --git a/Zend/zend_types.h b/Zend/zend_types.h
+index 5bc47dd3193..ab28b0fa163 100644
+--- a/Zend/zend_types.h
++++ b/Zend/zend_types.h
+@@ -448,17 +448,21 @@ struct _zend_array {
+ # define HT_HASH_RESET(ht) do { \
+ 		char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \
+ 		size_t size = HT_HASH_SIZE((ht)->nTableMask); \
+-		__m128i xmm0 = _mm_setzero_si128(); \
+-		xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
+-		ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
+-		do { \
+-			_mm_storeu_si128((__m128i*)p, xmm0); \
+-			_mm_storeu_si128((__m128i*)(p+16), xmm0); \
+-			_mm_storeu_si128((__m128i*)(p+32), xmm0); \
+-			_mm_storeu_si128((__m128i*)(p+48), xmm0); \
+-			p += 64; \
+-			size -= 64; \
+-		} while (size != 0); \
++		if (UNEXPECTED(size < 64)) { \
++			memset(p, HT_INVALID_IDX, size); \
++		} else { \
++			__m128i xmm0 = _mm_setzero_si128(); \
++			xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
++			ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
++			do { \
++				_mm_storeu_si128((__m128i*)p, xmm0); \
++				_mm_storeu_si128((__m128i*)(p+16), xmm0); \
++				_mm_storeu_si128((__m128i*)(p+32), xmm0); \
++				_mm_storeu_si128((__m128i*)(p+48), xmm0); \
++				p += 64; \
++				size -= 64; \
++			} while (size != 0); \
++		} \
+ 	} while (0)
+ #else
+ # define HT_HASH_RESET(ht) \
+diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
+index a6f86a9eab6..ad893ebfb5c 100644
+--- a/Zend/zend_vm_def.h
++++ b/Zend/zend_vm_def.h
+@@ -408,7 +408,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -417,6 +417,9 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -3183,6 +3186,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -3190,6 +3196,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
+index 5ee1c2c94da..dc78ba4a08d 100644
+--- a/Zend/zend_vm_execute.h
++++ b/Zend/zend_vm_execute.h
+@@ -6549,6 +6549,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -6556,6 +6559,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -8456,7 +8462,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -8465,6 +8471,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -8872,6 +8881,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -8879,6 +8891,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -10821,7 +10836,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -10830,6 +10845,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -11237,6 +11255,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -11244,6 +11265,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -14866,7 +14890,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -14875,6 +14899,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -15596,6 +15623,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -15603,6 +15633,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -16295,7 +16328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -16304,6 +16337,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -17025,6 +17061,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -17032,6 +17071,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -17981,7 +18023,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -17990,6 +18032,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -18349,6 +18394,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -18356,6 +18404,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -39651,7 +39702,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -39660,6 +39711,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -42142,6 +42196,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -42149,6 +42206,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -43460,7 +43520,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -43469,6 +43529,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -45880,6 +45943,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -45887,6 +45953,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -48757,7 +48826,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
+ 			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
+-				zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
+ 			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -48766,6 +48835,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+@@ -51276,6 +51348,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
+ 		    !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ 		    size_t len = ZSTR_LEN(op1_str);
+ 
++			if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+ 			ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+@@ -51283,6 +51358,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
+ 				zend_string_release_ex(op2_str, 0);
+ 			}
+ 		} else {
++			if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
++				zend_mm_safe_error_ex("Integer overflow in memory allocation");
++			}
+ 			str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
+ 			memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
+ 			memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
+diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
+index 530620f6259..e030b441319 100644
+--- a/ext/opcache/ZendAccelerator.c
++++ b/ext/opcache/ZendAccelerator.c
+@@ -2410,6 +2410,7 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
+ 	}
+ 
+ 	zend_map_ptr_extend(ZCSG(map_ptr_last));
++	zend_accel_pending_ce_cache_begin();
+ 
+ #if ZEND_MM_ALIGNMENT < 8
+ 	/* Align to 8-byte boundary */
+@@ -2456,6 +2457,7 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
+ 	EG(errors) = NULL;
+ 
+ 	ZCSG(map_ptr_last) = CG(map_ptr_last);
++	zend_accel_pending_ce_cache_commit();
+ 
+ 	zend_shared_alloc_destroy_xlat_table();
+ 
+@@ -2780,6 +2782,9 @@ zend_result accel_post_deactivate(void)
+ 		ZCG(cwd) = NULL;
+ 	}
+ 
++	/* A persist window left through a bailout never published its slots */
++	zend_accel_pending_ce_cache_discard();
++
+ 	if (!ZCG(enabled) || !accel_startup_ok) {
+ 		return SUCCESS;
+ 	}
+diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
+index de5ec45de72..72d3a239342 100644
+--- a/ext/opcache/ZendAccelerator.h
++++ b/ext/opcache/ZendAccelerator.h
+@@ -225,6 +225,12 @@ typedef struct _zend_accel_globals {
+ 	/* preallocated buffer for keys */
+ 	zend_string             key;
+ 	char                    _key[MAXPATHLEN * 8];
++
++	/* CE cache slots allocated during the current persist window, keyed by the
++	 * address of the shared class name string. They are written into the
++	 * strings by zend_accel_pending_ce_cache_commit() once ZCSG(map_ptr_last)
++	 * covers them. NULL outside a persist window. */
++	HashTable              *pending_ce_cache;
+ } zend_accel_globals;
+ 
+ typedef struct _zend_string_table {
+@@ -322,7 +328,10 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
+ 
+ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str);
+ 
+-uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name);
++void zend_accel_get_class_name_map_ptr(zend_string *type_name);
++void zend_accel_pending_ce_cache_begin(void);
++void zend_accel_pending_ce_cache_commit(void);
++void zend_accel_pending_ce_cache_discard(void);
+ 
+ /* memory write protection */
+ #define SHM_PROTECT() \
+diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
+index 7b4b4cbb121..f1b1da2baa7 100644
+--- a/ext/opcache/zend_file_cache.c
++++ b/ext/opcache/zend_file_cache.c
+@@ -1696,6 +1696,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
+ 	int cache_it = 1;
+ 	unsigned int actual_checksum;
+ 	int ok;
++	size_t orig_map_ptr_last = 0;
+ 
+ 	if (!full_path) {
+ 		return NULL;
+@@ -1831,6 +1832,8 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
+ 		}
+ 		memcpy(buf, mem, info.mem_size);
+ 		zend_map_ptr_extend(ZCSG(map_ptr_last));
++		orig_map_ptr_last = CG(map_ptr_last);
++		zend_accel_pending_ce_cache_begin();
+ 	} else {
+ use_process_mem:
+ 		buf = mem;
+@@ -1849,6 +1852,10 @@ use_process_mem:
+ 	} zend_end_try();
+ 	if (!ok) {
+ 		if (cache_it) {
++			/* The slots allocated by the failed unserialization are referenced
++			 * only by the abandoned buffer, so they can be reclaimed. */
++			zend_accel_pending_ce_cache_discard();
++			CG(map_ptr_last) = orig_map_ptr_last;
+ 			zend_shared_alloc_unlock();
+ 			goto use_process_mem;
+ 		} else {
+@@ -1862,6 +1869,7 @@ use_process_mem:
+ 
+ 	if (cache_it) {
+ 		ZCSG(map_ptr_last) = CG(map_ptr_last);
++		zend_accel_pending_ce_cache_commit();
+ 		script->dynamic_members.checksum = zend_accel_script_checksum(script);
+ 		script->dynamic_members.last_used = ZCG(request_time);
+ 
+diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
+index 49dfea34e33..4ff93a12b33 100644
+--- a/ext/opcache/zend_persist.c
++++ b/ext/opcache/zend_persist.c
+@@ -299,31 +299,78 @@ static HashTable *zend_persist_attributes(HashTable *attributes)
+ 	return ptr;
+ }
+ 
+-uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name)
++/* We delay the publishing of CE cache slots until after ZCSG(map_ptr_last) is
++ * published.
++ * CE cache slots stored in interned strings are immediately visible to other
++ * processes, so if we fail to update ZCSG(map_ptr_last) after publishing a
++ * slot (due to a bailout/exit), that slot may be re-allocated for something
++ * else by other processes. */
++void zend_accel_pending_ce_cache_begin(void)
++{
++	ZEND_ASSERT(ZCG(locked));
++
++	/* A persist window left through a bailout caught by the caller (e.g.
++	 * opcache_compile_file()) never published its slots. Drop them. */
++	zend_accel_pending_ce_cache_discard();
++
++	ZCG(pending_ce_cache) = emalloc(sizeof(HashTable));
++	zend_hash_init(ZCG(pending_ce_cache), 8, NULL, NULL, 0);
++}
++
++void zend_accel_pending_ce_cache_commit(void)
++{
++	ZEND_ASSERT(ZCG(pending_ce_cache));
++	/* Every pending slot must be covered by ZCSG(map_ptr_last) */
++	ZEND_ASSERT(ZCSG(map_ptr_last) == CG(map_ptr_last));
++
++	ZEND_HASH_FOREACH_NUM_KEY_VAL(ZCG(pending_ce_cache), zend_ulong h, zval *zv) {
++		zend_string *type_name = (zend_string*)(uintptr_t)h;
++
++		ZEND_ASSERT(!ZSTR_HAS_CE_CACHE(type_name));
++		GC_SET_REFCOUNT(type_name, (uint32_t)Z_LVAL_P(zv));
++		GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
++	} ZEND_HASH_FOREACH_END();
++
++	zend_accel_pending_ce_cache_discard();
++}
++
++void zend_accel_pending_ce_cache_discard(void)
++{
++	if (ZCG(pending_ce_cache)) {
++		zend_hash_destroy(ZCG(pending_ce_cache));
++		efree(ZCG(pending_ce_cache));
++		ZCG(pending_ce_cache) = NULL;
++	}
++}
++
++void zend_accel_get_class_name_map_ptr(zend_string *type_name)
+ {
+ 	uint32_t ret;
++	zval *slot;
+ 
+ 	if (zend_string_equals_literal_ci(type_name, "self") ||
+ 			zend_string_equals_literal_ci(type_name, "parent")) {
+-		return 0;
++		return;
+ 	}
+ 
+ 	/* We use type.name.gc.refcount to keep map_ptr of corresponding type */
+ 	if (ZSTR_HAS_CE_CACHE(type_name)) {
+-		return GC_REFCOUNT(type_name);
++		return;
+ 	}
+ 
+ 	if ((GC_FLAGS(type_name) & GC_IMMUTABLE)
+ 	 && (GC_FLAGS(type_name) & IS_STR_PERMANENT)) {
++		ZEND_ASSERT(ZCG(pending_ce_cache) && "Must be called inside a persist window");
++		slot = zend_hash_index_lookup(ZCG(pending_ce_cache), (zend_ulong)(uintptr_t)type_name);
++		if (Z_TYPE_P(slot) != IS_NULL) {
++			/* Already allocated earlier in this window */
++			return;
++		}
+ 		do {
+ 			ret = ZEND_MAP_PTR_NEW_OFFSET();
+ 		} while (ret <= 2);
+-		GC_SET_REFCOUNT(type_name, ret);
+-		GC_ADD_FLAGS(type_name, IS_STR_CLASS_NAME_MAP_PTR);
+-		return ret;
++		ZVAL_LONG(slot, ret);
+ 	}
+-
+-	return 0;
+ }
+ 
+ static HashTable *zend_persist_backed_enum_table(HashTable *backed_enum_table)
+@@ -1312,6 +1359,9 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
+ #endif
+ 
+ 	zend_map_ptr_extend(ZCSG(map_ptr_last));
++	if (for_shm) {
++		zend_accel_pending_ce_cache_begin();
++	}
+ 
+ 	zend_accel_persist_class_table(&script->script.class_table);
+ 	zend_hash_persist(&script->script.function_table);
+@@ -1336,6 +1386,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
+ 
+ 	if (for_shm) {
+ 		ZCSG(map_ptr_last) = CG(map_ptr_last);
++		zend_accel_pending_ce_cache_commit();
+ 	}
+ 
+ #ifdef HAVE_JIT
+diff --git a/ext/session/session.c b/ext/session/session.c
+index 114df24b464..d72ae27b448 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -3000,7 +3000,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo
+ 	if (php_session_rfc1867_orig_callback) {
+ 		retval = php_session_rfc1867_orig_callback(event, event_data, extra);
+ 	}
+-	if (!PS(rfc1867_enabled)) {
++	if (!PS(rfc1867_enabled) || true) {
+ 		return retval;
+ 	}
+ 
+diff --git a/ext/zend_test/tests/observer_bug81430_2.phpt b/ext/zend_test/tests/observer_bug81430_2.phpt
+index 90e0fa5ce01..2cdbca9a702 100644
+--- a/ext/zend_test/tests/observer_bug81430_2.phpt
++++ b/ext/zend_test/tests/observer_bug81430_2.phpt
+@@ -30,5 +30,3 @@ call_user_func([$r->getAttributes(A::class)[0], 'newInstance']);
+   <A::__construct>
+ 
+ Fatal error: Allowed memory size of %d bytes exhausted %s in %s on line %d
+-  </A::__construct>
+-</file '%s'>
+diff --git a/ext/zend_test/tests/observer_bug81435.phpt b/ext/zend_test/tests/observer_bug81435.phpt
+index 7b927e55fb1..e435292da0b 100644
+--- a/ext/zend_test/tests/observer_bug81435.phpt
++++ b/ext/zend_test/tests/observer_bug81435.phpt
+@@ -45,4 +45,3 @@ a();
+   <!-- init bailout() -->
+ 
+ Fatal error: Allowed memory size of 20971520 bytes exhausted %s in %s on line %d
+-</a>
+diff --git a/ext/zend_test/tests/observer_error_01.phpt b/ext/zend_test/tests/observer_error_01.phpt
+index 10b1e569b0f..70a761016a8 100644
+--- a/ext/zend_test/tests/observer_error_01.phpt
++++ b/ext/zend_test/tests/observer_error_01.phpt
+@@ -26,5 +26,3 @@ echo 'You should not see this.';
+   <foo>
+ 
+ Fatal error: Allowed memory size of 2097152 bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
+-  </foo:NULL>
+-</file '%s%eobserver_error_%d.php'>
+diff --git a/main/SAPI.c b/main/SAPI.c
+index 8b47a6c828c..57c30e57f71 100644
+--- a/main/SAPI.c
++++ b/main/SAPI.c
+@@ -507,18 +507,23 @@ SAPI_API void sapi_deactivate_module(void)
+ 	}
+ 	if (SG(request_info).auth_user) {
+ 		efree(SG(request_info).auth_user);
++		SG(request_info).auth_user = NULL;
+ 	}
+ 	if (SG(request_info).auth_password) {
+ 		efree(SG(request_info).auth_password);
++		SG(request_info).auth_password = NULL;
+ 	}
+ 	if (SG(request_info).auth_digest) {
+ 		efree(SG(request_info).auth_digest);
++		SG(request_info).auth_digest = NULL;
+ 	}
+ 	if (SG(request_info).content_type_dup) {
+ 		efree(SG(request_info).content_type_dup);
++		SG(request_info).content_type_dup = NULL;
+ 	}
+ 	if (SG(request_info).current_user) {
+ 		efree(SG(request_info).current_user);
++		SG(request_info).current_user = NULL;
+ 	}
+ 	if (sapi_module.deactivate) {
+ 		sapi_module.deactivate();
+diff --git a/main/main.c b/main/main.c
+index 9c62aa914eb..b9994ccf9d2 100644
+--- a/main/main.c
++++ b/main/main.c
+@@ -1850,6 +1850,8 @@ void php_request_shutdown(void *dummy)
+ 
+ 		for (i=0; i<NUM_TRACK_VARS; i++) {
+ 			zval_ptr_dtor(&PG(http_globals)[i]);
++			/* May be accessed before php_request_startup() */
++			ZVAL_UNDEF(&PG(http_globals)[i]);
+ 		}
+ 	} zend_end_try();
+ 
+@@ -1882,6 +1884,7 @@ void php_request_shutdown(void *dummy)
+ 	/* 15. Free Willy (here be crashes) */
+ 	zend_arena_destroy(CG(arena));
+ 	zend_interned_strings_deactivate();
++	clear_last_error();
+ 	zend_try {
+ 		shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
+ 	} zend_end_try();
+@@ -1905,6 +1908,9 @@ void php_request_shutdown(void *dummy)
+ #ifdef HAVE_DTRACE
+ 	DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
+ #endif /* HAVE_DTRACE */
++
++	/* May be accessed before php_request_startup() */
++	PG(modules_activated) = 0;
+ }
+ /* }}} */
+ 
+diff --git a/main/php_variables.c b/main/php_variables.c
+index a851c347601..35708907d63 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -214,7 +214,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
+ 			}
+ 
+ 			if (!index) {
+-				array_init(&gpc_element);
++				array_init_singleton(&gpc_element);
+ 				if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) {
+ 					zend_array_destroy(Z_ARR(gpc_element));
+ 					zval_ptr_dtor_nogc(val);
+@@ -231,7 +231,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
+ 				gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
+ 				if (!gpc_element_p) {
+ 					zval tmp;
+-					array_init(&tmp);
++					array_init_singleton(&tmp);
+ 					gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
+ 				} else {
+ 					if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
+@@ -239,7 +239,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
+ 					}
+ 					if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
+ 						zval_ptr_dtor_nogc(gpc_element_p);
+-						array_init(gpc_element_p);
++						array_init_singleton(gpc_element_p);
+ 					} else {
+ 						SEPARATE_ARRAY(gpc_element_p);
+ 					}
+@@ -437,7 +437,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ 		case PARSE_POST:
+ 		case PARSE_GET:
+ 		case PARSE_COOKIE:
+-			array_init(&array);
++			array_init_singleton(&array);
+ 			switch (arg) {
+ 				case PARSE_POST:
+ 					zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index c57e26b11b9..f98070bfcf7 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -389,6 +389,14 @@ static int find_boundary(multipart_buffer *self, char *boundary)
+ 	return 0;
+ }
+ 
++static zend_bool php_mime_should_save_hdr(const char *name)
++{
++	return !strcasecmp(name, "Content-Disposition")
++		|| !strcasecmp(name, "Content-Type");
++}
++
++static char *php_mime_get_hdr_value(zend_llist header, char *key);
++
+ /* parse headers */
+ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
+ {
+@@ -429,10 +437,16 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
+ 			}
+ 
+ 			*value = '\0';
+-			do { value++; } while (isspace((unsigned char)*value));
+ 
+-			key = estrdup(line);
+-			smart_string_appends(&buf_value, value);
++			/* Keep only headers we use, and ignore duplicates */
++			if (!php_mime_should_save_hdr(line)
++					|| php_mime_get_hdr_value(*header, line)) {
++				key = NULL;
++			} else {
++				key = estrdup(line);
++				do { value++; } while (isspace((unsigned char)*value));
++				smart_string_appends(&buf_value, value);
++			}
+ 		} else if (buf_value.c) { /* If no ':' on the line, add to previous line */
+ 			smart_string_appends(&buf_value, line);
+ 		} else {
+@@ -506,11 +520,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
+ 	return res;
+ }
+ 
+-static char *substring_conf(char *start, int len, char quote)
++static char *substring_conf(char *start, size_t len, char quote)
+ {
+ 	char *result = emalloc(len + 1);
+ 	char *resp = result;
+-	int i;
++	size_t i;
+ 
+ 	for (i = 0; i < len && start[i] != quote; ++i) {
+ 		if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
+@@ -538,14 +552,14 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
+ 		char quote = *str;
+ 
+ 		str++;
+-		return substring_conf(str, (int)strlen(str), quote);
++		return substring_conf(str, strlen(str), quote);
+ 	} else {
+ 		char *strend = str;
+ 
+ 		while (*strend && !isspace((unsigned char)*strend)) {
+ 			++strend;
+ 		}
+-		return substring_conf(str, strend - str, 0);
++		return substring_conf(str, (size_t)(strend - str), 0);
+ 	}
+ }
+ 
+-- 
+2.43.7
+
diff --git a/php-cve-2025-14179.patch b/php-cve-2025-14179.patch
new file mode 100644
index 0000000..71e15cd
--- /dev/null
+++ b/php-cve-2025-14179.patch
@@ -0,0 +1,274 @@
+From 4b0dd469bbba7bf5f25f1a4f694aeb15c3515be4 Mon Sep 17 00:00:00 2001
+From: Saki Takamachi <saki at sakiot.com>
+Date: Sun, 3 May 2026 19:56:30 +0200
+Subject: [PATCH 07/10] GHSA-w476-322c-wpvm: [pdo_firebird] Fix SQL injection
+ via NUL bytes in quoted strings
+
+Fixes GHSA-w476-322c-wpvm
+Fixes CVE-2025-14179
+
+(cherry picked from commit 3f40b65323dd1b85e9bab6878237d3867e449d5c)
+---
+ ext/pdo_firebird/firebird_driver.c            | 69 ++++++++++++-------
+ .../tests/ghsa-w476-322c-wpvm.phpt            | 44 ++++++++++++
+ 2 files changed, 88 insertions(+), 25 deletions(-)
+ create mode 100644 ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt
+
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index a446622c90e..25882919f86 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -291,7 +291,7 @@ static FbTokenType getToken(const char** begin, const char* end)
+ 	return ret;
+ }
+ 
+-int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
++int preprocess(const zend_string* sql, char* sql_out, size_t* sql_out_len, HashTable* named_params)
+ {
+ 	bool passAsIs = 1, execBlock = 0;
+ 	zend_long pindex = -1;
+@@ -322,7 +322,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 	if (l > 252) {
+ 		return 0;
+ 	}
+-	strncpy(ident, i, l);
++	memcpy(ident, i, l);
+ 	ident[l] = '\0';
+ 	if (!strcasecmp(ident, "EXECUTE"))
+ 	{
+@@ -347,7 +347,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 		if (l > 252) {
+ 			return 0;
+ 		}
+-		strncpy(ident2, i2, l);
++		memcpy(ident2, i2, l);
+ 		ident2[l] = '\0';
+ 		execBlock = !strcasecmp(ident2, "BLOCK");
+ 		passAsIs = 0;
+@@ -363,11 +363,15 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 
+ 	if (passAsIs)
+ 	{
+-		strcpy(sql_out, ZSTR_VAL(sql));
++		memcpy(sql_out, ZSTR_VAL(sql), ZSTR_LEN(sql));
++		sql_out[ZSTR_LEN(sql)] = '\0';
++		*sql_out_len = ZSTR_LEN(sql);
+ 		return 1;
+ 	}
+ 
+-	strncat(sql_out, start, p - start);
++	char *sql_out_p = sql_out;
++	memcpy(sql_out_p, start, p - start);
++	sql_out_p += p - start;
+ 
+ 	while (p < end)
+ 	{
+@@ -375,10 +379,12 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 		tok = getToken(&p, end);
+ 		switch (tok)
+ 		{
+-		case ttParamMark:
+-			tok = getToken(&p, end);
++		case ttParamMark: {
++			const char* p_peek = p;
++			tok = getToken(&p_peek, end);
+ 			if (tok == ttIdent /*|| tok == ttString*/)
+ 			{
++				p = p_peek;
+ 				++pindex;
+ 				l = p - start;
+ 				/* check the length of the identifier */
+@@ -387,7 +393,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 				if (l > 253) {
+ 					return 0;
+ 				}
+-				strncpy(pname, start, l);
++				memcpy(pname, start, l);
+ 				pname[l] = '\0';
+ 
+ 				if (named_params) {
+@@ -396,7 +402,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 					zend_hash_str_update(named_params, pname, l, &tmp);
+ 				}
+ 
+-				strcat(sql_out, "?");
++				*sql_out_p++ = '?';
+ 			}
+ 			else
+ 			{
+@@ -406,10 +412,11 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 					return 0;
+ 				}
+ 				++pindex;
+-				strncat(sql_out, start, p - start);
++				memcpy(sql_out_p, start, p - start);
++				sql_out_p += p - start;
+ 			}
+ 			break;
+-
++		}
+ 		case ttIdent:
+ 			if (execBlock)
+ 			{
+@@ -421,11 +428,14 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 				if (l > 252) {
+ 					return 0;
+ 				}
+-				strncpy(ident, start, l);
++				memcpy(ident, start, l);
+ 				ident[l] = '\0';
+ 				if (!strcasecmp(ident, "AS"))
+ 				{
+-					strncat(sql_out, start, end - start);
++					memcpy(sql_out_p, start, end - start);
++					sql_out_p += end - start;
++					*sql_out_p = '\0';
++					*sql_out_len = sql_out_p - sql_out;
+ 					return 1;
+ 				}
+ 			}
+@@ -436,7 +446,8 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 		case ttComment:
+ 		case ttString:
+ 		case ttOther:
+-			strncat(sql_out, start, p - start);
++			memcpy(sql_out_p, start, p - start);
++			sql_out_p += p - start;
+ 			break;
+ 
+ 		case ttBrokenComment:
+@@ -454,6 +465,8 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params)
+ 			break;
+ 		}
+ 	}
++	*sql_out_p = '\0';
++	*sql_out_len = sql_out_p - sql_out;
+ 	return 1;
+ }
+ 
+@@ -663,7 +676,7 @@ free_statement:
+ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype)
+ {
+ 	size_t qcount = 0;
+-	char const *co, *l, *r;
++	char const *co, *l;
+ 	char *c;
+ 	size_t quotedlen;
+ 	zend_string *quoted_str;
+@@ -672,9 +685,15 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
+ 		return zend_string_init("''", 2, 0);
+ 	}
+ 
++	const char * const end = ZSTR_VAL(unquoted) + ZSTR_LEN(unquoted);
++
+ 	/* Firebird only requires single quotes to be doubled if string lengths are used */
+ 	/* count the number of ' characters */
+-	for (co = ZSTR_VAL(unquoted); (co = strchr(co,'\'')); qcount++, co++);
++	for (co = ZSTR_VAL(unquoted); co < end; co++) {
++		if (*co == '\'') {
++			qcount++;
++		}
++	}
+ 
+ 	if (UNEXPECTED(ZSTR_LEN(unquoted) + 2 > ZSTR_MAX_LEN - qcount)) {
+ 		return NULL;
+@@ -686,15 +705,14 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un
+ 	*c++ = '\'';
+ 
+ 	/* foreach (chunk that ends in a quote) */
+-	for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) {
+-		strncpy(c, l, r-l+1);
+-		c += (r-l+1);
+-		/* add the second quote */
+-		*c++ = '\'';
++	for (l = ZSTR_VAL(unquoted); l < end; l++) {
++		*c++ = *l;
++		if (*l == '\'') {
++			/* add the second quote */
++			*c++ = '\'';
++		}
+ 	}
+ 
+-	/* copy the remainder */
+-	strncpy(c, l, quotedlen-(c-ZSTR_VAL(quoted_str))-1);
+ 	ZSTR_VAL(quoted_str)[quotedlen-1] = '\'';
+ 	ZSTR_VAL(quoted_str)[quotedlen]   = '\0';
+ 
+@@ -787,6 +805,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
+ {
+ 	pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+ 	char *new_sql;
++	size_t new_sql_len;
+ 
+ 	/* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
+ 	if (ZSTR_LEN(sql) > 65536) {
+@@ -814,14 +833,14 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql,
+ 	   we need to replace :foo by ?, and store the name we just replaced */
+ 	new_sql = emalloc(ZSTR_LEN(sql)+1);
+ 	new_sql[0] = '\0';
+-	if (!preprocess(sql, new_sql, named_params)) {
++	if (!preprocess(sql, new_sql, &new_sql_len, named_params)) {
+ 		strcpy(dbh->error_code, "07000");
+ 		efree(new_sql);
+ 		return 0;
+ 	}
+ 
+ 	/* prepare the statement */
+-	if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, H->sql_dialect, out_sqlda)) {
++	if (isc_dsql_prepare(H->isc_status, &H->tr, s, new_sql_len, new_sql, H->sql_dialect, out_sqlda)) {
+ 		RECORD_ERROR(dbh);
+ 		efree(new_sql);
+ 		return 0;
+diff --git a/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt b/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt
+new file mode 100644
+index 00000000000..41c1125e9b9
+--- /dev/null
++++ b/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt
+@@ -0,0 +1,44 @@
++--TEST--
++GHSA-w476-322c-wpvm: SQL injection in pdo_firebird via NUL bytes in quoted strings
++--EXTENSIONS--
++pdo_firebird
++--SKIPIF--
++<?php require('skipif.inc'); ?>
++--XLEAK--
++A bug in firebird causes a memory leak when calling `isc_attach_database()`.
++See https://github.com/FirebirdSQL/firebird/issues/7849
++--FILE--
++<?php
++
++require("testdb.inc");
++
++$dbh->exec('CREATE TABLE ghsa_w476_322c_wpvm (name VARCHAR(255))');
++
++$param = $dbh->quote("\0");
++$param2 = $dbh->quote('or 1=1--');
++var_export($param);
++echo("\n");
++
++echo "prepare: ";
++$stmt = $dbh->prepare("SELECT * FROM ghsa_w476_322c_wpvm WHERE name = {$param} AND name = {$param2}");
++$stmt->execute();
++echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)) . "\n";
++
++echo "query:   ";
++$stmt = $dbh->query("SELECT * FROM ghsa_w476_322c_wpvm WHERE name = {$param} AND name = {$param2}");
++echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)) . "\n";
++
++echo "exec:    ";
++$affectedRows = $dbh->exec("UPDATE ghsa_w476_322c_wpvm SET name = 'updated' WHERE name = {$param} AND name = {$param2}");
++echo $affectedRows . "\n";
++?>
++--CLEAN--
++<?php
++require 'testdb.inc';
++$dbh->exec("DROP TABLE ghsa_w476_322c_wpvm");
++?>
++--EXPECT--
++'\'' . "\0" . '\''
++prepare: []
++query:   []
++exec:    0
+-- 
+2.54.0
+
diff --git a/php-cve-2026-109618-post_max_size.patch b/php-cve-2026-109618-post_max_size.patch
new file mode 100644
index 0000000..cff649d
--- /dev/null
+++ b/php-cve-2026-109618-post_max_size.patch
@@ -0,0 +1,30 @@
+Stop reading a multipart body once it exceeds post_max_size. Without a
+Content-Length (chunked request body, e.g. Apache mod_php) the initial
+post_max_size check does not apply and the body is read without limit.
+
+Part of https://github.com/php/php-src/commit/01a40e89fbfc499936e3b05888d8f00bfde886df
+(GHSA-w8hw-w9fx-j79w, CVE-2026-109618), not in the minimal PHP 8.1 fix.
+
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -242,6 +242,10 @@
+ 
+ 	self->buf_begin = self->buffer;
+ 
++	if (SG(post_max_size) > 0 && SG(read_post_bytes) > SG(post_max_size)) {
++		return 0;
++	}
++
+ 	/* calculate the free space in the buffer */
+ 	bytes_to_read = self->bufsize - self->bytes_in_buffer;
+ 
+@@ -1291,6 +1295,9 @@
+ 	}
+ 
+ fileupload_done:
++	if (SG(post_max_size) > 0 && SG(read_post_bytes) > SG(post_max_size)) {
++		sapi_module.sapi_error(E_WARNING, "Actual POST length does not match Content-Length, and exceeds " ZEND_LONG_FMT " bytes", SG(post_max_size));
++	}
+ 	if (php_rfc1867_callback != NULL) {
+ 		multipart_event_end event_end;
+ 
diff --git a/php-cve-2026-14355.patch b/php-cve-2026-14355.patch
new file mode 100644
index 0000000..ea9c407
--- /dev/null
+++ b/php-cve-2026-14355.patch
@@ -0,0 +1,118 @@
+From 95e9851111d249e43948b76663cff1baeb5e758d Mon Sep 17 00:00:00 2001
+From: David Carlier <devnexen at gmail.com>
+Date: Fri, 29 May 2026 21:44:14 +0100
+Subject: [PATCH] ext/openssl: openssl_encrypt() zend mm heap overflow on
+ AES-WRAP-PAD mode.
+
+Fix #22186
+
+close GH-22187
+
+(cherry picked from commit cbc0489126a7682796aad1e5fb4e51de74af162c)
+---
+ NEWS                           |  6 ++++++
+ ext/openssl/openssl.c          | 17 +++++++++++++++--
+ ext/openssl/tests/gh22186.phpt | 32 ++++++++++++++++++++++++++++++++
+ 3 files changed, 53 insertions(+), 2 deletions(-)
+ create mode 100644 ext/openssl/tests/gh22186.phpt
+
+diff --git a/NEWS b/NEWS
+index c245d3e757e..191502bb73b 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,6 +1,12 @@
+ PHP                                                                        NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+ 
++Backported from 8.2.32
++
++- OpenSSL:
++  . Fixed bug GH-22187 (Memory corruption (zend_mm_heap corrupted) in
++    openssl_encrypt with AES-WRAP-PAD). (David Carlier)
++
+ Backported from 8.2.31
+ 
+ - FPM:
+diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
+index a6a05fe03db..331e94ba55e 100644
+--- a/ext/openssl/openssl.c
++++ b/ext/openssl/openssl.c
+@@ -7472,6 +7472,7 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
+ 		const char *aad, size_t aad_len, int enc)  /* {{{ */
+ {
+ 	int i = 0;
++	size_t outlen = data_len + EVP_CIPHER_block_size(cipher_type);
+ 
+ 	if (mode->is_single_run_aead && !EVP_CipherUpdate(cipher_ctx, NULL, &i, NULL, (int)data_len)) {
+ 		php_openssl_store_errors();
+@@ -7485,7 +7486,19 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
+ 		return FAILURE;
+ 	}
+ 
+-	*poutbuf = zend_string_alloc((int)data_len + EVP_CIPHER_block_size(cipher_type), 0);
++#ifdef EVP_CIPH_WRAP_MODE
++	if ((EVP_CIPHER_mode(cipher_type)) == EVP_CIPH_WRAP_MODE) {
++		/*
++		 * RFC 5649 wrap-with-padding rounds the input up to the block size
++		 * and prepends an integrity block, we reserve one extra block.
++		 * See EVP_EncryptUpdate(3): wrap mode may write up to
++		 * inl + cipher_block_size bytes.
++		 */
++		outlen += EVP_CIPHER_block_size(cipher_type);
++	}
++#endif
++
++	*poutbuf = zend_string_alloc(outlen, false);
+ 
+ 	if (!EVP_CipherUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(*poutbuf),
+ 					&i, (const unsigned char *)data, (int)data_len)) {
+@@ -7497,7 +7510,7 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
+ 		}
+ 		*/
+ 		php_openssl_store_errors();
+-		zend_string_release_ex(*poutbuf, 0);
++		zend_string_release_ex(*poutbuf, false);
+ 		return FAILURE;
+ 	}
+ 
+diff --git a/ext/openssl/tests/gh22186.phpt b/ext/openssl/tests/gh22186.phpt
+new file mode 100644
+index 00000000000..8f28e6c45b5
+--- /dev/null
++++ b/ext/openssl/tests/gh22186.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++GH-22186 (Heap buffer overflow in openssl_encrypt with AES-WRAP-PAD)
++--EXTENSIONS--
++openssl
++--SKIPIF--
++<?php
++/* openssl_get_cipher_methods() enumerates provider ciphers, but openssl_encrypt()
++ * resolves names via the legacy EVP_get_cipherbyname(), so on some builds the
++ * cipher is listed yet not usable. Probe the actual call path instead. */
++if (!@openssl_encrypt("test", "aes-128-wrap-pad", str_repeat("k", 16),
++        OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, str_repeat("\0", 4))) {
++    die('skip aes-128-wrap-pad not usable on this OpenSSL build');
++}
++?>
++--FILE--
++<?php
++$pass = str_repeat("k", 16);
++$iv = str_repeat("\0", 4);
++
++for ($i = 1; $i < 258; $i++) {
++    $data = str_repeat("a", $i);
++    $enc = openssl_encrypt($data, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv);
++    $dec = openssl_decrypt($enc, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv);
++    if ($dec !== $data) {
++        die("mismatch at $i\n");
++    }
++}
++
++echo "done\n";
++?>
++--EXPECT--
++done
+-- 
+2.54.0
+
diff --git a/php-cve-2026-17543.patch b/php-cve-2026-17543.patch
new file mode 100644
index 0000000..aa59c64
--- /dev/null
+++ b/php-cve-2026-17543.patch
@@ -0,0 +1,223 @@
+From eb0de306e0569f8b50065a42f13dd3e2b3729532 Mon Sep 17 00:00:00 2001
+From: Ilija Tovilo <ilija.tovilo at me.com>
+Date: Mon, 27 Jul 2026 16:49:38 +0200
+Subject: [PATCH 2/5] Fix SQL injection in ext-pgsql via E'...' backslash
+ breakout
+
+php_pgsql_add_quotes() quotes the string with E'...', but PQescapeStringConn()
+does not escape \ unless standard_conforming_strings is off.
+PQescapeStringConn() is meant to be used with '', so do that instead.
+
+Fixes GHSA-7qpv-r5mr-78m4
+
+(cherry picked from commit ab048bd83b578119cf81b456526d50498421d617)
+---
+ ext/pgsql/pgsql.c                            |  3 +-
+ ext/pgsql/tests/10pg_convert_9.phpt          | 18 +++++-
+ ext/pgsql/tests/10pg_convert_json_array.phpt |  4 +-
+ ext/pgsql/tests/12pg_insert_9.phpt           |  2 +-
+ ext/pgsql/tests/14pg_update_9.phpt           |  2 +-
+ ext/pgsql/tests/GHSA-7qpv-r5mr-78m4.phpt     | 58 ++++++++++++++++++++
+ ext/pgsql/tests/bug64609.phpt                |  2 +-
+ ext/pgsql/tests/bug68638.phpt                |  2 +-
+ 8 files changed, 81 insertions(+), 10 deletions(-)
+ create mode 100644 ext/pgsql/tests/GHSA-7qpv-r5mr-78m4.phpt
+
+diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
+index 01fb9dde3ba..de90b0b21d7 100644
+--- a/ext/pgsql/pgsql.c
++++ b/ext/pgsql/pgsql.c
+@@ -4563,7 +4563,7 @@ static int php_pgsql_convert_match(const zend_string *str, const char *regex , s
+  */
+ static zend_string *php_pgsql_add_quotes(zend_string *src)
+ {
+-	return zend_string_concat3("E'", strlen("E'"), ZSTR_VAL(src), ZSTR_LEN(src), "'", strlen("'"));
++	return zend_string_concat3("'", strlen("'"), ZSTR_VAL(src), ZSTR_LEN(src), "'", strlen("'"));
+ }
+ /* }}} */
+ 
+@@ -4841,7 +4841,6 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string *
+ 							zend_string *str;
+ 							/* PostgreSQL ignores \0 */
+ 							str = zend_string_alloc(Z_STRLEN_P(val) * 2, 0);
+-							/* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */
+ 							ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str),
+ 									Z_STRVAL_P(val), Z_STRLEN_P(val), &escape_err);
+ 							if (escape_err) {
+diff --git a/ext/pgsql/tests/10pg_convert_9.phpt b/ext/pgsql/tests/10pg_convert_9.phpt
+index f4bfaf5e395..fb36e5801c8 100644
+--- a/ext/pgsql/tests/10pg_convert_9.phpt
++++ b/ext/pgsql/tests/10pg_convert_9.phpt
+@@ -21,6 +21,8 @@ $converted = pg_convert($db, $table_name, $fields);
+ 
+ var_dump($converted);
+ 
++var_dump(pg_convert($db, $table_name, ['str' => "\\' OR 1=1"]));
++
+ /* Invalid values */
+ try {
+     $converted = pg_convert($db, $table_name, [5 => 'AAA']);
+@@ -48,18 +50,30 @@ try {
+ } catch (\TypeError $e) {
+     echo $e->getMessage(), \PHP_EOL;
+ }
++
++/* standard_conforming_strings = 1 */
++pg_query($db, "SET standard_conforming_strings = 1");
++var_dump(pg_convert($db, $table_name, ['str' => "\\' OR 1=1"]));
+ ?>
+ --EXPECT--
+ array(3) {
+   [""num""]=>
+   string(4) "1234"
+   [""str""]=>
+-  string(6) "E'AAA'"
++  string(5) "'AAA'"
+   [""bin""]=>
+-  string(12) "E'\\x424242'"
++  string(11) "'\\x424242'"
++}
++array(1) {
++  [""str""]=>
++  string(13) "'\\'' OR 1=1'"
+ }
+ Array of values must be an associative array with string keys
+ Array of values must be an associative array with string keys
+ Values must be of type string|int|float|bool|null, array given
+ Values must be of type string|int|float|bool|null, stdClass given
+ Values must be of type string|int|float|bool|null, PgSql\Connection given
++array(1) {
++  [""str""]=>
++  string(12) "'\'' OR 1=1'"
++}
+diff --git a/ext/pgsql/tests/10pg_convert_json_array.phpt b/ext/pgsql/tests/10pg_convert_json_array.phpt
+index 918765db06c..5353e04dac5 100644
+--- a/ext/pgsql/tests/10pg_convert_json_array.phpt
++++ b/ext/pgsql/tests/10pg_convert_json_array.phpt
+@@ -32,8 +32,8 @@ if (!pg_insert($db, $table_name_92, $fields)) {
+ --EXPECT--
+ array(2) {
+   [""textary""]=>
+-  string(51) "E'{"meeting", "lunch", "training", "presentation"}'"
++  string(50) "'{"meeting", "lunch", "training", "presentation"}'"
+   [""jsn""]=>
+-  string(22) "E'{"f1":1,"f2":"foo"}'"
++  string(21) "'{"f1":1,"f2":"foo"}'"
+ }
+ OK
+diff --git a/ext/pgsql/tests/12pg_insert_9.phpt b/ext/pgsql/tests/12pg_insert_9.phpt
+index 892494fe6f0..699426c89b2 100644
+--- a/ext/pgsql/tests/12pg_insert_9.phpt
++++ b/ext/pgsql/tests/12pg_insert_9.phpt
+@@ -54,7 +54,7 @@ try {
+ echo "Ok\n";
+ ?>
+ --EXPECTF--
+-INSERT INTO "php_pgsql_test" ("num","str","bin") VALUES (1234,E'AAA',E'\\x424242');
++INSERT INTO "php_pgsql_test" ("num","str","bin") VALUES (1234,'AAA','\\x424242');
+ INSERT INTO "php_pgsql_test" ("num","str","bin") VALUES ('1234','AAA','BBB');
+ object(PgSql\Result)#%d (0) {
+ }
+diff --git a/ext/pgsql/tests/14pg_update_9.phpt b/ext/pgsql/tests/14pg_update_9.phpt
+index d34f05216ec..64493075490 100644
+--- a/ext/pgsql/tests/14pg_update_9.phpt
++++ b/ext/pgsql/tests/14pg_update_9.phpt
+@@ -26,6 +26,6 @@ echo pg_update($db, $table_name, $fields, $ids, PGSQL_DML_STRING|PGSQL_DML_ESCAP
+ echo "Ok\n";
+ ?>
+ --EXPECT--
+-UPDATE "php_pgsql_test" SET "num"=1234,"str"=E'ABC',"bin"=E'\\x58595a' WHERE "num"=1234;
++UPDATE "php_pgsql_test" SET "num"=1234,"str"='ABC',"bin"='\\x58595a' WHERE "num"=1234;
+ UPDATE "php_pgsql_test" SET "num"='1234',"str"='ABC',"bin"='XYZ' WHERE "num"='1234';
+ Ok
+diff --git a/ext/pgsql/tests/GHSA-7qpv-r5mr-78m4.phpt b/ext/pgsql/tests/GHSA-7qpv-r5mr-78m4.phpt
+new file mode 100644
+index 00000000000..88b37a8432f
+--- /dev/null
++++ b/ext/pgsql/tests/GHSA-7qpv-r5mr-78m4.phpt
+@@ -0,0 +1,58 @@
++--TEST--
++GHSA-7qpv-r5mr-78m4: SQL injection via E'...' backslash breakout
++--CREDITS--
++expatch.llc
++--EXTENSIONS--
++pgsql
++--SKIPIF--
++<?php include("skipif.inc"); ?>
++--FILE--
++<?php
++include 'config.inc';
++
++$db = pg_connect($conn_str);
++
++pg_query($db, "SET standard_conforming_strings = 1");
++
++pg_query($db, "DROP TABLE IF EXISTS ghsa_7qpv_r5mr_78m4");
++pg_query($db, "CREATE TABLE ghsa_7qpv_r5mr_78m4 (id serial primary key, name text, admin boolean)");
++pg_query($db, "INSERT INTO ghsa_7qpv_r5mr_78m4 (name, admin) VALUES ('alice', false), ('bob', false)");
++
++$params = ['name' => "zzz' OR 1=1 --"];
++echo pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
++printf("returned: %d\n\n", count(pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params)));
++
++$params = ['name' => "zzz\\' OR 1=1 --"];
++echo pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
++printf("returned: %d\n\n", count(pg_select($db, 'ghsa_7qpv_r5mr_78m4', $params)));
++
++$params = ['name' => "john\\', true) --", 'admin' => 'false'];
++echo pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_STRING) . "\n";
++pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params);
++var_dump(pg_select($db, 'ghsa_7qpv_r5mr_78m4', ['id' => 3])[0]['admin']);
++echo "\n";
++
++$params = ['name' => "jake\\', true) --", 'admin' => 'f'];
++echo pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_ESCAPE|PGSQL_DML_STRING) . "\n";
++pg_insert($db, 'ghsa_7qpv_r5mr_78m4', $params, PGSQL_DML_EXEC|PGSQL_DML_ESCAPE);
++var_dump(pg_select($db, 'ghsa_7qpv_r5mr_78m4', ['id' => 4])[0]['admin']);
++
++?>
++--EXPECT--
++SELECT * FROM "ghsa_7qpv_r5mr_78m4" WHERE "name"='zzz'' OR 1=1 --';
++returned: 0
++
++SELECT * FROM "ghsa_7qpv_r5mr_78m4" WHERE "name"='zzz\'' OR 1=1 --';
++returned: 0
++
++INSERT INTO "ghsa_7qpv_r5mr_78m4" ("name","admin") VALUES ('john\'', true) --','f');
++string(1) "f"
++
++INSERT INTO "ghsa_7qpv_r5mr_78m4" ("name","admin") VALUES ('jake\'', true) --','f');
++string(1) "f"
++--CLEAN--
++<?php
++include('config.inc');
++$db = pg_connect($conn_str);
++pg_query($db, "DROP TABLE IF EXISTS ghsa_7qpv_r5mr_78m4");
++?>
+diff --git a/ext/pgsql/tests/bug64609.phpt b/ext/pgsql/tests/bug64609.phpt
+index ebf878dbeed..ba27091ecf3 100644
+--- a/ext/pgsql/tests/bug64609.phpt
++++ b/ext/pgsql/tests/bug64609.phpt
+@@ -28,5 +28,5 @@ var_dump($converted);
+ --EXPECT--
+ array(1) {
+   [""a""]=>
+-  string(5) "E'ok'"
++  string(4) "'ok'"
+ }
+diff --git a/ext/pgsql/tests/bug68638.phpt b/ext/pgsql/tests/bug68638.phpt
+index d95fa1e4412..2a1025cad8d 100644
+--- a/ext/pgsql/tests/bug68638.phpt
++++ b/ext/pgsql/tests/bug68638.phpt
+@@ -34,7 +34,7 @@ pg_query($conn, "DROP TABLE $table");
+ 
+ ?>
+ --EXPECT--
+-string(52) "UPDATE "test_68638" SET "value"=E'inf' WHERE "id"=1;"
++string(51) "UPDATE "test_68638" SET "value"='inf' WHERE "id"=1;"
+ array(2) {
+   ["id"]=>
+   string(1) "1"
+-- 
+2.55.0
+
diff --git a/php-cve-2026-6722.patch b/php-cve-2026-6722.patch
new file mode 100644
index 0000000..3365479
--- /dev/null
+++ b/php-cve-2026-6722.patch
@@ -0,0 +1,107 @@
+From 15064460d6682766f91c1a841d27cdfbc38907e8 Mon Sep 17 00:00:00 2001
+From: Ilija Tovilo <ilija.tovilo at me.com>
+Date: Sun, 3 May 2026 19:56:53 +0200
+Subject: [PATCH 01/10] GHSA-85c2-q967-79q5: [soap] Fix stale
+ SOAP_GLOBAL(ref_map) pointer with Apache Map
+
+Fixes GHSA-85c2-q967-79q5
+Fixes CVE-2026-6722
+
+(cherry picked from commit aee3b3ac9b816b0def1c462695b483b49a83148e)
+---
+ ext/soap/php_encoding.c                 |  3 +-
+ ext/soap/tests/GHSA-85c2-q967-79q5.phpt | 61 +++++++++++++++++++++++++
+ 2 files changed, 63 insertions(+), 1 deletion(-)
+ create mode 100644 ext/soap/tests/GHSA-85c2-q967-79q5.phpt
+
+diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
+index 4d389a8c585..bf394f7ea92 100644
+--- a/ext/soap/php_encoding.c
++++ b/ext/soap/php_encoding.c
+@@ -365,6 +365,7 @@ static bool soap_check_xml_ref(zval *data, xmlNodePtr node)
+ static void soap_add_xml_ref(zval *data, xmlNodePtr node)
+ {
+ 	if (SOAP_GLOBAL(ref_map)) {
++		Z_TRY_ADDREF_P(data);
+ 		zend_hash_index_update(SOAP_GLOBAL(ref_map), (zend_ulong)node, data);
+ 	}
+ }
+@@ -3437,7 +3438,7 @@ void encode_reset_ns()
+ 	} else {
+ 		SOAP_GLOBAL(ref_map) = emalloc(sizeof(HashTable));
+ 	}
+-	zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, NULL, 0);
++	zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+ 
+ void encode_finish()
+diff --git a/ext/soap/tests/GHSA-85c2-q967-79q5.phpt b/ext/soap/tests/GHSA-85c2-q967-79q5.phpt
+new file mode 100644
+index 00000000000..8bcac26ad18
+--- /dev/null
++++ b/ext/soap/tests/GHSA-85c2-q967-79q5.phpt
+@@ -0,0 +1,61 @@
++--TEST--
++GHSA-85c2-q967-79q5: Stale SOAP_GLOBAL(ref_map) pointer with Apache Map
++--CREDITS--
++brettgervasoni
++--EXTENSIONS--
++soap
++--FILE--
++<?php
++
++class Handler {
++    public function test(...$args) {
++        $GLOBALS['result'] = $args;
++    }
++}
++
++$envelope = <<<'XML'
++<?xml version="1.0" encoding="UTF-8"?>
++<soapenv:Envelope
++    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
++    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
++    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
++
++    <soapenv:Body>
++        <test>
++            <map xsi:type="apache:Map" xmlns:apache="http://xml.apache.org/xml-soap">
++                <item>
++                    <key>foo</key>
++                    <value id="stale"><object>bar</object></value>
++                </item>
++                <item>
++                    <key>foo</key>
++                    <value>baz</value>
++                </item>
++            </map>
++            <stale href="#stale"/>
++        </test>
++    </soapenv:Body>
++</soapenv:Envelope>
++XML;
++
++$s = new SoapServer(null, ['uri' => 'urn:a']);
++$s->setClass(Handler::class);
++$s->handle($envelope);
++var_dump($result);
++
++?>
++--EXPECTF--
++<?xml version="1.0" encoding="UTF-8"?>
++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:testResponse><return xsi:nil="true"/></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
++array(2) {
++  [0]=>
++  array(1) {
++    ["foo"]=>
++    string(3) "baz"
++  }
++  [1]=>
++  object(stdClass)#%d (1) {
++    ["object"]=>
++    string(3) "bar"
++  }
++}
+-- 
+2.54.0
+
diff --git a/php-cve-2026-6735.patch b/php-cve-2026-6735.patch
new file mode 100644
index 0000000..9f287dd
--- /dev/null
+++ b/php-cve-2026-6735.patch
@@ -0,0 +1,144 @@
+From cc2960e782eb5cc262d7bd572a7d18979a811954 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka at php.net>
+Date: Sun, 3 May 2026 20:01:41 +0200
+Subject: [PATCH 04/10] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint
+
+Fixes GHSA-7qg2-v9fj-4mwv
+Fixes CVE-2026-6735
+
+(cherry picked from commit 99a5ad7441de9914246c7863adb6997396008b9d)
+---
+ sapi/fpm/fpm/fpm_status.c                     | 34 +++++++++++--
+ .../tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt | 48 +++++++++++++++++++
+ 2 files changed, 78 insertions(+), 4 deletions(-)
+ create mode 100644 sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
+
+diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
+index f698753cf4c..81292aa3bf8 100644
+--- a/sapi/fpm/fpm/fpm_status.c
++++ b/sapi/fpm/fpm/fpm_status.c
+@@ -525,8 +525,8 @@ int fpm_status_handle_request(void) /* {{{ */
+ 		if (full_syntax) {
+ 			unsigned int i;
+ 			int first;
+-			zend_string *tmp_query_string;
+-			char *query_string;
++			zend_string *tmp_query_string, *tmp_request_uri_string;
++			char *query_string, *request_uri_string;
+ 			struct timeval duration, now;
+ 			float cpu;
+ 
+@@ -551,13 +551,36 @@ int fpm_status_handle_request(void) /* {{{ */
+ 					}
+ 				}
+ 
++				request_uri_string = NULL;
++				tmp_request_uri_string = NULL;
++				if (proc->request_uri[0] != '\0') {
++					if (encode_html) {
++						tmp_request_uri_string = php_escape_html_entities_ex(
++								(const unsigned char *) proc->request_uri,
++								strlen(proc->request_uri), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
++								NULL, /* double_encode */ 1, /* quiet */ 0);
++						request_uri_string = ZSTR_VAL(tmp_request_uri_string);
++					} else if (encode_json) {
++						tmp_request_uri_string = php_json_encode_string(proc->request_uri,
++								strlen(proc->request_uri), PHP_JSON_INVALID_UTF8_IGNORE);
++						request_uri_string = ZSTR_VAL(tmp_request_uri_string);
++						/* remove quotes around the string */
++						if (ZSTR_LEN(tmp_request_uri_string) >= 2) {
++							request_uri_string[ZSTR_LEN(tmp_request_uri_string) - 1] = '\0';
++							++request_uri_string;
++						}
++					} else {
++						request_uri_string = proc->request_uri;
++					}
++				}
++
+ 				query_string = NULL;
+ 				tmp_query_string = NULL;
+ 				if (proc->query_string[0] != '\0') {
+ 					if (encode_html) {
+ 						tmp_query_string = php_escape_html_entities_ex(
+ 								(const unsigned char *) proc->query_string,
+-								strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT,
++								strlen(proc->query_string), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT,
+ 								NULL, /* double_encode */ 1, /* quiet */ 0);
+ 					} else if (encode_json) {
+ 						tmp_query_string = php_json_encode_string(proc->query_string,
+@@ -596,7 +619,7 @@ int fpm_status_handle_request(void) /* {{{ */
+ 					proc->requests,
+ 					duration.tv_sec * 1000000UL + duration.tv_usec,
+ 					proc->request_method[0] != '\0' ? proc->request_method : "-",
+-					proc->request_uri[0] != '\0' ? proc->request_uri : "-",
++					request_uri_string ? request_uri_string : "-",
+ 					query_string ? "?" : "",
+ 					query_string ? query_string : "",
+ 					proc->content_length,
+@@ -607,6 +630,9 @@ int fpm_status_handle_request(void) /* {{{ */
+ 				PUTS(buffer);
+ 				efree(buffer);
+ 
++				if (tmp_request_uri_string) {
++					zend_string_free(tmp_request_uri_string);
++				}
+ 				if (tmp_query_string) {
+ 					zend_string_free(tmp_query_string);
+ 				}
+diff --git a/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
+new file mode 100644
+index 00000000000..475bc130a42
+--- /dev/null
++++ b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt
+@@ -0,0 +1,48 @@
++--TEST--
++FPM: GHSA-7qg2-v9fj-4mwv - status xss
++--SKIPIF--
++<?php include "skipif.inc"; ?>
++--FILE--
++<?php
++
++require_once "tester.inc";
++
++$cfg = <<<EOT
++[global]
++error_log = {{FILE:LOG}}
++[unconfined]
++listen = {{ADDR}}
++pm = static
++pm.max_children = 2
++pm.status_path = /status
++catch_workers_output = yes
++EOT;
++
++$code = <<<EOT
++<?php
++usleep(200000);
++EOT;
++
++$tester = new FPM\Tester($cfg, $code);
++$tester->start();
++$tester->expectLogStartNotices();
++$responses = $tester
++        ->multiRequest([
++                ['uri' => '/<script>alert(1)</script>', 'query' => '<script>alert(2)</script>'],
++                ['uri' => '/status', 'query' => 'full&html', 'delay' => 100000],
++        ]);
++var_dump(strpos($responses[1]->getBody(), '<script>'));
++$tester->terminate();
++$tester->expectLogTerminatingNotices();
++$tester->close();
++
++?>
++Done
++--EXPECT--
++bool(false)
++Done
++--CLEAN--
++<?php
++require_once "tester.inc";
++FPM\Tester::clean();
++?>
+-- 
+2.54.0
+
diff --git a/php-cve-2026-7258.patch b/php-cve-2026-7258.patch
new file mode 100644
index 0000000..b9c8180
--- /dev/null
+++ b/php-cve-2026-7258.patch
@@ -0,0 +1,1719 @@
+From 07e5a9263314fd9a2a4479661353704e00dd8d0c Mon Sep 17 00:00:00 2001
+From: Ilija Tovilo <ilija.tovilo at me.com>
+Date: Sun, 3 May 2026 20:03:18 +0200
+Subject: [PATCH 08/10] GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to
+ ctype.h functions
+
+Fixes GHSA-m8rr-4c36-8gq4
+Fixes CVE-2026-7258
+
+(cherry picked from commit a38418777f65780d9d622197677e90567690fc07)
+---
+ Zend/zend_compile.c                 |  2 +-
+ Zend/zend_operators.c               |  8 ++++----
+ Zend/zend_virtual_cwd.c             | 10 +++++-----
+ Zend/zend_virtual_cwd.h             |  2 +-
+ ext/com_dotnet/com_extension.c      |  4 ++--
+ ext/date/lib/parse_date.c           | 10 +++++-----
+ ext/date/lib/parse_date.re          | 10 +++++-----
+ ext/date/lib/parse_iso_intervals.c  |  4 ++--
+ ext/date/lib/parse_iso_intervals.re |  4 ++--
+ ext/date/lib/timelib.c              |  2 +-
+ ext/filter/logical_filters.c        | 10 +++++-----
+ ext/ftp/ftp.c                       | 10 +++++-----
+ ext/gd/libgd/gd_xbm.c               |  2 +-
+ ext/imap/php_imap.c                 |  2 +-
+ ext/intl/locale/locale_methods.c    |  2 +-
+ ext/mbstring/mbstring.c             |  4 ++--
+ ext/mbstring/php_mbregex.c          |  2 +-
+ ext/pcre/php_pcre.c                 |  4 ++--
+ ext/pdo/pdo.c                       |  2 +-
+ ext/pdo/pdo_sql_parser.re           |  2 +-
+ ext/pdo/pdo_stmt.c                  |  2 +-
+ ext/standard/dl.c                   |  2 +-
+ ext/standard/exec.c                 |  2 +-
+ ext/standard/file.c                 |  2 +-
+ ext/standard/filters.c              |  2 +-
+ ext/standard/formatted_print.c      |  8 ++++----
+ ext/standard/ftp_fopen_wrapper.c    | 12 ++++++------
+ ext/standard/html.c                 |  4 ++--
+ ext/standard/math.c                 |  6 +++---
+ ext/standard/metaphone.c            | 18 ++++++++---------
+ ext/standard/quot_print.c           |  8 ++++----
+ ext/standard/scanf.c                | 10 +++++-----
+ ext/standard/soundex.c              |  2 +-
+ ext/standard/string.c               | 14 +++++++-------
+ ext/standard/strnatcmp.c            | 30 ++++++++++++++---------------
+ ext/standard/type.c                 |  2 +-
+ ext/standard/url.c                  | 20 +++++++++----------
+ ext/standard/url_scanner_ex.re      |  6 +++---
+ ext/standard/versioning.c           | 16 +++++++--------
+ main/SAPI.c                         |  6 +++---
+ main/fopen_wrappers.c               |  6 +++---
+ main/php_ini.c                      |  2 +-
+ main/php_variables.c                |  4 ++--
+ main/rfc1867.c                      | 12 ++++++------
+ main/snprintf.c                     | 14 +++++++-------
+ main/spprintf.c                     | 14 +++++++-------
+ main/streams/streams.c              |  4 ++--
+ main/streams/transports.c           |  2 +-
+ sapi/cli/php_cli_server.c           |  2 +-
+ sapi/fpm/fpm/fpm_conf.c             |  4 ++--
+ sapi/litespeed/lsapi_main.c         |  4 ++--
+ sapi/litespeed/lsapilib.c           |  6 +++---
+ sapi/phpdbg/phpdbg_cmd.c            |  4 ++--
+ sapi/phpdbg/phpdbg_prompt.c         |  2 +-
+ sapi/phpdbg/phpdbg_utils.c          | 10 +++++-----
+ win32/sendmail.c                    |  6 +++---
+ 56 files changed, 182 insertions(+), 182 deletions(-)
+
+diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
+index c0cd3c97341..856e81ace7f 100644
+--- a/Zend/zend_compile.c
++++ b/Zend/zend_compile.c
+@@ -2006,7 +2006,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
+ 	/* Note that on Win32 CWD is per drive (heritage from CP/M).
+ 	 * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
+ 	 */
+-	if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
++	if ((2 <= len) && isalpha((unsigned char)path[0]) && (':' == path[1])) {
+ 		/* Skip over the drive spec (if any) so as not to change */
+ 		path += 2;
+ 		len_adjust += 2;
+diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
+index ef5c50c4336..1c4abc9ede5 100644
+--- a/Zend/zend_operators.c
++++ b/Zend/zend_operators.c
+@@ -2883,8 +2883,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1,
+ 
+ 	len = MIN(len1, len2);
+ 	while (len--) {
+-		c1 = zend_tolower((int)*(unsigned char *)s1++);
+-		c2 = zend_tolower((int)*(unsigned char *)s2++);
++		c1 = zend_tolower((unsigned char)*(s1++));
++		c2 = zend_tolower((unsigned char)*(s2++));
+ 		if (c1 != c2) {
+ 			return c1 - c2;
+ 		}
+@@ -2904,8 +2904,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1
+ 	}
+ 	len = MIN(length, MIN(len1, len2));
+ 	while (len--) {
+-		c1 = zend_tolower((int)*(unsigned char *)s1++);
+-		c2 = zend_tolower((int)*(unsigned char *)s2++);
++		c1 = zend_tolower((unsigned char)*(s1++));
++		c2 = zend_tolower((unsigned char)*(s2++));
+ 		if (c1 != c2) {
+ 			return c1 - c2;
+ 		}
+diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c
+index d8a9046d04d..ca5f79d9933 100644
+--- a/Zend/zend_virtual_cwd.c
++++ b/Zend/zend_virtual_cwd.c
+@@ -195,7 +195,7 @@ void virtual_cwd_main_cwd_init(uint8_t reinit) /* {{{ */
+ 	main_cwd_state.cwd_length = strlen(cwd);
+ #ifdef ZEND_WIN32
+ 	if (main_cwd_state.cwd_length >= 2 && cwd[1] == ':') {
+-		cwd[0] = toupper(cwd[0]);
++		cwd[0] = toupper((unsigned char)cwd[0]);
+ 	}
+ #endif
+ 	main_cwd_state.cwd = strdup(cwd);
+@@ -273,7 +273,7 @@ CWD_API char *virtual_getcwd_ex(size_t *length) /* {{{ */
+ 		*length = state->cwd_length+1;
+ 		retval = (char *) emalloc(*length+1);
+ 		memcpy(retval, state->cwd, *length);
+-		retval[0] = toupper(retval[0]);
++		retval[0] = toupper((unsigned char)retval[0]);
+ 		retval[*length-1] = DEFAULT_SLASH;
+ 		retval[*length] = '\0';
+ 		return retval;
+@@ -1114,7 +1114,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
+ 			if (resolved_path[start] == 0) {
+ 				goto verify;
+ 			}
+-			resolved_path[start] = toupper(resolved_path[start]);
++			resolved_path[start] = toupper((unsigned char)resolved_path[start]);
+ 			start++;
+ 		}
+ 		resolved_path[start++] = DEFAULT_SLASH;
+@@ -1122,13 +1122,13 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
+ 			if (resolved_path[start] == 0) {
+ 				goto verify;
+ 			}
+-			resolved_path[start] = toupper(resolved_path[start]);
++			resolved_path[start] = toupper((unsigned char)resolved_path[start]);
+ 			start++;
+ 		}
+ 		resolved_path[start++] = DEFAULT_SLASH;
+ 	} else if (IS_ABSOLUTE_PATH(resolved_path, path_length)) {
+ 		/* skip DRIVE name */
+-		resolved_path[0] = toupper(resolved_path[0]);
++		resolved_path[0] = toupper((unsigned char)resolved_path[0]);
+ 		resolved_path[2] = DEFAULT_SLASH;
+ 		start = 3;
+ 	}
+diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h
+index 728e3ba69d8..d15c8e28d5d 100644
+--- a/Zend/zend_virtual_cwd.h
++++ b/Zend/zend_virtual_cwd.h
+@@ -82,7 +82,7 @@ typedef unsigned short mode_t;
+ #define IS_UNC_PATH(path, len) \
+ 	(len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1]))
+ #define IS_ABSOLUTE_PATH(path, len) \
+-	(len >= 2 && (/* is local */isalpha(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1])))
++	(len >= 2 && (/* is local */isalpha((unsigned char)(path)[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1])))
+ 
+ #else
+ #ifdef HAVE_DIRENT_H
+diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c
+index 55b3c282aee..380ca0791e8 100644
+--- a/ext/com_dotnet/com_extension.c
++++ b/ext/com_dotnet/com_extension.c
+@@ -104,11 +104,11 @@ static PHP_INI_MH(OnTypeLibFileUpdate)
+ 		}
+ 
+ 		/* Remove leading/training white spaces on search_string */
+-		while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */
++		while (isspace((unsigned char)*typelib_name)) {/* Ends on '\0' in worst case */
+ 			typelib_name ++;
+ 		}
+ 		ptr = typelib_name + strlen(typelib_name) - 1;
+-		while ((ptr != typelib_name) && isspace(*ptr)) {
++		while ((ptr != typelib_name) && isspace((unsigned char)*ptr)) {
+ 			*ptr = '\0';
+ 			ptr--;
+ 		}
+diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c
+index 78feb742081..9c5c9d602a1 100644
+--- a/ext/date/lib/parse_date.c
++++ b/ext/date/lib/parse_date.c
+@@ -509,7 +509,7 @@ static timelib_sll timelib_get_nr(const char **ptr, int max_length)
+ 
+ static void timelib_skip_day_suffix(const char **ptr)
+ {
+-	if (isspace(**ptr)) {
++	if (isspace((unsigned char)**ptr)) {
+ 		return;
+ 	}
+ 	if (!timelib_strncasecmp(*ptr, "nd", 2) || !timelib_strncasecmp(*ptr, "rd", 2) ||!timelib_strncasecmp(*ptr, "st", 2) || !timelib_strncasecmp(*ptr, "th", 2)) {
+@@ -792,7 +792,7 @@ static timelib_long timelib_parse_tz_cor(const char **ptr, int *tz_not_found)
+ 
+ 	*tz_not_found = 1;
+ 
+-	while (isdigit(**ptr) || **ptr == ':') {
++	while (isdigit((unsigned char)**ptr) || **ptr == ':') {
+ 		++*ptr;
+ 	}
+ 	end = *ptr;
+@@ -857,7 +857,7 @@ static timelib_long timelib_parse_tz_minutes(const char **ptr, timelib_time *t)
+ 	}
+ 
+ 	++*ptr;
+-	while (isdigit(**ptr)) {
++	while (isdigit((unsigned char)**ptr)) {
+ 		++*ptr;
+ 	}
+ 
+@@ -25936,10 +25936,10 @@ timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_contain
+ 	in.errors->error_messages = NULL;
+ 
+ 	if (len > 0) {
+-		while (isspace(*s) && s < e) {
++		while (isspace((unsigned char)*s) && s < e) {
+ 			s++;
+ 		}
+-		while (isspace(*e) && e > s) {
++		while (isspace((unsigned char)*e) && e > s) {
+ 			e--;
+ 		}
+ 	}
+diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re
+index f0db34d302b..a2d12361df9 100644
+--- a/ext/date/lib/parse_date.re
++++ b/ext/date/lib/parse_date.re
+@@ -507,7 +507,7 @@ static timelib_sll timelib_get_nr(const char **ptr, int max_length)
+ 
+ static void timelib_skip_day_suffix(const char **ptr)
+ {
+-	if (isspace(**ptr)) {
++	if (isspace((unsigned char)**ptr)) {
+ 		return;
+ 	}
+ 	if (!timelib_strncasecmp(*ptr, "nd", 2) || !timelib_strncasecmp(*ptr, "rd", 2) ||!timelib_strncasecmp(*ptr, "st", 2) || !timelib_strncasecmp(*ptr, "th", 2)) {
+@@ -790,7 +790,7 @@ static timelib_long timelib_parse_tz_cor(const char **ptr, int *tz_not_found)
+ 
+ 	*tz_not_found = 1;
+ 
+-	while (isdigit(**ptr) || **ptr == ':') {
++	while (isdigit((unsigned char)**ptr) || **ptr == ':') {
+ 		++*ptr;
+ 	}
+ 	end = *ptr;
+@@ -855,7 +855,7 @@ static timelib_long timelib_parse_tz_minutes(const char **ptr, timelib_time *t)
+ 	}
+ 
+ 	++*ptr;
+-	while (isdigit(**ptr)) {
++	while (isdigit((unsigned char)**ptr)) {
+ 		++*ptr;
+ 	}
+ 
+@@ -1938,10 +1938,10 @@ timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_contain
+ 	in.errors->error_messages = NULL;
+ 
+ 	if (len > 0) {
+-		while (isspace(*s) && s < e) {
++		while (isspace((unsigned char)*s) && s < e) {
+ 			s++;
+ 		}
+-		while (isspace(*e) && e > s) {
++		while (isspace((unsigned char)*e) && e > s) {
+ 			e--;
+ 		}
+ 	}
+diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c
+index a467da3471f..113343f5615 100644
+--- a/ext/date/lib/parse_iso_intervals.c
++++ b/ext/date/lib/parse_iso_intervals.c
+@@ -948,10 +948,10 @@ void timelib_strtointerval(const char *s, size_t len,
+ 	in.errors->error_messages = NULL;
+ 
+ 	if (len > 0) {
+-		while (isspace(*s) && s < e) {
++		while (isspace((unsigned char)*s) && s < e) {
+ 			s++;
+ 		}
+-		while (isspace(*e) && e > s) {
++		while (isspace((unsigned char)*e) && e > s) {
+ 			e--;
+ 		}
+ 	}
+diff --git a/ext/date/lib/parse_iso_intervals.re b/ext/date/lib/parse_iso_intervals.re
+index 2a394156f98..00942007751 100644
+--- a/ext/date/lib/parse_iso_intervals.re
++++ b/ext/date/lib/parse_iso_intervals.re
+@@ -343,10 +343,10 @@ void timelib_strtointerval(const char *s, size_t len,
+ 	in.errors->error_messages = NULL;
+ 
+ 	if (len > 0) {
+-		while (isspace(*s) && s < e) {
++		while (isspace((unsigned char)*s) && s < e) {
+ 			s++;
+ 		}
+-		while (isspace(*e) && e > s) {
++		while (isspace((unsigned char)*e) && e > s) {
+ 			e--;
+ 		}
+ 	}
+diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c
+index d42c69bbd6f..9949225df7e 100644
+--- a/ext/date/lib/timelib.c
++++ b/ext/date/lib/timelib.c
+@@ -126,7 +126,7 @@ void timelib_time_tz_abbr_update(timelib_time* tm, const char* tz_abbr)
+ 	TIMELIB_TIME_FREE(tm->tz_abbr);
+ 	tm->tz_abbr = timelib_strdup(tz_abbr);
+ 	for (i = 0; i < tz_abbr_len; i++) {
+-		tm->tz_abbr[i] = toupper(tz_abbr[i]);
++		tm->tz_abbr[i] = toupper((unsigned char)tz_abbr[i]);
+ 	}
+ }
+ 
+diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
+index 3db0ef40905..472e2768651 100644
+--- a/ext/filter/logical_filters.c
++++ b/ext/filter/logical_filters.c
+@@ -528,21 +528,21 @@ static int _php_filter_validate_domain(char * domain, size_t len, zend_long flag
+ 	}
+ 
+ 	/* First char must be alphanumeric */
+-	if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) {
++	if(*s == '.' || (hostname && !isalnum((unsigned char)*s))) {
+ 		return 0;
+ 	}
+ 
+ 	while (s < e) {
+ 		if (*s == '.') {
+ 			/* The first and the last character of a label must be alphanumeric */
+-			if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) {
++			if (*(s + 1) == '.' || (hostname && (!isalnum((unsigned char)s[-1]) || !isalnum((unsigned char)s[1])))) {
+ 				return 0;
+ 			}
+ 
+ 			/* Reset label length counter */
+ 			i = 1;
+ 		} else {
+-			if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) {
++			if (i > 63 || (hostname && *s != '-' && !isalnum((unsigned char)*s))) {
+ 				return 0;
+ 			}
+ 
+@@ -569,9 +569,9 @@ static int is_userinfo_valid(zend_string *str)
+ 	const char *valid = "-._~!$&'()*+,;=:";
+ 	const char *p = ZSTR_VAL(str);
+ 	while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) {
+-		if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
++		if (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || strchr(valid, *p)) {
+ 			p++;
+-		} else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
++		} else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit((unsigned char)p[1]) && isxdigit((unsigned char)p[2])) {
+ 			p += 3;
+ 		} else {
+ 			return 0;
+diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
+index 9253edc5589..9da59eabfb2 100644
+--- a/ext/ftp/ftp.c
++++ b/ext/ftp/ftp.c
+@@ -499,7 +499,7 @@ ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value
+ 	array_init(return_value);
+ 	while (ftp_readline(ftp)) {
+ 		add_next_index_string(return_value, ftp->inbuf);
+-		if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
++		if (isdigit((unsigned char)ftp->inbuf[0]) && isdigit((unsigned char)ftp->inbuf[1]) && isdigit((unsigned char)ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
+ 			return;
+ 		}
+ 	}
+@@ -841,7 +841,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
+ 		return 0;
+ 	}
+ 	/* parse out the IP and port */
+-	for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
++	for (ptr = ftp->inbuf; *ptr && !isdigit((unsigned char)*ptr); ptr++);
+ 	n = sscanf(ptr, "%lu,%lu,%lu,%lu,%lu,%lu", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]);
+ 	if (n != 6) {
+ 		return 0;
+@@ -1144,7 +1144,7 @@ ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len)
+ 		return -1;
+ 	}
+ 	/* parse out the timestamp */
+-	for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
++	for (ptr = ftp->inbuf; *ptr && !isdigit((unsigned char)*ptr); ptr++);
+ 	n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ 	if (n != 6) {
+ 		return -1;
+@@ -1342,13 +1342,13 @@ ftp_getresp(ftpbuf_t *ftp)
+ 		}
+ 
+ 		/* Break out when the end-tag is found */
+-		if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
++		if (isdigit((unsigned char)ftp->inbuf[0]) && isdigit((unsigned char)ftp->inbuf[1]) && isdigit((unsigned char)ftp->inbuf[2]) && ftp->inbuf[3] == ' ') {
+ 			break;
+ 		}
+ 	}
+ 
+ 	/* translate the tag */
+-	if (!isdigit(ftp->inbuf[0]) || !isdigit(ftp->inbuf[1]) || !isdigit(ftp->inbuf[2])) {
++	if (!isdigit((unsigned char)ftp->inbuf[0]) || !isdigit((unsigned char)ftp->inbuf[1]) || !isdigit((unsigned char)ftp->inbuf[2])) {
+ 		return 0;
+ 	}
+ 
+diff --git a/ext/gd/libgd/gd_xbm.c b/ext/gd/libgd/gd_xbm.c
+index 3c655a2998c..8efb34fbb0d 100644
+--- a/ext/gd/libgd/gd_xbm.c
++++ b/ext/gd/libgd/gd_xbm.c
+@@ -191,7 +191,7 @@ void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
+ 	} else {
+ 		for (i=0; i<l; i++) {
+ 			/* only in C-locale isalnum() would work */
+-			if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
++			if (!isupper((unsigned char)name[i]) && !islower((unsigned char)name[i]) && !isdigit((unsigned char)name[i])) {
+ 				name[i] = '_';
+ 			}
+ 		}
+diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
+index 5c45e213aa5..74fa59d1c5d 100644
+--- a/ext/imap/php_imap.c
++++ b/ext/imap/php_imap.c
+@@ -2316,7 +2316,7 @@ PHP_FUNCTION(imap_utf8)
+ #define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f)
+ 
+ /* validate a modified-base64 character */
+-#define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',')
++#define B64CHAR(c) (isalnum((unsigned char)(c)) || (c) == '+' || (c) == ',')
+ 
+ /* map the low 64 bits of `n' to the modified-base64 characters */
+ #define B64(n)	("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c
+index 159b3ea0a19..adca3ed3e32 100644
+--- a/ext/intl/locale/locale_methods.c
++++ b/ext/intl/locale/locale_methods.c
+@@ -1135,7 +1135,7 @@ static int strToMatch(const char* str ,char *retstr)
+ 			if( *str == '-' ){
+ 				*retstr =  '_';
+ 			} else {
+-				*retstr = tolower(*str);
++				*retstr = tolower((unsigned char)*str);
+ 			}
+ 				str++;
+ 				retstr++;
+diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
+index 238d74e4838..265356a21ce 100644
+--- a/ext/mbstring/mbstring.c
++++ b/ext/mbstring/mbstring.c
+@@ -626,7 +626,7 @@ static char *php_mb_rfc1867_getword(const zend_encoding *encoding, char **line,
+ 
+ static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *str) /* {{{ */
+ {
+-	while (*str && isspace(*(unsigned char *)str)) {
++	while (*str && isspace((unsigned char)*str)) {
+ 		++str;
+ 	}
+ 
+@@ -642,7 +642,7 @@ static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *st
+ 	} else {
+ 		char *strend = str;
+ 
+-		while (*strend && !isspace(*(unsigned char *)strend)) {
++		while (*strend && !isspace((unsigned char)*strend)) {
+ 			++strend;
+ 		}
+ 		return php_mb_rfc1867_substring_conf(encoding, str, strend - str, 0);
+diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
+index 0734011f9fb..5342de2b4ca 100644
+--- a/ext/mbstring/php_mbregex.c
++++ b/ext/mbstring/php_mbregex.c
+@@ -784,7 +784,7 @@ static inline void mb_regex_substitute(
+ 						continue;
+ 					}
+ 					if (name_end[0] == delim) break;
+-					if (maybe_num && !isdigit(name_end[0])) maybe_num = 0;
++					if (maybe_num && !isdigit((unsigned char)name_end[0])) maybe_num = 0;
+ 					name_end++;
+ 				}
+ 				p = name_end + 1;
+diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
+index 6249a807970..65891091256 100644
+--- a/ext/pcre/php_pcre.c
++++ b/ext/pcre/php_pcre.c
+@@ -648,7 +648,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in
+ 
+ 	/* Parse through the leading whitespace, and display a warning if we
+ 	   get to the end without encountering a delimiter. */
+-	while (isspace((int)*(unsigned char *)p)) p++;
++	while (isspace((unsigned char)*p)) p++;
+ 	if (*p == 0) {
+ 		if (key != regex) {
+ 			zend_string_release_ex(key, 0);
+@@ -662,7 +662,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in
+ 	/* Get the delimiter and display a warning if it is alphanumeric
+ 	   or a backslash. */
+ 	delimiter = *p++;
+-	if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') {
++	if (isalnum((unsigned char)delimiter) || delimiter == '\\') {
+ 		if (key != regex) {
+ 			zend_string_release_ex(key, 0);
+ 		}
+diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c
+index b18efe46284..03925abbc3b 100644
+--- a/ext/pdo/pdo.c
++++ b/ext/pdo/pdo.c
+@@ -229,7 +229,7 @@ PDO_API int php_pdo_parse_data_source(const char *data_source, zend_ulong data_s
+ 			}
+ 		}
+ 
+-		while (i < data_source_len && isspace(data_source[i])) {
++		while (i < data_source_len && isspace((unsigned char)data_source[i])) {
+ 			i++;
+ 		}
+ 
+diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re
+index 7f4721d12a6..7d282352396 100644
+--- a/ext/pdo/pdo_sql_parser.re
++++ b/ext/pdo/pdo_sql_parser.re
+@@ -105,7 +105,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string
+ 
+ 			if (t == PDO_PARSER_BIND) {
+ 				ptrdiff_t len = s.cur - s.tok;
+-				if ((ZSTR_VAL(inquery) < (s.cur - len)) && isalnum(*(s.cur - len - 1))) {
++				if ((ZSTR_VAL(inquery) < (s.cur - len)) && isalnum((unsigned char)s.cur[-len - 1])) {
+ 					continue;
+ 				}
+ 				query_type |= PDO_PLACEHOLDER_NAMED;
+diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
+index c3c466fbdd2..ea2046a134b 100644
+--- a/ext/pdo/pdo_stmt.c
++++ b/ext/pdo/pdo_stmt.c
+@@ -148,7 +148,7 @@ bool pdo_stmt_describe_columns(pdo_stmt_t *stmt) /* {{{ */
+ 					stmt->columns[col].name = zend_string_separate(orig_name, 0);
+ 					char *s = ZSTR_VAL(stmt->columns[col].name);
+ 					while (*s != '\0') {
+-						*s = toupper(*s);
++						*s = toupper((unsigned char)*s);
+ 						s++;
+ 					}
+ 					break;
+diff --git a/ext/standard/dl.c b/ext/standard/dl.c
+index 0df3848852f..babab64864c 100644
+--- a/ext/standard/dl.c
++++ b/ext/standard/dl.c
+@@ -93,7 +93,7 @@ PHPAPI void *php_load_shlib(const char *path, char **errp)
+ 			size_t i = strlen(err);
+ 			(*errp)=estrdup(err);
+ 			php_win32_error_msg_free(err);
+-			while (i > 0 && isspace((*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; }
++			while (i > 0 && isspace((unsigned char)(*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; }
+ 		} else {
+ 			(*errp) = estrdup("<No message>");
+ 		}
+diff --git a/ext/standard/exec.c b/ext/standard/exec.c
+index 1831b8eaa54..156eaa2cd3d 100644
+--- a/ext/standard/exec.c
++++ b/ext/standard/exec.c
+@@ -83,7 +83,7 @@ PHP_MINIT_FUNCTION(exec)
+ 
+ static size_t strip_trailing_whitespace(char *buf, size_t bufl) {
+ 	size_t l = bufl;
+-	while (l-- > 0 && isspace(((unsigned char *)buf)[l]));
++	while (l-- > 0 && isspace((unsigned char)buf[l]));
+ 	if (l != (bufl - 1)) {
+ 		bufl = l + 1;
+ 		buf[bufl] = '\0';
+diff --git a/ext/standard/file.c b/ext/standard/file.c
+index 8bab36096b1..bf20702e976 100644
+--- a/ext/standard/file.c
++++ b/ext/standard/file.c
+@@ -2086,7 +2086,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, int
+ 		inc_len = (bptr < limit ? (*bptr == '\0' ? 1 : php_mblen(bptr, limit - bptr)): 0);
+ 		if (inc_len == 1) {
+ 			char *tmp = bptr;
+-			while ((*tmp != delimiter) && isspace((int)*(unsigned char *)tmp)) {
++			while ((*tmp != delimiter) && isspace((unsigned char)*tmp)) {
+ 				tmp++;
+ 			}
+ 			if (*tmp == enclosure && tmp < limit) {
+diff --git a/ext/standard/filters.c b/ext/standard/filters.c
+index 9b54b3deab1..08678f8d5d8 100644
+--- a/ext/standard/filters.c
++++ b/ext/standard/filters.c
+@@ -958,7 +958,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
+ 					goto out;
+ 				}
+ 
+-				if (!isxdigit((int) *ps)) {
++				if (!isxdigit(*ps)) {
+ 					err = PHP_CONV_ERR_INVALID_SEQ;
+ 					goto out;
+ 				}
+diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c
+index b988422df21..a1927b5fe88 100644
+--- a/ext/standard/formatted_print.c
++++ b/ext/standard/formatted_print.c
+@@ -378,7 +378,7 @@ php_sprintf_getnumber(char **buffer, size_t *len)
+ 
+ int php_sprintf_get_argnum(char **format, size_t *format_len) {
+ 	char *temppos = *format;
+-	while (isdigit((int) *temppos)) temppos++;
++	while (isdigit((unsigned char)*temppos)) temppos++;
+ 	if (*temppos != '$') {
+ 		return ARG_NUM_NEXT;
+ 	}
+@@ -466,7 +466,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n
+ 
+ 			PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
+ 						  *format, format - Z_STRVAL_P(z_format)));
+-			if (isalpha((int)*format)) {
++			if (isalpha((unsigned char)*format)) {
+ 				width = precision = 0;
+ 				argnum = ARG_NUM_NEXT;
+ 			} else {
+@@ -535,7 +535,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n
+ 					}
+ 					width = Z_LVAL_P(tmp);
+ 					adjusting |= ADJ_WIDTH;
+-				} else if (isdigit((int)*format)) {
++				} else if (isdigit((unsigned char)*format)) {
+ 					PRINTF_DEBUG(("sprintf: getting width\n"));
+ 					if ((width = php_sprintf_getnumber(&format, &format_len)) < 0) {
+ 						zend_value_error("Width must be greater than zero and less than %d", INT_MAX);
+@@ -580,7 +580,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n
+ 						precision = Z_LVAL_P(tmp);
+ 						adjusting |= ADJ_PRECISION;
+ 						expprec = 1;
+-					} else if (isdigit((int)*format)) {
++					} else if (isdigit((unsigned char)*format)) {
+ 						if ((precision = php_sprintf_getnumber(&format, &format_len)) < 0) {
+ 							zend_value_error("Precision must be greater than zero and less than %d", INT_MAX);
+ 							goto fail;
+diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
+index d19113f7c77..c7491179fa9 100644
+--- a/ext/standard/ftp_fopen_wrapper.c
++++ b/ext/standard/ftp_fopen_wrapper.c
+@@ -78,8 +78,8 @@ static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer
+ {
+ 	buffer[0] = '\0'; /* in case read fails to read anything */
+ 	while (php_stream_gets(stream, buffer, buffer_size-1) &&
+-		   !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) &&
+-			 isdigit((int) buffer[2]) && buffer[3] == ' '));
++		   !(isdigit((unsigned char)buffer[0]) && isdigit((unsigned char)buffer[1]) &&
++			 isdigit((unsigned char)buffer[2]) && buffer[3] == ' '));
+ 	return strtol(buffer, NULL, 10);
+ }
+ /* }}} */
+@@ -228,7 +228,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
+ #define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) {	\
+ 	unsigned char *s = (unsigned char *) val, *e = (unsigned char *) s + val_len;	\
+ 	while (s < e) {	\
+-		if (iscntrl(*s)) {	\
++		if (iscntrl((unsigned char)*s)) {	\
+ 			php_stream_wrapper_log_error(wrapper, options, err_msg, val);	\
+ 			goto connect_errexit;	\
+ 		}	\
+@@ -339,14 +339,14 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_
+ 		/* parse pasv command (129, 80, 95, 25, 13, 221) */
+ 		tpath = tmp_line;
+ 		/* skip over the "227 Some message " part */
+-		for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++);
++		for (tpath += 4; *tpath && !isdigit((unsigned char)*tpath); tpath++);
+ 		if (!*tpath) {
+ 			return 0;
+ 		}
+ 		/* skip over the host ip, to get the port */
+ 		hoststart = tpath;
+ 		for (i = 0; i < 4; i++) {
+-			for (; isdigit((int) *tpath); tpath++);
++			for (; isdigit((unsigned char)*tpath); tpath++);
+ 			if (*tpath != ',') {
+ 				return 0;
+ 			}
+@@ -826,7 +826,7 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url,
+ 		struct tm tm, tmbuf, *gmt;
+ 		time_t stamp;
+ 
+-		while ((size_t)(p - tmp_line) < sizeof(tmp_line) && !isdigit(*p)) {
++		while ((size_t)(p - tmp_line) < sizeof(tmp_line) && !isdigit((unsigned char)*p)) {
+ 			p++;
+ 		}
+ 
+diff --git a/ext/standard/html.c b/ext/standard/html.c
+index 14ccd71a236..8d39490b888 100644
+--- a/ext/standard/html.c
++++ b/ext/standard/html.c
+@@ -682,8 +682,8 @@ static inline int process_numeric_entity(const char **buf, unsigned *code_point)
+ 
+ 	/* strtol allows whitespace and other stuff in the beginning
+ 		* we're not interested */
+-	if ((hexadecimal && !isxdigit(**buf)) ||
+-			(!hexadecimal && !isdigit(**buf))) {
++	if ((hexadecimal && !isxdigit((unsigned char)**buf)) ||
++			(!hexadecimal && !isdigit((unsigned char)**buf))) {
+ 		return FAILURE;
+ 	}
+ 
+diff --git a/ext/standard/math.c b/ext/standard/math.c
+index 8643676b03e..af5869c88bc 100644
+--- a/ext/standard/math.c
++++ b/ext/standard/math.c
+@@ -727,9 +727,9 @@ PHPAPI void _php_math_basetozval(zend_string *str, int base, zval *ret)
+ 	e = s + ZSTR_LEN(str);
+ 
+ 	/* Skip leading whitespace */
+-	while (s < e && isspace(*s)) s++;
++	while (s < e && isspace((unsigned char)*s)) s++;
+ 	/* Skip trailing whitespace */
+-	while (s < e && isspace(*(e-1))) e--;
++	while (s < e && isspace((unsigned char)e[-1])) e--;
+ 
+ 	if (e - s >= 2) {
+ 		if (base == 16 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2;
+@@ -1031,7 +1031,7 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *de
+ 	tmpbuf = strpprintf(0, "%.*F", dec, d);
+ 	if (tmpbuf == NULL) {
+ 		return NULL;
+-	} else if (!isdigit((int)ZSTR_VAL(tmpbuf)[0])) {
++	} else if (!isdigit((unsigned char)ZSTR_VAL(tmpbuf)[0])) {
+ 		return tmpbuf;
+ 	}
+ 
+diff --git a/ext/standard/metaphone.c b/ext/standard/metaphone.c
+index 7affde44de1..01ae1f965c1 100644
+--- a/ext/standard/metaphone.c
++++ b/ext/standard/metaphone.c
+@@ -78,7 +78,7 @@ static const char _codes[26] =
+ };
+ 
+ 
+-#define ENCODE(c) (isalpha(c) ? _codes[((toupper(c)) - 'A')] : 0)
++#define ENCODE(c) (isalpha((unsigned char)(c)) ? _codes[((toupper((unsigned char)(c))) - 'A')] : 0)
+ 
+ #define isvowel(c)  (ENCODE(c) & 1)		/* AEIOU */
+ 
+@@ -102,17 +102,17 @@ static const char _codes[26] =
+  * accesssing the array directly... */
+ 
+ /* Look at the next letter in the word */
+-#define Next_Letter (toupper(word[w_idx+1]))
++#define Next_Letter (toupper((unsigned char)word[w_idx+1]))
+ /* Look at the current letter in the word */
+-#define Curr_Letter (toupper(word[w_idx]))
++#define Curr_Letter (toupper((unsigned char)word[w_idx]))
+ /* Go N letters back. */
+-#define Look_Back_Letter(n)	(w_idx >= n ? toupper(word[w_idx-n]) : '\0')
++#define Look_Back_Letter(n)	(w_idx >= n ? toupper((unsigned char)word[w_idx-n]) : '\0')
+ /* Previous letter.  I dunno, should this return null on failure? */
+ #define Prev_Letter (Look_Back_Letter(1))
+ /* Look two letters down.  It makes sure you don't walk off the string. */
+-#define After_Next_Letter	(Next_Letter != '\0' ? toupper(word[w_idx+2]) \
++#define After_Next_Letter	(Next_Letter != '\0' ? toupper((unsigned char)word[w_idx+2]) \
+ 											     : '\0')
+-#define Look_Ahead_Letter(n) (toupper(Lookahead((char *) word+w_idx, n)))
++#define Look_Ahead_Letter(n) (toupper((unsigned char)Lookahead((char *) word+w_idx, n)))
+ 
+ 
+ /* Allows us to safely look ahead an arbitrary # of letters */
+@@ -156,7 +156,7 @@ static char Lookahead(char *word, size_t how_far)
+ #define Phone_Len	(p_idx)
+ 
+ /* Note is a letter is a 'break' in the word */
+-#define Isbreak(c)  (!isalpha(c))
++#define Isbreak(c)  (!isalpha((unsigned char)(c)))
+ 
+ /* {{{ metaphone */
+ static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonemes, zend_string **phoned_word, int traditional)
+@@ -179,7 +179,7 @@ static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonem
+ 
+ /*-- The first phoneme has to be processed specially. --*/
+ 	/* Find our first letter */
+-	for (; !isalpha(Curr_Letter); w_idx++) {
++	for (; !isalpha((unsigned char)Curr_Letter); w_idx++) {
+ 		/* On the off chance we were given nothing but crap... */
+ 		if (Curr_Letter == '\0') {
+ 			End_Phoned_Word();
+@@ -263,7 +263,7 @@ static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonem
+ 		 */
+ 
+ 		/* Ignore non-alphas */
+-		if (!isalpha(Curr_Letter))
++		if (!isalpha((unsigned char)Curr_Letter))
+ 			continue;
+ 
+ 		/* Drop duplicates, except CC */
+diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c
+index e6aa2e43f4c..fba61f9f484 100644
+--- a/ext/standard/quot_print.c
++++ b/ext/standard/quot_print.c
+@@ -216,11 +216,11 @@ PHP_FUNCTION(quoted_printable_decode)
+ 		switch (str_in[i]) {
+ 		case '=':
+ 			if (str_in[i + 1] && str_in[i + 2] &&
+-				isxdigit((int) str_in[i + 1]) &&
+-				isxdigit((int) str_in[i + 2]))
++				isxdigit((unsigned char)str_in[i + 1]) &&
++				isxdigit((unsigned char)str_in[i + 2]))
+ 			{
+-				ZSTR_VAL(str_out)[j++] = (php_hex2int((int) str_in[i + 1]) << 4)
+-						+ php_hex2int((int) str_in[i + 2]);
++				ZSTR_VAL(str_out)[j++] = (php_hex2int((unsigned char)str_in[i + 1]) << 4)
++						+ php_hex2int((unsigned char)str_in[i + 2]);
+ 				i += 3;
+ 			} else  /* check for soft line break according to RFC 2045*/ {
+ 				k = 1;
+diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c
+index 78ecc1642cf..61154eca3a3 100644
+--- a/ext/standard/scanf.c
++++ b/ext/standard/scanf.c
+@@ -345,7 +345,7 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
+ 			goto xpgCheckDone;
+ 		}
+ 
+-		if ( isdigit( (int)*ch ) ) {
++		if ( isdigit( (unsigned char)*ch ) ) {
+ 			/*
+ 			 * Check for an XPG3-style %n$ specification.  Note: there
+ 			 * must not be a mixture of XPG3 specs and non-XPG3 specs
+@@ -656,9 +656,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
+ 		/*
+ 		 * If we see whitespace in the format, skip whitespace in the string.
+ 		 */
+-		if ( isspace( (int)*ch ) ) {
++		if ( isspace( (unsigned char)*ch ) ) {
+ 			sch = *string;
+-			while ( isspace( (int)sch ) ) {
++			while ( isspace( (unsigned char)sch ) ) {
+ 				if (*string == '\0') {
+ 					goto done;
+ 				}
+@@ -809,7 +809,7 @@ literal:
+ 		if (!(flags & SCAN_NOSKIP)) {
+ 			while (*string != '\0') {
+ 				sch = *string;
+-				if (! isspace((int)sch) ) {
++				if (! isspace((unsigned char)sch) ) {
+ 					break;
+ 				}
+ 				string++;
+@@ -835,7 +835,7 @@ literal:
+ 				end = string;
+ 				while (*end != '\0') {
+ 					sch = *end;
+-					if ( isspace( (int)sch ) ) {
++					if ( isspace( (unsigned char)sch ) ) {
+ 						break;
+ 					}
+ 					end++;
+diff --git a/ext/standard/soundex.c b/ext/standard/soundex.c
+index 7d50be97e75..4dded617a65 100644
+--- a/ext/standard/soundex.c
++++ b/ext/standard/soundex.c
+@@ -67,7 +67,7 @@ PHP_FUNCTION(soundex)
+ 		/* BUG: should also map here accented letters used in non */
+ 		/* English words or names (also found in English text!): */
+ 		/* esstsett, thorn, n-tilde, c-cedilla, s-caron, ... */
+-		code = toupper((int)(unsigned char)str[i]);
++		code = toupper((unsigned char)str[i]);
+ 		if (code >= 'A' && code <= 'Z') {
+ 			if (_small == 0) {
+ 				/* remember first valid char */
+diff --git a/ext/standard/string.c b/ext/standard/string.c
+index da1a97f49da..8ca36ed7186 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -3534,9 +3534,9 @@ PHPAPI void php_stripcslashes(zend_string *str)
+ 				case 'f':  *target++='\f'; nlen--; break;
+ 				case '\\': *target++='\\'; nlen--; break;
+ 				case 'x':
+-					if (source+1 < end && isxdigit((int)(*(source+1)))) {
++					if (source+1 < end && isxdigit((unsigned char)source[1])) {
+ 						numtmp[0] = *++source;
+-						if (source+1 < end && isxdigit((int)(*(source+1)))) {
++						if (source+1 < end && isxdigit((unsigned char)source[1])) {
+ 							numtmp[1] = *++source;
+ 							numtmp[2] = '\0';
+ 							nlen-=3;
+@@ -4386,7 +4386,7 @@ PHP_FUNCTION(hebrev)
+ 
+ 	do {
+ 		if (block_type == _HEB_BLOCK_TYPE_HEB) {
+-			while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
++			while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((unsigned char)tmp[1]) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
+ 				tmp++;
+ 				block_end++;
+ 				block_length++;
+@@ -4436,7 +4436,7 @@ PHP_FUNCTION(hebrev)
+ 				block_end++;
+ 				block_length++;
+ 			}
+-			while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
++			while ((_isblank((int)*tmp) || ispunct((unsigned char)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
+ 				tmp--;
+ 				block_end--;
+ 			}
+@@ -4818,7 +4818,7 @@ int php_tag_find(char *tag, size_t len, const char *set) {
+ 				done =1;
+ 				break;
+ 			default:
+-				if (!isspace((int)c)) {
++				if (!isspace((unsigned char)c)) {
+ 					if (state == 0) {
+ 						state=1;
+ 					}
+@@ -4908,7 +4908,7 @@ state_0:
+ 			if (in_q) {
+ 				break;
+ 			}
+-			if (isspace(*(p + 1)) && !allow_tag_spaces) {
++			if (isspace((unsigned char)p[1]) && !allow_tag_spaces) {
+ 				*(rp++) = c;
+ 				break;
+ 			}
+@@ -4955,7 +4955,7 @@ state_1:
+ 			if (in_q) {
+ 				break;
+ 			}
+-			if (isspace(*(p + 1)) && !allow_tag_spaces) {
++			if (isspace((unsigned char)p[1]) && !allow_tag_spaces) {
+ 				goto reg_char_1;
+ 			}
+ 			depth++;
+diff --git a/ext/standard/strnatcmp.c b/ext/standard/strnatcmp.c
+index 8cbc0db1c3f..6d45785bcdd 100644
+--- a/ext/standard/strnatcmp.c
++++ b/ext/standard/strnatcmp.c
+@@ -40,12 +40,12 @@ compare_right(char const **a, char const *aend, char const **b, char const *bend
+ 	   both numbers to know that they have the same magnitude, so we
+ 	   remember it in BIAS. */
+ 	for(;; (*a)++, (*b)++) {
+-		if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&
+-			(*b == bend || !isdigit((int)(unsigned char)**b)))
++		if ((*a == aend || !isdigit((unsigned char)**a)) &&
++			(*b == bend || !isdigit((unsigned char)**b)))
+ 			return bias;
+-		else if (*a == aend || !isdigit((int)(unsigned char)**a))
++		else if (*a == aend || !isdigit((unsigned char)**a))
+ 			return -1;
+-		else if (*b == bend || !isdigit((int)(unsigned char)**b))
++		else if (*b == bend || !isdigit((unsigned char)**b))
+ 			return +1;
+ 		else if (**a < **b) {
+ 			if (!bias)
+@@ -67,12 +67,12 @@ compare_left(char const **a, char const *aend, char const **b, char const *bend)
+ 	/* Compare two left-aligned numbers: the first to have a
+ 	   different value wins. */
+ 	for(;; (*a)++, (*b)++) {
+-		if ((*a == aend || !isdigit((int)(unsigned char)**a)) &&
+-			(*b == bend || !isdigit((int)(unsigned char)**b)))
++		if ((*a == aend || !isdigit((unsigned char)**a)) &&
++			(*b == bend || !isdigit((unsigned char)**b)))
+ 			return 0;
+-		else if (*a == aend || !isdigit((int)(unsigned char)**a))
++		else if (*a == aend || !isdigit((unsigned char)**a))
+ 			return -1;
+-		else if (*b == bend || !isdigit((int)(unsigned char)**b))
++		else if (*b == bend || !isdigit((unsigned char)**b))
+ 			return +1;
+ 		 else if (**a < **b)
+ 			 return -1;
+@@ -103,27 +103,27 @@ PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len
+ 	ca = *ap; cb = *bp;
+ 
+ 	/* skip over leading zeros */
+-	while (ca == '0' && (ap+1 < aend) && isdigit((int)(unsigned char)*(ap+1))) {
++	while (ca == '0' && (ap+1 < aend) && isdigit((unsigned char)ap[1])) {
+ 		ca = *++ap;
+ 	}
+ 
+-	while (cb == '0' && (bp+1 < bend) && isdigit((int)(unsigned char)*(bp+1))) {
++	while (cb == '0' && (bp+1 < bend) && isdigit((unsigned char)bp[1])) {
+ 		cb = *++bp;
+ 	}
+ 
+ 	while (1) {
+ 
+ 		/* Skip consecutive whitespace */
+-		while (isspace((int)(unsigned char)ca)) {
++		while (isspace(ca)) {
+ 			ca = *++ap;
+ 		}
+ 
+-		while (isspace((int)(unsigned char)cb)) {
++		while (isspace(cb)) {
+ 			cb = *++bp;
+ 		}
+ 
+ 		/* process run of digits */
+-		if (isdigit((int)(unsigned char)ca)  &&  isdigit((int)(unsigned char)cb)) {
++		if (isdigit(ca)  &&  isdigit(cb)) {
+ 			fractional = (ca == '0' || cb == '0');
+ 
+ 			if (fractional)
+@@ -147,8 +147,8 @@ PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len
+ 		}
+ 
+ 		if (fold_case) {
+-			ca = toupper((int)(unsigned char)ca);
+-			cb = toupper((int)(unsigned char)cb);
++			ca = toupper(ca);
++			cb = toupper(cb);
+ 		}
+ 
+ 		if (ca < cb)
+diff --git a/ext/standard/type.c b/ext/standard/type.c
+index 93df434fe31..bf56c70d73d 100644
+--- a/ext/standard/type.c
++++ b/ext/standard/type.c
+@@ -161,7 +161,7 @@ PHP_FUNCTION(intval)
+ 		char *strval = Z_STRVAL_P(num);
+ 		size_t strlen = Z_STRLEN_P(num);
+ 
+-		while (isspace(*strval) && strlen) {
++		while (isspace((unsigned char)*strval) && strlen) {
+ 			strval++;
+ 			strlen--;
+ 		}
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index e3d95768fb0..def29df906a 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -117,7 +117,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port
+ 		p = s;
+ 		while (p < e) {
+ 			/* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */
+-			if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') {
++			if (!isalpha((unsigned char)*p) && !isdigit((unsigned char)*p) && *p != '+' && *p != '.' && *p != '-') {
+ 				if (e + 1 < ue && e < binary_strcspn(s, ue, "?#")) {
+ 					goto parse_port;
+ 				} else if (s + 1 < ue && *s == '/' && *(s + 1) == '/') { /* relative-scheme URL */
+@@ -146,7 +146,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port
+ 			 * correctly parse things like a.com:80
+ 			 */
+ 			p = e + 1;
+-			while (p < ue && isdigit(*p)) {
++			while (p < ue && isdigit((unsigned char)*p)) {
+ 				p++;
+ 			}
+ 
+@@ -186,7 +186,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port
+ 		p = e + 1;
+ 		pp = p;
+ 
+-		while (pp < ue && pp - p < 6 && isdigit(*pp)) {
++		while (pp < ue && pp - p < 6 && isdigit((unsigned char)*pp)) {
+ 			pp++;
+ 		}
+ 
+@@ -429,12 +429,12 @@ static int php_htoi(char *s)
+ 	int value;
+ 	int c;
+ 
+-	c = ((unsigned char *)s)[0];
++	c = (unsigned char)s[0];
+ 	if (isupper(c))
+ 		c = tolower(c);
+ 	value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
+ 
+-	c = ((unsigned char *)s)[1];
++	c = (unsigned char)s[1];
+ 	if (isupper(c))
+ 		c = tolower(c);
+ 	value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
+@@ -601,8 +601,8 @@ PHPAPI size_t php_url_decode(char *str, size_t len)
+ 		if (*data == '+') {
+ 			*dest = ' ';
+ 		}
+-		else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1))
+-				 && isxdigit((int) *(data + 2))) {
++		else if (*data == '%' && len >= 2 && isxdigit((unsigned char)data[1])
++				 && isxdigit((unsigned char)data[2])) {
+ 			*dest = (char) php_htoi(data + 1);
+ 			data += 2;
+ 			len -= 2;
+@@ -660,8 +660,8 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len)
+ 	char *data = str;
+ 
+ 	while (len--) {
+-		if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1))
+-			&& isxdigit((int) *(data + 2))) {
++		if (*data == '%' && len >= 2 && isxdigit((unsigned char)data[1])
++			&& isxdigit((unsigned char)data[2])) {
+ 			*dest = (char) php_htoi(data + 1);
+ 			data += 2;
+ 			len -= 2;
+@@ -722,7 +722,7 @@ no_name_header:
+ 				c = *p;
+ 				*p = '\0';
+ 				s = p + 1;
+-				while (isspace((int)*(unsigned char *)s)) {
++				while (isspace((unsigned char)*s)) {
+ 					s++;
+ 				}
+ 
+diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
+index bac49206e63..30b395b3957 100644
+--- a/ext/standard/url_scanner_ex.re
++++ b/ext/standard/url_scanner_ex.re
+@@ -85,7 +85,7 @@ static int php_ini_on_update_tags(zend_ini_entry *entry, zend_string *new_value,
+ 
+ 			*val++ = '\0';
+ 			for (q = key; *q; q++) {
+-				*q = tolower(*q);
++				*q = tolower((unsigned char)*q);
+ 			}
+ 			keylen = q - key;
+ 			str = zend_string_init(key, keylen, 1);
+@@ -134,7 +134,7 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value
+ 		char *q;
+ 
+ 		for (q = key; *q; q++) {
+-			*q = tolower(*q);
++			*q = tolower((unsigned char)*q);
+ 		}
+ 		keylen = q - key;
+ 		if (keylen > 0) {
+@@ -454,7 +454,7 @@ static inline void handle_tag(STD_PARA)
+ 	}
+ 	smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
+ 	for (i = 0; i < ZSTR_LEN(ctx->tag.s); i++)
+-		ZSTR_VAL(ctx->tag.s)[i] = tolower((int)(unsigned char)ZSTR_VAL(ctx->tag.s)[i]);
++		ZSTR_VAL(ctx->tag.s)[i] = tolower((unsigned char)ZSTR_VAL(ctx->tag.s)[i]);
+     /* intentionally using str_find here, in case the hash value is set, but the string val is changed later */
+ 	if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ZSTR_VAL(ctx->tag.s), ZSTR_LEN(ctx->tag.s))) != NULL) {
+ 		ok = 1;
+diff --git a/ext/standard/versioning.c b/ext/standard/versioning.c
+index aa60d974672..178539709c7 100644
+--- a/ext/standard/versioning.c
++++ b/ext/standard/versioning.c
+@@ -45,8 +45,8 @@ php_canonicalize_version(const char *version)
+  *  s/([^\d\.])([^\D\.])/$1.$2/g;
+  *  s/([^\D\.])([^\d\.])/$1.$2/g;
+  */
+-#define isdig(x) (isdigit(x)&&(x)!='.')
+-#define isndig(x) (!isdigit(x)&&(x)!='.')
++#define isdig(x) (isdigit((unsigned char)(x))&&(x)!='.')
++#define isndig(x) (!isdigit((unsigned char)(x))&&(x)!='.')
+ #define isspecialver(x) ((x)=='-'||(x)=='_'||(x)=='+')
+ 
+ 		lq = *(q - 1);
+@@ -59,7 +59,7 @@ php_canonicalize_version(const char *version)
+ 				*q++ = '.';
+ 			}
+ 			*q++ = *p;
+-		} else if (!isalnum(*p)) {
++		} else if (!isalnum((unsigned char)*p)) {
+ 			if (lq != '.') {
+ 				*q++ = '.';
+ 			}
+@@ -152,17 +152,17 @@ php_version_compare(const char *orig_ver1, const char *orig_ver2)
+ 		if ((n2 = strchr(p2, '.')) != NULL) {
+ 			*n2 = '\0';
+ 		}
+-		if (isdigit(*p1) && isdigit(*p2)) {
++		if (isdigit((unsigned char)*p1) && isdigit((unsigned char)*p2)) {
+ 			/* compare element numerically */
+ 			l1 = strtol(p1, NULL, 10);
+ 			l2 = strtol(p2, NULL, 10);
+ 			compare = ZEND_NORMALIZE_BOOL(l1 - l2);
+-		} else if (!isdigit(*p1) && !isdigit(*p2)) {
++		} else if (!isdigit((unsigned char)*p1) && !isdigit((unsigned char)*p2)) {
+ 			/* compare element names */
+ 			compare = compare_special_version_forms(p1, p2);
+ 		} else {
+ 			/* mix of names and numbers */
+-			if (isdigit(*p1)) {
++			if (isdigit((unsigned char)*p1)) {
+ 				compare = compare_special_version_forms("#N#", p2);
+ 			} else {
+ 				compare = compare_special_version_forms(p1, "#N#");
+@@ -180,13 +180,13 @@ php_version_compare(const char *orig_ver1, const char *orig_ver2)
+ 	}
+ 	if (compare == 0) {
+ 		if (n1 != NULL) {
+-			if (isdigit(*p1)) {
++			if (isdigit((unsigned char)*p1)) {
+ 				compare = 1;
+ 			} else {
+ 				compare = php_version_compare(p1, "#N#");
+ 			}
+ 		} else if (n2 != NULL) {
+-			if (isdigit(*p2)) {
++			if (isdigit((unsigned char)*p2)) {
+ 				compare = -1;
+ 			} else {
+ 				compare = php_version_compare("#N#", p2);
+diff --git a/main/SAPI.c b/main/SAPI.c
+index 561cf6d598c..8b47a6c828c 100644
+--- a/main/SAPI.c
++++ b/main/SAPI.c
+@@ -193,7 +193,7 @@ static void sapi_read_post_data(void)
+ 				*p = 0;
+ 				break;
+ 			default:
+-				*p = tolower(*p);
++				*p = tolower((unsigned char)*p);
+ 				break;
+ 		}
+ 	}
+@@ -710,10 +710,10 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg)
+ 	}
+ 
+ 	/* cut off trailing spaces, linefeeds and carriage-returns */
+-	if (header_line_len && isspace(header_line[header_line_len-1])) {
++	if (header_line_len && isspace((unsigned char)header_line[header_line_len - 1])) {
+ 		do {
+ 			header_line_len--;
+-		} while(header_line_len && isspace(header_line[header_line_len-1]));
++		} while(header_line_len && isspace((unsigned char)header_line[header_line_len - 1]));
+ 		header_line[header_line_len]='\0';
+ 	}
+ 
+diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
+index efb110171b1..2ba2615ee6f 100644
+--- a/main/fopen_wrappers.c
++++ b/main/fopen_wrappers.c
+@@ -487,7 +487,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt
+ 	}
+ 
+ 	/* Don't resolve paths which contain protocol (except of file://) */
+-	for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
++	for (p = filename; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
+ 	if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) {
+ 		wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE);
+ 		if (wrapper == &php_plain_files_wrapper) {
+@@ -519,7 +519,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt
+ 		/* Check for stream wrapper */
+ 		int is_stream_wrapper = 0;
+ 
+-		for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
++		for (p = ptr; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
+ 		if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) {
+ 			/* .:// or ..:// is not a stream wrapper */
+ 			if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
+@@ -588,7 +588,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt
+ 			actual_path = trypath;
+ 
+ 			/* Check for stream wrapper */
+-			for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
++			for (p = trypath; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
+ 			if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) {
+ 				wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE);
+ 				if (!wrapper) {
+diff --git a/main/php_ini.c b/main/php_ini.c
+index 136942896da..f28c7db7de5 100644
+--- a/main/php_ini.c
++++ b/main/php_ini.c
+@@ -40,7 +40,7 @@
+ 		char *tmp = path; \
+ 		while (*tmp) { \
+ 			if (*tmp == '\\') *tmp = '/'; \
+-			else *tmp = tolower(*tmp); \
++			else *tmp = tolower((unsigned char)*tmp); \
+ 				tmp++; \
+ 		} \
+ 	}
+diff --git a/main/php_variables.c b/main/php_variables.c
+index da7266416a5..a851c347601 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -185,7 +185,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac
+ 
+ 			ip++;
+ 			index_s = ip;
+-			if (isspace(*ip)) {
++			if (isspace((unsigned char)*ip)) {
+ 				ip++;
+ 			}
+ 			if (*ip==']') {
+@@ -508,7 +508,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
+ 
+ 		if (arg == PARSE_COOKIE) {
+ 			/* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
+-			while (isspace(*var)) {
++			while (isspace((unsigned char)*var)) {
+ 				var++;
+ 			}
+ 			if (var == val || *var == '\0') {
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index 83d141d38b1..c57e26b11b9 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -413,7 +413,7 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
+ 		}
+ 
+ 		/* space in the beginning means same header */
+-		if (!isspace(line[0])) {
++		if (!isspace((unsigned char)line[0])) {
+ 			value = strchr(line, ':');
+ 		}
+ 
+@@ -429,7 +429,7 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header)
+ 			}
+ 
+ 			*value = '\0';
+-			do { value++; } while (isspace(*value));
++			do { value++; } while (isspace((unsigned char)*value));
+ 
+ 			key = estrdup(line);
+ 			smart_string_appends(&buf_value, value);
+@@ -526,7 +526,7 @@ static char *substring_conf(char *start, int len, char quote)
+ 
+ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
+ {
+-	while (*str && isspace(*str)) {
++	while (*str && isspace((unsigned char)*str)) {
+ 		++str;
+ 	}
+ 
+@@ -542,7 +542,7 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str)
+ 	} else {
+ 		char *strend = str;
+ 
+-		while (*strend && !isspace(*strend)) {
++		while (*strend && !isspace((unsigned char)*strend)) {
+ 			++strend;
+ 		}
+ 		return substring_conf(str, strend - str, 0);
+@@ -809,7 +809,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ 				goto fileupload_done;
+ 			}
+ 
+-			while (isspace(*cd)) {
++			while (isspace((unsigned char)*cd)) {
+ 				++cd;
+ 			}
+ 
+@@ -817,7 +817,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+ 			{
+ 				char *key = NULL, *word = pair;
+ 
+-				while (isspace(*cd)) {
++				while (isspace((unsigned char)*cd)) {
+ 					++cd;
+ 				}
+ 
+diff --git a/main/snprintf.c b/main/snprintf.c
+index f082115c676..b591169012b 100644
+--- a/main/snprintf.c
++++ b/main/snprintf.c
+@@ -286,7 +286,7 @@ PHPAPI char * php_conv_fp(char format, double num,
+ 	/*
+ 	 * Check for Infinity and NaN
+ 	 */
+-	if (isalpha((int)*p)) {
++	if (isalpha((unsigned char)*p)) {
+ 		*len = strlen(p);
+ 		memcpy(buf, p, *len + 1);
+ 		*is_negative = false;
+@@ -433,11 +433,11 @@ typedef struct buf_area buffy;
+ #define NUM( c )			( c - '0' )
+ 
+ #define STR_TO_DEC( str, num )		\
+-    num = NUM( *str++ ) ;		\
+-    while ( isdigit((int)*str ) )		\
++    num = NUM( *(str)++ ) ;		\
++    while ( isdigit((unsigned char)*(str) ) )		\
+     {					\
+ 	num *= 10 ;			\
+-	num += NUM( *str++ ) ;		\
++	num += NUM( *(str)++ ) ;		\
+     }
+ 
+ /*
+@@ -531,7 +531,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
+ 			/*
+ 			 * Try to avoid checking for flags, width or precision
+ 			 */
+-			if (isascii((int)*fmt) && !islower((int)*fmt)) {
++			if (isascii((unsigned char)*fmt) && !islower((unsigned char)*fmt)) {
+ 				/*
+ 				 * Recognize flags: -, #, BLANK, +
+ 				 */
+@@ -553,7 +553,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
+ 				/*
+ 				 * Check if a width was specified
+ 				 */
+-				if (isdigit((int)*fmt)) {
++				if (isdigit((unsigned char)*fmt)) {
+ 					STR_TO_DEC(fmt, min_width);
+ 					adjust_width = true;
+ 				} else if (*fmt == '*') {
+@@ -573,7 +573,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
+ 				if (*fmt == '.') {
+ 					adjust_precision = true;
+ 					fmt++;
+-					if (isdigit((int)*fmt)) {
++					if (isdigit((unsigned char)*fmt)) {
+ 						STR_TO_DEC(fmt, precision);
+ 					} else if (*fmt == '*') {
+ 						precision = va_arg(ap, int);
+diff --git a/main/spprintf.c b/main/spprintf.c
+index 4c01347fcf4..2a31e3ae38b 100644
+--- a/main/spprintf.c
++++ b/main/spprintf.c
+@@ -146,12 +146,12 @@
+ #define NUM(c) (c - '0')
+ 
+ #define STR_TO_DEC(str, num) do {			\
+-	num = NUM(*str++);                  	\
+-	while (isdigit((int)*str)) {        	\
++	num = NUM(*(str)++);                  	\
++	while (isdigit((unsigned char)*(str))) {\
+ 		num *= 10;                      	\
+-		num += NUM(*str++);             	\
++		num += NUM(*(str)++);             	\
+ 		if (num >= INT_MAX / 10) {			\
+-			while (isdigit((int)*str++));	\
++			while (isdigit((unsigned char)*(str)++));	\
+ 			break;							\
+ 		}									\
+     }										\
+@@ -238,7 +238,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
+ 			/*
+ 			 * Try to avoid checking for flags, width or precision
+ 			 */
+-			if (isascii((int)*fmt) && !islower((int)*fmt)) {
++			if (isascii((unsigned char)*fmt) && !islower((unsigned char)*fmt)) {
+ 				/*
+ 				 * Recognize flags: -, #, BLANK, +
+ 				 */
+@@ -260,7 +260,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
+ 				/*
+ 				 * Check if a width was specified
+ 				 */
+-				if (isdigit((int)*fmt)) {
++				if (isdigit((unsigned char)*fmt)) {
+ 					STR_TO_DEC(fmt, min_width);
+ 					adjust_width = true;
+ 				} else if (*fmt == '*') {
+@@ -280,7 +280,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
+ 				if (*fmt == '.') {
+ 					adjust_precision = true;
+ 					fmt++;
+-					if (isdigit((int)*fmt)) {
++					if (isdigit((unsigned char)*fmt)) {
+ 						STR_TO_DEC(fmt, precision);
+ 					} else if (*fmt == '*') {
+ 						precision = va_arg(ap, int);
+diff --git a/main/streams/streams.c b/main/streams/streams.c
+index 634c0d58348..030c2453e50 100644
+--- a/main/streams/streams.c
++++ b/main/streams/streams.c
+@@ -1739,7 +1739,7 @@ static inline int php_stream_wrapper_scheme_validate(const char *protocol, unsig
+ 	unsigned int i;
+ 
+ 	for(i = 0; i < protocol_len; i++) {
+-		if (!isalnum((int)protocol[i]) &&
++		if (!isalnum((unsigned char)protocol[i]) &&
+ 			protocol[i] != '+' &&
+ 			protocol[i] != '-' &&
+ 			protocol[i] != '.') {
+@@ -1819,7 +1819,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const
+ 		return (php_stream_wrapper*)((options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper);
+ 	}
+ 
+-	for (p = path; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
++	for (p = path; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
+ 		n++;
+ 	}
+ 
+diff --git a/main/streams/transports.c b/main/streams/transports.c
+index 35ac4ae27ad..306f7ff5e4b 100644
+--- a/main/streams/transports.c
++++ b/main/streams/transports.c
+@@ -94,7 +94,7 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
+ 		}
+ 	}
+ 
+-	for (p = name; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
++	for (p = name; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++) {
+ 		n++;
+ 	}
+ 
+diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
+index 82cf5c10d15..ab0ad1d6e5c 100644
+--- a/sapi/cli/php_cli_server.c
++++ b/sapi/cli/php_cli_server.c
+@@ -633,7 +633,7 @@ static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list
+ 			if (key[i] == '-') {
+ 				key[i] = '_';
+ 			} else {
+-				key[i] = toupper(key[i]);
++				key[i] = toupper((unsigned char)key[i]);
+ 			}
+ 		}
+ 		spprintf(&real_key, 0, "%s_%s", "HTTP", key);
+diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
+index cc7102eabbc..01c4ee2d573 100644
+--- a/sapi/fpm/fpm/fpm_conf.c
++++ b/sapi/fpm/fpm/fpm_conf.c
+@@ -932,7 +932,7 @@ static int fpm_conf_process_all_pools(void)
+ 			}
+ 
+ 			for (i = 0; i < strlen(status); i++) {
+-				if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.' && status[i] != '~') {
++				if (!isalnum((unsigned char)status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.' && status[i] != '~') {
+ 					zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.~'", wp->config->name, status);
+ 					return -1;
+ 				}
+@@ -955,7 +955,7 @@ static int fpm_conf_process_all_pools(void)
+ 			}
+ 
+ 			for (i = 0; i < strlen(ping); i++) {
+-				if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.' && ping[i] != '~') {
++				if (!isalnum((unsigned char)ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.' && ping[i] != '~') {
+ 					zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must contain only the following characters '[alphanum]/_-.~'", wp->config->name, ping);
+ 					return -1;
+ 				}
+diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
+index 2b3d83ad4be..3c0c3cafe02 100644
+--- a/sapi/litespeed/lsapi_main.c
++++ b/sapi/litespeed/lsapi_main.c
+@@ -1707,12 +1707,12 @@ PHP_FUNCTION(litespeed_response_headers)
+             len = p - h->header;
+             if (p && len > 0 && len < LSAPI_RESP_HTTP_HEADER_MAX) {
+                 memmove( headerBuf, h->header, len );
+-                while( len > 0 && (isspace( headerBuf[len-1])) ) {
++                while( len > 0 && (isspace((unsigned char)headerBuf[len - 1])) ) {
+                     --len;
+                 }
+                 headerBuf[len] = 0;
+                 if ( len ) {
+-                    while( isspace(*++p));
++                    while(isspace((unsigned char)*++p));
+                     add_assoc_string_ex(return_value, headerBuf, len, p);
+                 }
+             }
+diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c
+index 09cd2e6bf9a..038e43137f2 100644
+--- a/sapi/litespeed/lsapilib.c
++++ b/sapi/litespeed/lsapilib.c
+@@ -2242,7 +2242,7 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
+ 
+             while(( pKey < pKeyEnd )&&( *p ))
+             {
+-                char ch = toupper( *pKey );
++                char ch = toupper( (unsigned char)*pKey );
+                 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
+                     break;
+                 ++p; ++pKey;
+@@ -2426,7 +2426,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
+                 if ( ch == '-' )
+                     *p++ = '_';
+                 else
+-                    *p++ = toupper( ch );
++                    *p++ = toupper( (unsigned char)ch );
+             }
+             *p = 0;
+             keyLen += 5;
+@@ -2671,7 +2671,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
+     if ( !pBind )
+         return -1;
+ 
+-    while( isspace( *pBind ) )
++    while(isspace( (unsigned char)*pBind ) )
+         ++pBind;
+ 
+     strncpy(achAddr, pBind, 255);
+diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c
+index 7e6a87fcc89..2b18949e8fd 100644
+--- a/sapi/phpdbg/phpdbg_cmd.c
++++ b/sapi/phpdbg/phpdbg_cmd.c
+@@ -766,9 +766,9 @@ PHPDBG_API char *phpdbg_read_input(const char *buffered) /* {{{ */
+ 		}
+ 	}
+ 
+-	if (buffer && isspace(*buffer)) {
++	if (buffer && isspace((unsigned char)*buffer)) {
+ 		char *trimmed = buffer;
+-		while (isspace(*trimmed))
++		while (isspace((unsigned char)*trimmed))
+ 			trimmed++;
+ 
+ 		trimmed = estrdup(trimmed);
+diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
+index 8ca6d83c78c..ebf36eae781 100644
+--- a/sapi/phpdbg/phpdbg_prompt.c
++++ b/sapi/phpdbg/phpdbg_prompt.c
+@@ -213,7 +213,7 @@ static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) {
+ 
+ 	state->line++;
+ 
+-	while (cmd_len > 0L && isspace(cmd[cmd_len-1])) {
++	while (cmd_len > 0L && isspace((unsigned char)cmd[cmd_len-1])) {
+ 		cmd_len--;
+ 	}
+ 
+diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
+index f638d608905..04bc117ffb3 100644
+--- a/sapi/phpdbg/phpdbg_utils.c
++++ b/sapi/phpdbg/phpdbg_utils.c
+@@ -82,10 +82,10 @@ PHPDBG_API int phpdbg_is_numeric(const char *str) /* {{{ */
+ 		return 0;
+ 
+ 	for (; *str; str++) {
+-		if (isspace(*str) || *str == '-') {
++		if (isspace((unsigned char)*str) || *str == '-') {
+ 			continue;
+ 		}
+-		return isdigit(*str);
++		return isdigit((unsigned char)*str);
+ 	}
+ 	return 0;
+ } /* }}} */
+@@ -96,7 +96,7 @@ PHPDBG_API int phpdbg_is_empty(const char *str) /* {{{ */
+ 		return 1;
+ 
+ 	for (; *str; str++) {
+-		if (isspace(*str)) {
++		if (isspace((unsigned char)*str)) {
+ 			continue;
+ 		}
+ 		return 0;
+@@ -199,12 +199,12 @@ PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len) /* {{
+ 	const char *p = str;
+ 	char *new = NULL;
+ 
+-	while (p && isspace(*p)) {
++	while (p && isspace((unsigned char)*p)) {
+ 		++p;
+ 		--len;
+ 	}
+ 
+-	while (*p && isspace(*(p + len -1))) {
++	while (*p && isspace((unsigned char)p[len - 1])) {
+ 		--len;
+ 	}
+ 
+diff --git a/win32/sendmail.c b/win32/sendmail.c
+index d4de4645d67..e08424bf058 100644
+--- a/win32/sendmail.c
++++ b/win32/sendmail.c
+@@ -57,7 +57,7 @@
+ 												efree(response); \
+ 											} \
+ 										}
+-#define SMTP_SKIP_SPACE(str)	{ while (isspace(*str)) { str++; } }
++#define SMTP_SKIP_SPACE(str)	{ while (isspace((unsigned char)*(str))) { (str)++; } }
+ 
+ 
+ char seps[] = " ,\t\n";
+@@ -725,7 +725,7 @@ static int PostHeader(char *RPath, const char *Subject, const char *mailTo, char
+ 		headers_lc_len = strlen(headers_lc);
+ 
+ 		for (i = 0; i < headers_lc_len; i++) {
+-			headers_lc[i] = tolower(headers_lc[i]);
++			headers_lc[i] = tolower((unsigned char)headers_lc[i]);
+ 		}
+ 	}
+ 
+@@ -853,7 +853,7 @@ return 0;
+ 
+ 	/* Resolve the servers IP */
+ 	/*
+-	if (!isdigit(PW32G(mail_host)[0])||!gethostbyname(PW32G(mail_host)))
++	if (!isdigit((unsigned char)PW32G(mail_host)[0])||!gethostbyname(PW32G(mail_host)))
+ 	{
+ 		return (FAILED_TO_RESOLVE_HOST);
+ 	}
+-- 
+2.54.0
+
+From 7dff10e9a31d469fcd436e10b06f8b2bf2758a68 Mon Sep 17 00:00:00 2001
+From: Remi Collet <remi at remirepo.net>
+Date: Thu, 7 May 2026 09:01:35 +0200
+Subject: [PATCH 10/10] NEWS from 8.2.31
+
+---
+ NEWS | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 9d420d24da6..c245d3e757e 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,5 +1,35 @@
+ PHP                                                                        NEWS
+ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
++
++Backported from 8.2.31
++
++- FPM:
++  . Fixed GHSA-7qg2-v9fj-4mwv (XSS within status endpoint). (CVE-2026-6735)
++    (Jakub Zelenka)
++
++- MBString:
++  . Fixed GHSA-wm6j-2649-pv75 (Null pointer dereference in
++    php_mb_check_encoding() via mb_ereg_search_init()). (CVE-2026-7259)
++    (vi3tL0u1s)
++
++- PDO_Firebird:
++  . Fixed GHSA-w476-322c-wpvm (SQL injection via NUL bytes in quoted strings).
++    (CVE-2025-14179) (SakiTakamachi)
++
++- SOAP:
++  . Fixed GHSA-85c2-q967-79q5 (Stale SOAP_GLOBAL(ref_map) pointer with Apache
++    Map). (CVE-2026-6722) (ilutov)
++  . Fixed GHSA-m33r-qmcv-p97q (Use-after-free after header parsing failure with
++    SOAP_PERSISTENCE_SESSION). (CVE-2026-7261) (ilutov)
++  . Fixed GHSA-hmxp-6pc4-f3vv (Broken Apache map value NULL check).
++    (CVE-2026-7262) (ilutov)
++
++- Standard:
++  . Fixed GHSA-96wq-48vp-hh57 (Signed integer overflow of char array offset).
++    (CVE-2026-7568) (TimWolla)
++  . Fixed GHSA-m8rr-4c36-8gq4 (Consistently pass unsigned char to ctype.h
++    functions). (CVE-2026-7258) (ilutov)
++
+ 18 Dec 2025, PHP 8.1.34
+ 
+ - Curl:
+-- 
+2.54.0
+
diff --git a/php-cve-2026-7259.patch b/php-cve-2026-7259.patch
new file mode 100644
index 0000000..13393af
--- /dev/null
+++ b/php-cve-2026-7259.patch
@@ -0,0 +1,66 @@
+From 785bcb5dd5980a4f3173ab0b80c70a5602bc9339 Mon Sep 17 00:00:00 2001
+From: vi3tL0u1s <luuviethoang.attt at gmail.com>
+Date: Sun, 3 May 2026 20:02:21 +0200
+Subject: [PATCH 05/10] GHSA-wm6j-2649-pv75: [mbstring] Fix null pointer
+ dereference in php_mb_check_encoding() via mb_ereg_search_init()
+
+Fixes GHSA-wm6j-2649-pv75
+Fixes CVE-2026-7259
+
+(cherry picked from commit 79a054eae016c56409432e69aebc8ca908a88838)
+---
+ Zend/tests/GHSA-wm6j-2649-pv75.phpt | 22 ++++++++++++++++++++++
+ ext/mbstring/php_mbregex.c          |  7 ++++++-
<Skipped 7480 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/php.git/commitdiff/00fc6f8628d7d05eec9ee9e9be1ac1823842960e



More information about the pld-cvs-commit mailing list