[php-src] PHP-8.1-CVE-2026-109618-109619: Avoid state corruption via bailout
| From: | Arnaud Le Blanc via Ilija Tovilo | Date: | Wed, 21 Oct 2026 13:35:47 +0000 |
| Subject: | [php-src] PHP-8.1-CVE-2026-109618-109619: Avoid state corruption via bailout | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142520@lists.php.net to get a copy of this message | ||
Author: Arnaud Le Blanc (arnaud-lb)
Committer: Ilija Tovilo (iluuu1994)
Pusher: DanielEScherzer
Date: 2026-10-18T20:12:35+02:00
Commit: https://github.com/php/php-src/commit/1d7dec178a094e6e75b229ce22754045f8c6070a
Raw diff: https://github.com/php/php-src/commit/1d7dec178a094e6e75b229ce22754045f8c6070a.diff
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@me.com>
Changed paths:
M Zend/zend_API.h
M Zend/zend_alloc.c
M Zend/zend_alloc.h
M Zend/zend_execute_API.c
M Zend/zend_hash.c
M Zend/zend_hash.h
M Zend/zend_multiply.h
M Zend/zend_strtod.c
M Zend/zend_types.h
M Zend/zend_vm_def.h
M Zend/zend_vm_execute.h
M ext/opcache/ZendAccelerator.c
M ext/opcache/ZendAccelerator.h
M ext/opcache/zend_file_cache.c
M ext/opcache/zend_persist.c
M ext/session/session.c
M ext/zend_test/tests/observer_bug81430_2.phpt
M ext/zend_test/tests/observer_bug81435.phpt
M ext/zend_test/tests/observer_error_01.phpt
M main/SAPI.c
M main/main.c
M main/php_variables.c
M main/rfc1867.c
Diff:
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 9ed1a3fbabd2..a32b83c0533d 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 61792b37c9c5..7f43a7f6df07 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 9603af8a27d3..72becadc7746 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 1e31934f1581..82cea225a8ed 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 b96a95110117..65f31c2b9a21 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 092682d67713..09a7994d91d5 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 c6cd472a237b..bfe1b8e88692 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 3e7f90378ef5..7f72c82f610e 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 5bc47dd31934..ab28b0fa163b 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 a6f86a9eab6f..ad893ebfb5c6 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 5ee1c2c94daf..dc78ba4a08d0 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 530620f6259f..e030b4413193 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 de5ec45de72c..72d3a239342b 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 7b4b4cbb1211..f1b1da2baa78 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 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle
*file_handl
} 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 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle
*file_handl
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 49dfea34e33e..4ff93a12b33e 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 114df24b4649..d72ae27b4481 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 90e0fa5ce015..2cdbca9a7029 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 7b927e55fb19..e435292da0bd 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 10b1e569b0fa..70a761016a8e 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 561cf6d598c6..656418a08e54 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 9c62aa914eb0..b9994ccf9d24 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 da7266416a54..aaeb28172d7a 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 83d141d38b11..92e3eaec8383 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(*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(*strend)) {
++strend;
}
- return substring_conf(str, strend - str, 0);
+ return substring_conf(str, (size_t)(strend - str), 0);
}
}