diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 3c134f44..67942e39 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -376,6 +376,7 @@ ZEND_API 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 int object_init(zval *arg); ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce); ZEND_API int 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 25216898..126aa124 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" #ifdef HAVE_SIGNAL_H # include @@ -358,7 +359,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, @@ -370,22 +406,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 @@ -1352,7 +1380,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 @@ -2596,7 +2624,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); @@ -2608,7 +2636,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); @@ -2622,7 +2650,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)) { @@ -2901,7 +2929,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 b3986ab9..992fa225 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -397,6 +397,8 @@ static void apc_init_heap(void) */ +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 6eb9dfac..cc2faeff 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -265,11 +265,31 @@ void shutdown_executor(void) /* {{{ */ zend_close_rsrc_list(&EG(regular_list)); } zend_end_try(); + /* No PHP callback functions should be called after this point. */ + EG(active) = 0; + + if (!fast_shutdown) { + zend_hash_graceful_reverse_destroy(&EG(symbol_table)); + +#if ZEND_DEBUG + if (gc_enabled() && !CG(unclean_shutdown)) { + gc_collect_cycles(); + } +#endif + } else { + /* 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); - /* All resources and objects are destroyed. */ - /* No PHP callback functions may be called after this point. */ - EG(active) = 0; + /* may be used by zend_error_zstr_at before init_executor */ + EG(error_handling) = EH_NORMAL; + EG(exception) = NULL; zend_try { zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator); @@ -285,14 +305,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)); zend_cleanup_internal_classes(); - } else { - zend_hash_graceful_reverse_destroy(&EG(symbol_table)); - -#if ZEND_DEBUG - if (gc_enabled() && !CG(unclean_shutdown)) { - gc_collect_cycles(); - } -#endif + EG(objects_store).object_buckets = NULL; + EG(objects_store).top = 1; /* remove error handlers before destroying classes and functions, * so that if handler used some class, crash would not happen */ diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 16fd24e3..a0b5daff 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -93,7 +93,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)); } #if defined(ZEND_WIN32) @@ -219,6 +219,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)); @@ -230,7 +237,7 @@ static 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)); } ht->nTableSize += ht->nTableSize; HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); @@ -1041,7 +1048,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 2c295adc..51dc4c5e 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -276,6 +276,7 @@ ZEND_API int 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 uint32_t zend_array_count(HashTable *ht); ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source); diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index ea5e2cae..f45ddda9 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -112,6 +112,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l) current = next; } + l->head = NULL; + l->tail = NULL; l->count = 0; } diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index 1ec1af06..ee2fd8df 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_operators.c b/Zend/zend_operators.c index ef778ea1..66f02ac3 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1844,7 +1844,7 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) / size_t result_len = op1_len + op2_len; zend_string *result_str; - if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) { + if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) { zend_throw_error(NULL, "String size overflow"); zval_ptr_dtor_str(&op1_copy); zval_ptr_dtor_str(&op2_copy); diff --git a/Zend/zend_string.h b/Zend/zend_string.h index c95578d4..5af0a35d 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -76,6 +76,9 @@ END_EXTERN_C() #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1) +#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1)) +#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD) + #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \ (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \ GC_SET_REFCOUNT(str, 1); \ diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 3aa99f8d..01c1779d 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -600,7 +600,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) @@ -613,7 +613,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 4250aabd..fd7e5d6a 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -317,17 +317,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 9c46476b..7ce7e361 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -308,29 +308,45 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - FREE_OP1(); + if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - FREE_OP2(); + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !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); - FREE_OP2(); + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - FREE_OP1(); - FREE_OP2(); + if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -2732,29 +2748,45 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - FREE_OP1(); + if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - FREE_OP2(); + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && !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); - FREE_OP2(); + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - FREE_OP1(); - FREE_OP2(); + if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a84cfe3d..9fac5b1f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4954,29 +4954,45 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !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); - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -6665,29 +6681,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - zval_ptr_dtor_nogc(free_op2); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -7136,29 +7168,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - zval_ptr_dtor_nogc(free_op2); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -9769,29 +9817,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -10238,29 +10302,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CONST != IS_CONST && IS_CONST != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -12962,29 +13042,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -13727,29 +13823,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -14700,29 +14812,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -15341,29 +15469,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -16795,29 +16939,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -17222,29 +17382,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - zval_ptr_dtor_nogc(free_op1); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - zval_ptr_dtor_nogc(free_op1); - + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -38573,29 +38749,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -41082,29 +41274,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -42551,29 +42759,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - zval_ptr_dtor_nogc(free_op2); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -44849,29 +45073,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - zval_ptr_dtor_nogc(free_op2); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - zval_ptr_dtor_nogc(free_op2); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } @@ -48219,29 +48459,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } else { @@ -50651,29 +50907,45 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER } else { ZVAL_STR(EX_VAR(opline->result.var), op2_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { if (IS_CV == IS_CONST || IS_CV == IS_CV) { ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); } else { ZVAL_STR(EX_VAR(opline->result.var), op1_str); } - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } else if (IS_CV != IS_CONST && IS_CV != IS_CV && !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); - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + 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); ZVAL_NEW_STR(EX_VAR(opline->result.var), str); - - + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } } ZEND_VM_NEXT_OPCODE(); } diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index decaa0e1..4d86241f 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1676,7 +1676,7 @@ matched: } if (new_len >= alloc_len) { - alloc_len = zend_safe_address_guarded(2, new_len, alloc_len); + alloc_len = zend_safe_address_guarded(2, new_len, ZSTR_MAX_OVERHEAD) - ZSTR_MAX_OVERHEAD; if (result == NULL) { result = zend_string_alloc(alloc_len, 0); } else { @@ -1762,14 +1762,12 @@ not_matched: result = zend_string_copy(subject_str); break; } - new_len = result_len + subject_len - last_end_offset; - if (new_len >= alloc_len) { - alloc_len = new_len; /* now we know exactly how long it is */ - if (NULL != result) { - result = zend_string_realloc(result, alloc_len, 0); - } else { - result = zend_string_alloc(alloc_len, 0); - } + /* now we know exactly how long it is */ + alloc_len = result_len + subject_len - last_end_offset; + if (NULL != result) { + result = zend_string_realloc(result, alloc_len, 0); + } else { + result = zend_string_alloc(alloc_len, 0); } /* stick that last bit of string on our output */ memcpy(ZSTR_VAL(result) + result_len, piece, subject_len - last_end_offset); @@ -1913,9 +1911,9 @@ matched: pcre2_get_mark(match_data)); ZEND_ASSERT(eval_result); - new_len = zend_safe_address_guarded(1, ZSTR_LEN(eval_result), new_len); + new_len = zend_safe_address_guarded(1, ZSTR_LEN(eval_result) + ZSTR_MAX_OVERHEAD, new_len) -ZSTR_MAX_OVERHEAD; if (new_len >= alloc_len) { - alloc_len = zend_safe_address_guarded(2, new_len, alloc_len); + alloc_len = zend_safe_address_guarded(2, new_len, ZSTR_MAX_OVERHEAD) - ZSTR_MAX_OVERHEAD; if (result == NULL) { result = zend_string_alloc(alloc_len, 0); } else { @@ -1972,14 +1970,12 @@ not_matched: result = zend_string_copy(subject_str); break; } - new_len = result_len + subject_len - last_end_offset; - if (new_len >= alloc_len) { - alloc_len = new_len; /* now we know exactly how long it is */ - if (NULL != result) { - result = zend_string_realloc(result, alloc_len, 0); - } else { - result = zend_string_alloc(alloc_len, 0); - } + /* now we know exactly how long it is */ + alloc_len = result_len + subject_len - last_end_offset; + if (NULL != result) { + result = zend_string_realloc(result, alloc_len, 0); + } else { + result = zend_string_alloc(alloc_len, 0); } /* stick that last bit of string on our output */ memcpy(ZSTR_VAL(result) + result_len, piece, subject_len - last_end_offset); diff --git a/ext/pcre/tests/bug81243.phpt b/ext/pcre/tests/bug81243.phpt new file mode 100644 index 00000000..a413f33f --- /dev/null +++ b/ext/pcre/tests/bug81243.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #81243 (Too much memory is allocated for preg_replace()) +--FILE-- + +--EXPECT-- +bool(true) +bool(true) diff --git a/ext/session/session.c b/ext/session/session.c index 52b9da31..94120a9c 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -3160,7 +3160,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/main/SAPI.c b/main/SAPI.c index afb0c772..6749184e 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -513,18 +513,23 @@ SAPI_API void sapi_deactivate(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 30629117..2a985b5c 100644 --- a/main/main.c +++ b/main/main.c @@ -784,6 +784,7 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) + PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals) @@ -1920,6 +1921,8 @@ void php_request_shutdown(void *dummy) for (i=0; i