From c47a1a260d67d1991081a6050a4460feaa73dcad Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 17 Jan 2023 17:24:25 +0100 Subject: [PATCH 001/103] PHP-8.1 is now for PHP 8.1.16-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 6d206f825234f..3911a49570222 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.15 +?? ??? ????, PHP 8.1.16 + + +02 Feb 2023, PHP 8.1.15 - Apache: . Fixed bug GH-9949 (Partial content on incomplete POST request). (cmb) diff --git a/Zend/zend.h b/Zend/zend.h index ac3a826a4813b..16b0ce6a1bd82 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.15-dev" +#define ZEND_VERSION "4.1.16-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index f7e15261412b1..6bf3274d2705b 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.15-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.16-dev],[https://bugs.php.net],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 165364047e310..4231920700d72 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 15 +#define PHP_RELEASE_VERSION 16 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.15-dev" -#define PHP_VERSION_ID 80115 +#define PHP_VERSION "8.1.16-dev" +#define PHP_VERSION_ID 80116 From b5e9bf777518e0b21d00dc69340e98db8581d659 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 15 Jan 2023 23:15:40 +0100 Subject: [PATCH 002/103] Fix incorrect check condition in ZEND_YIELD The condition `UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE` always returned false, because `UNEXPECTED(expression)` always returns 0 or 1. Move the parens so the comparison is executed properly. Closes GH-10332. --- NEWS | 2 ++ Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 40 ++++++++++++++++++++-------------------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/NEWS b/NEWS index 3911a49570222..f43d3bf531b7a 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.16 +- Core: + . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) 02 Feb 2023, PHP 8.1.15 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d869116c33e33..4845a92b95a7e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8119,7 +8119,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED /* Set the new yielded key */ if (OP2_TYPE != IS_UNUSED) { zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R); - if ((OP2_TYPE & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((OP2_TYPE & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c22a1a104e93c..a5a5eabf2b037 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7526,7 +7526,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -9665,7 +9665,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE /* Set the new yielded key */ if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -10508,7 +10508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { zval *key = NULL; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -12020,7 +12020,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -19834,7 +19834,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -20273,7 +20273,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER( /* Set the new yielded key */ if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -20733,7 +20733,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { zval *key = NULL; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -21132,7 +21132,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -24957,7 +24957,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -27255,7 +27255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( /* Set the new yielded key */ if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -29154,7 +29154,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { zval *key = NULL; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -31533,7 +31533,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -33604,7 +33604,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -35341,7 +35341,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDL /* Set the new yielded key */ if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -35883,7 +35883,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { zval *key = NULL; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -37809,7 +37809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -43038,7 +43038,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE /* Set the new yielded key */ if (IS_CONST != IS_UNUSED) { zval *key = RT_CONSTANT(opline, opline->op2); - if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -46593,7 +46593,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(Z /* Set the new yielded key */ if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -48392,7 +48392,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z /* Set the new yielded key */ if (IS_UNUSED != IS_UNUSED) { zval *key = NULL; - if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); @@ -51978,7 +51978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ /* Set the new yielded key */ if (IS_CV != IS_UNUSED) { zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key)) == IS_REFERENCE) { + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { key = Z_REFVAL_P(key); } ZVAL_COPY(&generator->key, key); From 7d68f9128eb58f1b6f31e4a38134b58dae846ed8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 19 Jan 2023 07:40:24 +0300 Subject: [PATCH 003/103] Fix incorrect compilation of FE_FETCH with predicted empty array Fixes ext/opcache/tests/sccp_loop_var_free.phpt with opcache.jit=1205 and opcache.optimization_level=0 --- ext/opcache/jit/zend_jit_arm64.dasc | 14 ++++++++++++++ ext/opcache/jit/zend_jit_x86.dasc | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 5c201252d7d3a..7bca5be068b18 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -14536,6 +14536,20 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o { zend_jit_addr op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var); + if (!MAY_BE_HASH(op1_info) && !MAY_BE_PACKED(op1_info)) { + /* empty array */ + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | b &exit_addr + } else { + | b >3 + } + } else { + | b =>target_label + } + return 1; + } + | // array = EX_VAR(opline->op1.var); | // fe_ht = Z_ARRVAL_P(array); | GET_ZVAL_PTR FCARG1x, op1_addr, TMP1 diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 57a2cc9b28c96..af4500d9835a1 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -15438,6 +15438,20 @@ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, uint32_t o { zend_jit_addr op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var); + if (!MAY_BE_HASH(op1_info) && !MAY_BE_PACKED(op1_info)) { + /* empty array */ + if (exit_addr) { + if (exit_opcode == ZEND_JMP) { + | jmp &exit_addr + } else { + | jmp >3 + } + } else { + | jmp =>target_label + } + return 1; + } + | // array = EX_VAR(opline->op1.var); | // fe_ht = Z_ARRVAL_P(array); | GET_ZVAL_PTR FCARG1a, op1_addr From ce877da23bd48f90c189d89147a5cbb26a525274 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 19 Jan 2023 18:48:03 +0000 Subject: [PATCH 004/103] Sync with timelib 2021.19 --- ext/date/lib/timelib.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 8c88b26cad44e..03a83a4d290e2 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202118 -#define TIMELIB_EXTENDED_VERSION 20211801 -#define TIMELIB_ASCII_VERSION "2021.18" +#define TIMELIB_VERSION 202119 +#define TIMELIB_EXTENDED_VERSION 20211901 +#define TIMELIB_ASCII_VERSION "2021.19" #include #include From 0801c567dc09787eba797d23f48f56b962b4282b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Jan 2023 23:52:48 +0100 Subject: [PATCH 005/103] Fix GH-10248: Assertion `!(zval_get_type(&(*(property))) == 10)' failed. The assertion failure was triggered in a debug code-path that validates property types for internal classes. zend_verify_internal_read_property_type was called with retval being a reference, which is not allowed because that function eventually calls to i_zend_check_property_type, which does not expect a reference. The non-debug code-path already takes into account that retval can be a reference, as it optionally dereferences retval. Add a dereference in zend_verify_internal_read_property_type just before the call to zend_verify_property_type, which is how other callers often behave as well. --- Zend/zend_execute.c | 1 + ext/spl/tests/gh10248.phpt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 ext/spl/tests/gh10248.phpt diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index fc555bfce1184..922b45c42baf4 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1207,6 +1207,7 @@ static void zend_verify_internal_read_property_type(zend_object *obj, zend_strin zend_property_info *prop_info = zend_get_property_info(obj->ce, name, /* silent */ true); if (prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(val); zend_verify_property_type(prop_info, val, /* strict */ true); } } diff --git a/ext/spl/tests/gh10248.phpt b/ext/spl/tests/gh10248.phpt new file mode 100644 index 0000000000000..d4af9e98d0f69 --- /dev/null +++ b/ext/spl/tests/gh10248.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-10248 (Assertion `!(zval_get_type(&(*(property))) == 10)' failed.) +--FILE-- +property = &$b; +$a->property; + +echo "Done\n"; + +?> +--EXPECT-- +Done From f6734495f7581b821a8c098badcf4e5d0e8125e4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 20 Jan 2023 16:47:36 +0100 Subject: [PATCH 006/103] [ci skip] NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index f43d3bf531b7a..436d8faf46dce 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS trampoline is used from internal code). (Derick) . Fix GH-10251 (Assertion `(flag & (1<<3)) == 0' failed). (nielsdos) . Fix wrong comparison in block optimisation pass after opcode update. (nieldsdos) + . Fix GH-10248 (Assertion `!(zval_get_type(&(*(property))) == 10)' failed). + (nielsdos) - Date: . Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like From 974dba3b80e46b12af956a12b64bb0ab99513673 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 21 Jan 2023 14:05:59 +0100 Subject: [PATCH 007/103] Fix duplicated FILE section in test bug80747.phpt Signed-off-by: George Peter Banyard --- ext/openssl/tests/bug80747.phpt | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/openssl/tests/bug80747.phpt b/ext/openssl/tests/bug80747.phpt index cc7770ea68e5b..b21fc4d9dcda3 100644 --- a/ext/openssl/tests/bug80747.phpt +++ b/ext/openssl/tests/bug80747.phpt @@ -1,6 +1,5 @@ --TEST-- Bug #80747: Providing RSA key size < 512 generates key that crash PHP ---FILE-- --EXTENSIONS-- openssl --SKIPIF-- From 560ca9c7ae24467eeabd01e42f498682b70763f4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 24 Jan 2023 07:15:03 +0100 Subject: [PATCH 008/103] Fix incorrect bitshifting and masking in ffi bitfield (#10403) When a uint8_t is bitshifted to the left, it is actually promoted to an int. For the current code this has the effect of a wrong sign-extension, and the result will also wrongly become zero when insert_pos >= 32. Fix this by adding an explicit cast. Furthermore, the partial prefix byte mask was computed incorrectly: the byte is already shifted so the mask should not account for the shift. --- ext/ffi/ffi.c | 6 +++--- ext/ffi/tests/gh10403.phpt | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 ext/ffi/tests/gh10403.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 686db459eff5b..107d2862c1256 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -592,14 +592,14 @@ static uint64_t zend_ffi_bit_field_read(void *ptr, zend_ffi_field *field) /* {{{ /* Read partial prefix byte */ if (pos != 0) { size_t num_bits = 8 - pos; - mask = ((1U << num_bits) - 1U) << pos; + mask = (1U << num_bits) - 1U; val = (*p++ >> pos) & mask; insert_pos += num_bits; } /* Read full bytes */ while (p < last_p) { - val |= *p++ << insert_pos; + val |= (uint64_t) *p++ << insert_pos; insert_pos += 8; } @@ -607,7 +607,7 @@ static uint64_t zend_ffi_bit_field_read(void *ptr, zend_ffi_field *field) /* {{{ if (p == last_p) { size_t num_bits = last_bit % 8 + 1; mask = (1U << num_bits) - 1U; - val |= (*p & mask) << insert_pos; + val |= (uint64_t) (*p & mask) << insert_pos; } return val; diff --git a/ext/ffi/tests/gh10403.phpt b/ext/ffi/tests/gh10403.phpt new file mode 100644 index 0000000000000..6e422c438fdf6 --- /dev/null +++ b/ext/ffi/tests/gh10403.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-10403: Fix incorrect bitshifting and masking in ffi bitfield +--EXTENSIONS-- +ffi +--SKIPIF-- + +--FILE-- +new('struct MyStruct'); +$test_struct->x = 1023; +$test_values = [0x3fafbfcfdfefff, 0x01020304050607, 0, 0x3fffffffffffff, 0x2ffffffffffff5]; +foreach ($test_values as $test_value) { + $test_struct->y = $test_value; + var_dump($test_struct->y === $test_value); +} +var_dump($test_struct->x); +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +int(1023) From 2787e3cd6548079b1bd8546ce5938dd10004b40c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 24 Jan 2023 07:32:07 +0100 Subject: [PATCH 009/103] Fix incorrect check condition in type inference (#10425) The "nothing to do" case would never be hit because the switch block would execute if the opcode is ZEND_ASSIGN_STATIC_PROP_OP, not ZEND_ASSIGN_STATIC_PROP. This meant that we were falling through to the else block. Fix this by correcting the check condition. --- Zend/Optimizer/zend_inference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 0654464f108dc..dfb70a3dcabf0 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2505,7 +2505,7 @@ static zend_always_inline int _zend_update_type_info( UPDATE_SSA_TYPE(orig, ssa_op->op1_def); COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def); } - } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP) { + } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { /* Nothing to do */ } else { if (opline->opcode == ZEND_ASSIGN_OP && ssa_op->result_def >= 0 && (tmp & MAY_BE_RC1)) { From 3197104e85957b8debb8d49a7e224618055da4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 24 Jan 2023 19:00:41 +0100 Subject: [PATCH 010/103] Fix GH-10292 1st param of mt_srand() has UNKNOWN default on PHP <8.3 Closes GH-10429 --- NEWS | 4 ++++ ext/standard/basic_functions.stub.php | 4 ++-- ext/standard/basic_functions_arginfo.h | 4 ++-- ext/standard/tests/general_functions/rand.phpt | 13 +++++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 436d8faf46dce..d1836167d7f17 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Core: . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) +- Standard: + . Fixed bug GH-10292 (Made the default value of the first param of srand() and + mt_srand() unknown). (kocsismate) + 02 Feb 2023, PHP 8.1.15 - Apache: diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 3a5f482456666..5c46718652ee3 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1548,10 +1548,10 @@ function quoted_printable_encode(string $string): string {} /* mt_rand.c */ -function mt_srand(int $seed = 0, int $mode = MT_RAND_MT19937): void {} +function mt_srand(int $seed = UNKNOWN, int $mode = MT_RAND_MT19937): void {} /** @alias mt_srand */ -function srand(int $seed = 0, int $mode = MT_RAND_MT19937): void {} +function srand(int $seed = UNKNOWN, int $mode = MT_RAND_MT19937): void {} function rand(int $min = UNKNOWN, int $max = UNKNOWN): int {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 693b2644cbf5b..2f93d91d4960e 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 87ed2b04b9b46ce3df78d6f9d6d62bd6b2ae8fe5 */ + * Stub hash: eb6a3a2e3cf8f62e768d5d4968606438819e6cf0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -1813,7 +1813,7 @@ ZEND_END_ARG_INFO() #define arginfo_quoted_printable_encode arginfo_base64_encode ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mt_srand, 0, 0, IS_VOID, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, seed, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO(0, seed, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "MT_RAND_MT19937") ZEND_END_ARG_INFO() diff --git a/ext/standard/tests/general_functions/rand.phpt b/ext/standard/tests/general_functions/rand.phpt index 73dec4eb75ff1..409108914fb86 100644 --- a/ext/standard/tests/general_functions/rand.phpt +++ b/ext/standard/tests/general_functions/rand.phpt @@ -13,10 +13,21 @@ var_dump(rand(0,3)); var_dump(srand()); var_dump(srand(-1)); +try { + srand(mode: MT_RAND_MT19937); +} catch (Error $e) { + echo $e->getMessage() . "\n"; +} var_dump(mt_srand()); var_dump(mt_srand(-1)); +try { + mt_srand(mode: MT_RAND_MT19937); +} catch (Error $e) { + echo $e->getMessage() . "\n"; +} + var_dump(getrandmax()); var_dump(mt_getrandmax()); @@ -32,8 +43,10 @@ int(%i) int(%d) NULL NULL +srand(): Argument #1 ($seed) must be passed explicitly, because the default value is not known NULL NULL +mt_srand(): Argument #1 ($seed) must be passed explicitly, because the default value is not known int(%d) int(%d) Done From 40da9961f20fafc9ac5322c7700f451fe3568891 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 24 Jan 2023 23:19:21 +0100 Subject: [PATCH 011/103] [ci skip] NEWS (#10442) --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index d1836167d7f17..ebd284b87f2f6 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,10 @@ PHP NEWS - Core: . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) + . Fixed incorrect check condition in type inference. (nielsdos) + +- FFI: + . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and From b7a158a19bc7939d6c73f6c95d2e44ac964ba52d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 23 Jan 2023 22:11:08 +0100 Subject: [PATCH 012/103] Fix incorrect page_size check The current check always evaluated to false because if `!page_size` is true, then `page_size & (page_size - 1)` equals `0 & (0 - 1)` which is always 0. The if condition is meant to check if page_size is zero or not a power of two, thus we must change the AND to an OR to fix this issue. Closes GH-10427 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/opcache/ZendAccelerator.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ebd284b87f2f6..f7eaef0535599 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ PHP NEWS - FFI: . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) +- Opcache: + . Fix incorrect page_size check. (nielsdos) + - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 99bb33573f3b2..1ffd6cb3e5d46 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3197,7 +3197,7 @@ static zend_result accel_post_startup(void) size_t page_size; page_size = zend_get_page_size(); - if (!page_size && (page_size & (page_size - 1))) { + if (!page_size || (page_size & (page_size - 1))) { zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can't get page size."); abort(); } From a8c8fb2564f46be7832f994717b0b4653bdf744a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 21 Jan 2023 13:50:36 +0100 Subject: [PATCH 013/103] Fix incorrect check in cs_8559_5 in map_from_unicode() The condition `code == 0x0450 || code == 0x045D` is always false because of an incorrect range check on code. According to the BMP coverage in the encoding spec for ISO-8859-5 (https://encoding.spec.whatwg.org/iso-8859-5-bmp.html) the range of valid characters is 0x0401 - 0x045F (except for 0x040D, 0x0450, 0x045D). The current check has an upper bound of 0x044F instead of 0x045F. Fix this by changing the upper bound. Closes GH-10399 Signed-off-by: George Peter Banyard --- NEWS | 1 + ext/standard/html.c | 2 +- .../strings/html_entity_decode_iso8859-5.phpt | 28 +++++++++---------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index f7eaef0535599..d8028bf92a63c 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) + . Fix incorrect check in cs_8559_5 in map_from_unicode(). (nielsdos) 02 Feb 2023, PHP 8.1.15 diff --git a/ext/standard/html.c b/ext/standard/html.c index b93ce95df1900..14ccd71a2368c 100644 --- a/ext/standard/html.c +++ b/ext/standard/html.c @@ -477,7 +477,7 @@ static inline int map_from_unicode(unsigned code, enum entity_charset charset, u *res = 0xF0; /* numero sign */ } else if (code == 0xA7) { *res = 0xFD; /* section sign */ - } else if (code >= 0x0401 && code <= 0x044F) { + } else if (code >= 0x0401 && code <= 0x045F) { if (code == 0x040D || code == 0x0450 || code == 0x045D) return FAILURE; *res = code - 0x360; diff --git a/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt b/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt index 46e6dc4dfe3c8..0616827c54853 100644 --- a/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt +++ b/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt @@ -358,47 +358,47 @@ CYRILLIC SMALL LETTER YA: я => ef NUMERO SIGN: № => f0 ð => ð -CYRILLIC SMALL LETTER IO: ё => 2623783435313b +CYRILLIC SMALL LETTER IO: ё => f1 ñ => ñ -CYRILLIC SMALL LETTER DJE: ђ => 2623783435323b +CYRILLIC SMALL LETTER DJE: ђ => f2 ò => ò -CYRILLIC SMALL LETTER GJE: ѓ => 2623783435333b +CYRILLIC SMALL LETTER GJE: ѓ => f3 ó => ó -CYRILLIC SMALL LETTER UKRAINIAN IE: є => 2623783435343b +CYRILLIC SMALL LETTER UKRAINIAN IE: є => f4 ô => ô -CYRILLIC SMALL LETTER DZE: ѕ => 2623783435353b +CYRILLIC SMALL LETTER DZE: ѕ => f5 õ => õ -CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I: і => 2623783435363b +CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I: і => f6 ö => ö -CYRILLIC SMALL LETTER YI: ї => 2623783435373b +CYRILLIC SMALL LETTER YI: ї => f7 ÷ => ÷ -CYRILLIC SMALL LETTER JE: ј => 2623783435383b +CYRILLIC SMALL LETTER JE: ј => f8 ø => ø -CYRILLIC SMALL LETTER LJE: љ => 2623783435393b +CYRILLIC SMALL LETTER LJE: љ => f9 ù => ù -CYRILLIC SMALL LETTER NJE: њ => 2623783435413b +CYRILLIC SMALL LETTER NJE: њ => fa ú => ú -CYRILLIC SMALL LETTER TSHE: ћ => 2623783435423b +CYRILLIC SMALL LETTER TSHE: ћ => fb û => û -CYRILLIC SMALL LETTER KJE: ќ => 2623783435433b +CYRILLIC SMALL LETTER KJE: ќ => fc ü => ü SECTION SIGN: § => fd ý => ý -CYRILLIC SMALL LETTER SHORT U: ў => 2623783435453b +CYRILLIC SMALL LETTER SHORT U: ў => fe þ => þ -CYRILLIC SMALL LETTER DZHE: џ => 2623783435463b +CYRILLIC SMALL LETTER DZHE: џ => ff ÿ => ÿ From 9830204213d7bfeaac72c75cb7d508d26409bdff Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 27 Jan 2023 10:52:42 +0100 Subject: [PATCH 014/103] Handle non-INDIRECT symbol table entries in zend_fiber_object_gc() (#10386) Fixes GH-10340 --- Zend/tests/fibers/gh10340-001.phpt | 19 +++++++++++++++ Zend/tests/fibers/gh10340-002.phpt | 19 +++++++++++++++ Zend/tests/fibers/gh10340-003.phpt | 38 ++++++++++++++++++++++++++++++ Zend/zend_fibers.c | 6 +++-- 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/fibers/gh10340-001.phpt create mode 100644 Zend/tests/fibers/gh10340-002.phpt create mode 100644 Zend/tests/fibers/gh10340-003.phpt diff --git a/Zend/tests/fibers/gh10340-001.phpt b/Zend/tests/fibers/gh10340-001.phpt new file mode 100644 index 0000000000000..0c34b4a787bce --- /dev/null +++ b/Zend/tests/fibers/gh10340-001.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug GH-10340 001 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); +gc_collect_cycles(); +?> +==DONE== +--EXPECTF-- +Warning: Undefined variable $y in %s on line %d +==DONE== diff --git a/Zend/tests/fibers/gh10340-002.phpt b/Zend/tests/fibers/gh10340-002.phpt new file mode 100644 index 0000000000000..6c8f8016cbf12 --- /dev/null +++ b/Zend/tests/fibers/gh10340-002.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug GH-10340 002 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); +gc_collect_cycles(); +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/tests/fibers/gh10340-003.phpt b/Zend/tests/fibers/gh10340-003.phpt new file mode 100644 index 0000000000000..6e59223a2a9c9 --- /dev/null +++ b/Zend/tests/fibers/gh10340-003.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug GH-10340 003 (Assertion in zend_fiber_object_gc()) +--FILE-- +start(); + +print "1\n"; + +$fiber = null; +gc_collect_cycles(); + +print "2\n"; +?> +==DONE== +--EXPECT-- +1 +C::__destruct +2 +==DONE== diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 432be61e652b9..caa35c61983be 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -656,8 +656,10 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n if (lastSymTable) { zval *val; ZEND_HASH_FOREACH_VAL(lastSymTable, val) { - ZEND_ASSERT(Z_TYPE_P(val) == IS_INDIRECT); - zend_get_gc_buffer_add_zval(buf, Z_INDIRECT_P(val)); + if (EXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) { + val = Z_INDIRECT_P(val); + } + zend_get_gc_buffer_add_zval(buf, val); } ZEND_HASH_FOREACH_END(); } lastSymTable = symTable; From 1173c2e64a52dc95dd9bd220393db5efc50ae6db Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 27 Jan 2023 19:32:25 +0100 Subject: [PATCH 015/103] Prevent dtor of generator in suspended fiber (#10462) Generators that suspended a fiber should not be dtor because they will be executed during the fiber dtor. Fiber dtor throws an exception in the fiber's context in order to unwind and execute finally blocks, which will also properly dtor the generator. Fixes GH-9916 --- Zend/tests/gh9916-001.phpt | 27 ++++++++++++++++++ Zend/tests/gh9916-002.phpt | 21 ++++++++++++++ Zend/tests/gh9916-003.phpt | 36 ++++++++++++++++++++++++ Zend/tests/gh9916-004.phpt | 26 +++++++++++++++++ Zend/tests/gh9916-005.phpt | 25 +++++++++++++++++ Zend/tests/gh9916-006.phpt | 37 +++++++++++++++++++++++++ Zend/tests/gh9916-007.phpt | 57 ++++++++++++++++++++++++++++++++++++++ Zend/tests/gh9916-008.phpt | 47 +++++++++++++++++++++++++++++++ Zend/tests/gh9916-009.phpt | 35 +++++++++++++++++++++++ Zend/tests/gh9916-010.phpt | 34 +++++++++++++++++++++++ Zend/tests/gh9916-011.phpt | 41 +++++++++++++++++++++++++++ Zend/zend_generators.c | 12 +++++++- Zend/zend_generators.h | 1 + 13 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh9916-001.phpt create mode 100644 Zend/tests/gh9916-002.phpt create mode 100644 Zend/tests/gh9916-003.phpt create mode 100644 Zend/tests/gh9916-004.phpt create mode 100644 Zend/tests/gh9916-005.phpt create mode 100644 Zend/tests/gh9916-006.phpt create mode 100644 Zend/tests/gh9916-007.phpt create mode 100644 Zend/tests/gh9916-008.phpt create mode 100644 Zend/tests/gh9916-009.phpt create mode 100644 Zend/tests/gh9916-010.phpt create mode 100644 Zend/tests/gh9916-011.phpt diff --git a/Zend/tests/gh9916-001.phpt b/Zend/tests/gh9916-001.phpt new file mode 100644 index 0000000000000..3e518807238bc --- /dev/null +++ b/Zend/tests/gh9916-001.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug GH-9916 001 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== +Finally diff --git a/Zend/tests/gh9916-002.phpt b/Zend/tests/gh9916-002.phpt new file mode 100644 index 0000000000000..6f0b81cf3e91a --- /dev/null +++ b/Zend/tests/gh9916-002.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug GH-9916 002 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== diff --git a/Zend/tests/gh9916-003.phpt b/Zend/tests/gh9916-003.phpt new file mode 100644 index 0000000000000..c4bfb815118bc --- /dev/null +++ b/Zend/tests/gh9916-003.phpt @@ -0,0 +1,36 @@ +--TEST-- +Bug GH-9916 003 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== +Finally (inner) +Finally diff --git a/Zend/tests/gh9916-004.phpt b/Zend/tests/gh9916-004.phpt new file mode 100644 index 0000000000000..1a51a841e8bb6 --- /dev/null +++ b/Zend/tests/gh9916-004.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug GH-9916 004 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== diff --git a/Zend/tests/gh9916-005.phpt b/Zend/tests/gh9916-005.phpt new file mode 100644 index 0000000000000..f84c756919cd0 --- /dev/null +++ b/Zend/tests/gh9916-005.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug GH-9916 005 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +send($fiber); + $gen->current(); +}); +$fiber->start(); + +$gen = null; +$fiber = null; +gc_collect_cycles(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== diff --git a/Zend/tests/gh9916-006.phpt b/Zend/tests/gh9916-006.phpt new file mode 100644 index 0000000000000..28c57105c7b1f --- /dev/null +++ b/Zend/tests/gh9916-006.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug GH-9916 006 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Fiber return\n"; +}); +$fiber->start(); +$fiber->resume(); +$gen->next(); +$gen->current(); +?> +==DONE== +--EXPECT-- +Before suspend +After suspend +Fiber return +Before exit diff --git a/Zend/tests/gh9916-007.phpt b/Zend/tests/gh9916-007.phpt new file mode 100644 index 0000000000000..e1ec3fb19f32b --- /dev/null +++ b/Zend/tests/gh9916-007.phpt @@ -0,0 +1,57 @@ +--TEST-- +Bug GH-9916 007 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== +Finally (iterator) +Finally diff --git a/Zend/tests/gh9916-008.phpt b/Zend/tests/gh9916-008.phpt new file mode 100644 index 0000000000000..84521d69e2120 --- /dev/null +++ b/Zend/tests/gh9916-008.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug GH-9916 008 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Not executed"; +}); +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before suspend +==DONE== diff --git a/Zend/tests/gh9916-009.phpt b/Zend/tests/gh9916-009.phpt new file mode 100644 index 0000000000000..75643d871dea0 --- /dev/null +++ b/Zend/tests/gh9916-009.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug GH-9916 009 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- + new stdClass]; + print "Not executed\n"; + } +})(); +$fiber = new Fiber(function() use ($gen, &$fiber) { + $gen->current(); + print "Not executed\n"; +}); +$fiber->start(); +?> +==DONE== +--EXPECTF-- +Before suspend +==DONE== +Finally + +Fatal error: Uncaught Error: Cannot use "yield from" in a force-closed generator in %s:%d +Stack trace: +#0 [internal function]: {closure}() +#1 %s(%d): Generator->current() +#2 [internal function]: {closure}() +#3 {main} + thrown in %s on line %d diff --git a/Zend/tests/gh9916-010.phpt b/Zend/tests/gh9916-010.phpt new file mode 100644 index 0000000000000..d3a841d7ceb31 --- /dev/null +++ b/Zend/tests/gh9916-010.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug GH-9916 010 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); + print "Before next\n"; + $gen->next(); + print "Not executed\n"; +}); + +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before current +Before yield +Before yield 2 +Before next +Before suspend +==DONE== diff --git a/Zend/tests/gh9916-011.phpt b/Zend/tests/gh9916-011.phpt new file mode 100644 index 0000000000000..05fa884c29337 --- /dev/null +++ b/Zend/tests/gh9916-011.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug GH-9916 011 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +next(); + } +})(); + +$fiber = new Fiber(function () use ($gen, &$fiber) { + print "Before current\n"; + $gen->current(); + print "Before next\n"; + $gen->next(); + print "Not executed\n"; +}); + +$fiber->start(); +?> +==DONE== +--EXPECT-- +Before current +Before yield +Before yield 2 +Before next +Before suspend +==DONE== diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index d5253e46eddf2..24316dc4e896b 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -223,6 +223,14 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ uint32_t op_num, try_catch_offset; int i; + /* Generator is running in a suspended fiber. + * Will be dtor during fiber dtor */ + if (generator->flags & ZEND_GENERATOR_IN_FIBER) { + /* Prevent finally blocks from yielding */ + generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; + return; + } + /* leave yield from mode to properly allow finally execution */ if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) { zval_ptr_dtor(&generator->values); @@ -727,7 +735,8 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ } /* Resume execution */ - generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; + generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING + | (EG(active_fiber) ? ZEND_GENERATOR_IN_FIBER : 0); if (!ZEND_OBSERVER_ENABLED) { zend_execute_ex(generator->execute_data); } else { @@ -778,6 +787,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ goto try_again; } + generator->flags &= ~ZEND_GENERATOR_IN_FIBER; orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT; } /* }}} */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 17b25a99b87c1..4ccc42b92f668 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -92,6 +92,7 @@ static const zend_uchar ZEND_GENERATOR_CURRENTLY_RUNNING = 0x1; static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2; static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4; static const zend_uchar ZEND_GENERATOR_DO_INIT = 0x8; +static const zend_uchar ZEND_GENERATOR_IN_FIBER = 0x10; void zend_register_generator_ce(void); ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution); From d7de73b551a2499290c2b8afe1d899d00432b706 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 27 Jan 2023 19:33:58 +0100 Subject: [PATCH 016/103] Fix overflow check in OnUpdateMemoryConsumption (#10456) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memsize is a signed long, therefore the check against the (*un*signed long maximum) / 1024² will allow too large values. This check worked correctly in d4b3f89c53f8 where it checked against the maximum signed value, but was broken in 003346c450b5. Fix it by changing ZEND_ULONG_MAX to ZEND_LONG_MAX. --- ext/opcache/zend_accelerator_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index da1696bb92083..2300ee2964bea 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -70,8 +70,8 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n"); return FAILURE; } - if (UNEXPECTED(memsize > ZEND_ULONG_MAX / (1024 * 1024))) { - *p = ZEND_ULONG_MAX; + if (UNEXPECTED(memsize > ZEND_LONG_MAX / (1024 * 1024))) { + *p = ZEND_LONG_MAX; } else { *p = memsize * (1024 * 1024); } From a24ac59e553c0df88bb6acd8f53a4ff8fb944139 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 27 Jan 2023 19:36:28 +0100 Subject: [PATCH 017/103] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index d8028bf92a63c..411201c1acca1 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) . Fixed incorrect check condition in type inference. (nielsdos) + . Fixed overflow check in OnUpdateMemoryConsumption. (nielsdos) + . Fixed bug GH-9916 (Entering shutdown sequence with a fiber suspended in a + Generator emits an unavoidable fatal error or crashes). (Arnaud) - FFI: . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) From 284c29328ee2116c3025482188d2bd880a7f3f37 Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Sat, 28 Jan 2023 10:13:58 -0600 Subject: [PATCH 018/103] Fix GH-10437: Set active fiber to null on bailout (#10443) --- NEWS | 2 ++ Zend/tests/fibers/gh10437.phpt | 18 ++++++++++++++++++ Zend/zend_fibers.c | 1 + 3 files changed, 21 insertions(+) create mode 100644 Zend/tests/fibers/gh10437.phpt diff --git a/NEWS b/NEWS index 411201c1acca1..3583a625cf8cb 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ PHP NEWS . Fixed overflow check in OnUpdateMemoryConsumption. (nielsdos) . Fixed bug GH-9916 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes). (Arnaud) + . Fixed bug GH-10437 (Segfault/assertion when using fibers in shutdown + function after bailout). (trowski) - FFI: . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) diff --git a/Zend/tests/fibers/gh10437.phpt b/Zend/tests/fibers/gh10437.phpt new file mode 100644 index 0000000000000..5c793c986ee29 --- /dev/null +++ b/Zend/tests/fibers/gh10437.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-10437 (Segfault/assertion when using fibers in shutdown function after bailout) +--FILE-- +start(); + +?> +--EXPECTF-- +Fatal error: Bailout in fiber in %sgh10437.php on line %d +NULL diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index caa35c61983be..051a9dceaea7a 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -543,6 +543,7 @@ static zend_always_inline zend_fiber_transfer zend_fiber_switch_to( /* Forward bailout into current fiber. */ if (UNEXPECTED(transfer.flags & ZEND_FIBER_TRANSFER_FLAG_BAILOUT)) { + EG(active_fiber) = NULL; zend_bailout(); } From ec4939b170caca3602c0e1e739c0ab28aa5d5208 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 28 Jan 2023 00:07:35 +0100 Subject: [PATCH 019/103] Fix incorrect check in phar tar parsing The entry.flags was used to check whether the entry has the directory flag. The flags however were masked to only contain the permissions. We need to check the mode, before the permission masking, instead of the flags to check whether it is a directory. Closes GH-10464 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/phar/tar.c | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 3583a625cf8cb..8d7c133fc4a2e 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ PHP NEWS - Opcache: . Fix incorrect page_size check. (nielsdos) +- Phar: + . Fix incorrect check in phar tar parsing. (nielsdos) + - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) diff --git a/ext/phar/tar.c b/ext/phar/tar.c index e56d3e8e3211c..99b6b9812de18 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -478,14 +478,15 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia return FAILURE; } + uint32_t entry_mode = phar_tar_number(hdr->mode, sizeof(hdr->mode)); entry.tar_type = ((old & (hdr->typeflag == '\0')) ? TAR_FILE : hdr->typeflag); entry.offset = entry.offset_abs = pos; /* header_offset unused in tar */ entry.fp_type = PHAR_FP; - entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK; + entry.flags = entry_mode & PHAR_ENT_PERM_MASK; entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime)); entry.is_persistent = myphar->is_persistent; - if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) { + if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry_mode)) { entry.tar_type = TAR_DIR; } From 81607a62ca85d016699e16344a5cebca9edba46a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 30 Jan 2023 13:15:05 +0300 Subject: [PATCH 020/103] Fix type inference Fixes oss-fuzz #55358 --- Zend/Optimizer/zend_inference.c | 18 ++++++++++++-- ext/opcache/tests/jit/assign_obj_op_003.phpt | 26 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/assign_obj_op_003.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index dfb70a3dcabf0..33b01dda038f4 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2537,12 +2537,26 @@ static zend_always_inline int _zend_update_type_info( } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { /* The return value must also satisfy the property type */ if (prop_info) { - tmp &= zend_fetch_prop_type(script, prop_info, NULL); + t1 = zend_fetch_prop_type(script, prop_info, NULL); + if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG + && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) { + /* DOUBLE may be auto-converted to LONG */ + tmp |= MAY_BE_LONG; + tmp &= ~MAY_BE_DOUBLE; + } + tmp &= t1; } } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { /* The return value must also satisfy the property type */ if (prop_info) { - tmp &= zend_fetch_prop_type(script, prop_info, NULL); + t1 = zend_fetch_prop_type(script, prop_info, NULL); + if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG + && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) { + /* DOUBLE may be auto-converted to LONG */ + tmp |= MAY_BE_LONG; + tmp &= ~MAY_BE_DOUBLE; + } + tmp &= t1; } } else { if (tmp & MAY_BE_REF) { diff --git a/ext/opcache/tests/jit/assign_obj_op_003.phpt b/ext/opcache/tests/jit/assign_obj_op_003.phpt new file mode 100644 index 0000000000000..325583e84d912 --- /dev/null +++ b/ext/opcache/tests/jit/assign_obj_op_003.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT ASSIGN_OBJ_OP: invalid type inference +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +bar += 1.3; + } catch(y) { + } + } +} +var_dump(new Foo); +?> +--EXPECTF-- +Deprecated: Implicit conversion from float 1.3 to int loses precision in %sassign_obj_op_003.php on line 6 +object(Foo)#1 (1) { + ["bar"]=> + int(1) +} From b9bca2dadb0d8d554615f944c3fbff6e0750d72d Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 30 Jan 2023 11:59:12 +0100 Subject: [PATCH 021/103] Fix resetting ZEND_GENERATOR_IN_FIBER flag Signed-off-by: Bob Weinand --- Zend/tests/gh9916-012.phpt | 17 +++++++++++++++++ Zend/zend_generators.c | 3 +-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh9916-012.phpt diff --git a/Zend/tests/gh9916-012.phpt b/Zend/tests/gh9916-012.phpt new file mode 100644 index 0000000000000..cd31ea1215b64 --- /dev/null +++ b/Zend/tests/gh9916-012.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug GH-9916 012 (Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes) +--FILE-- +current(); +}); +$fiber->start(); + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 24316dc4e896b..65feafc1b6923 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -747,7 +747,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ zend_observer_fcall_end(generator->execute_data, &generator->value); } } - generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING; + generator->flags &= ~(ZEND_GENERATOR_CURRENTLY_RUNNING | ZEND_GENERATOR_IN_FIBER); generator->frozen_call_stack = NULL; if (EXPECTED(generator->execute_data) && @@ -787,7 +787,6 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ goto try_again; } - generator->flags &= ~ZEND_GENERATOR_IN_FIBER; orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT; } /* }}} */ From 00be6e1aed5e55c04f716a7364ff55e698e154a5 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 30 Jan 2023 12:32:53 +0100 Subject: [PATCH 022/103] Look at executing generator for fiber destructor behaviour --- Zend/tests/fibers/get-return-after-bailout.phpt | 7 +++++++ Zend/tests/generators/gh9801.phpt | 7 +++++++ Zend/zend_generators.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Zend/tests/fibers/get-return-after-bailout.phpt b/Zend/tests/fibers/get-return-after-bailout.phpt index 0f004070251b5..04bd464cfab0e 100644 --- a/Zend/tests/fibers/get-return-after-bailout.phpt +++ b/Zend/tests/fibers/get-return-after-bailout.phpt @@ -1,5 +1,12 @@ --TEST-- Fiber::getReturn() after bailout +--SKIPIF-- + --FILE-- --FILE-- flags & ZEND_GENERATOR_IN_FIBER) { + if (zend_generator_get_current(generator)->flags & ZEND_GENERATOR_IN_FIBER) { /* Prevent finally blocks from yielding */ generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; return; From a42bf93308b159ecda3da01e12b471b13a279d55 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 26 Jan 2023 11:44:07 +0000 Subject: [PATCH 023/103] Fixed GH-10447: 'p' format specifier does not yield 'Z' for 00:00 --- ext/date/php_date.c | 2 +- ext/date/tests/gh10447.phpt | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 ext/date/tests/gh10447.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 0305873eea0e6..fec7d5d03cd63 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -716,7 +716,7 @@ static zend_string *date_format(const char *format, size_t format_len, timelib_t /* timezone */ case 'I': length = slprintf(buffer, sizeof(buffer), "%d", localtime ? offset->is_dst : 0); break; case 'p': - if (!localtime || strcmp(offset->abbr, "UTC") == 0 || strcmp(offset->abbr, "Z") == 0) { + if (!localtime || strcmp(offset->abbr, "UTC") == 0 || strcmp(offset->abbr, "Z") == 0 || strcmp(offset->abbr, "GMT+0000") == 0) { length = slprintf(buffer, sizeof(buffer), "%s", "Z"); break; } diff --git a/ext/date/tests/gh10447.phpt b/ext/date/tests/gh10447.phpt new file mode 100644 index 0000000000000..3b7ff54c97fb5 --- /dev/null +++ b/ext/date/tests/gh10447.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug GH-10447 ('p' format specifier does not yield 'Z' for 00:00) +--FILE-- +format('Y-m-d\TH:i:sp'), "\n"; + +$date = new \DateTimeImmutable('2023-01-25T00:00:00-00:00'); +echo $date->format('Y-m-d\TH:i:sp'), "\n"; +?> +--EXPECT-- +2023-01-25T00:00:00Z +2023-01-25T00:00:00Z From f7e678476f4a01034868ecf225b907235b9e9d8e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 21 Jan 2023 09:13:36 +0100 Subject: [PATCH 024/103] .github/workflows/push.yml: enable ccache This reduces the LINUX_X64_RELEASE_ZTS build time from 9-10 minutes to less than 3 minutes. Closes GH-10395 --- .github/workflows/push.yml | 18 ++++++++++++++++++ .gitignore | 1 + 2 files changed, 19 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 0e29c87e55034..9fc0d05747c45 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -17,6 +17,9 @@ on: pull_request: branches: - '**' +env: + CC: ccache gcc + CXX: ccache g++ jobs: LINUX_X64: strategy: @@ -38,6 +41,13 @@ jobs: uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + # This duplicates the "job.name" expression above because + # GitHub has no way to query the job name (github.job is the + # job id, not the job name) + key: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}-${{hashFiles('main/php_version.h')}}" - name: ./configure uses: ./.github/actions/configure-x64 with: @@ -83,6 +93,10 @@ jobs: uses: actions/checkout@v3 - name: apt uses: ./.github/actions/apt-x32 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" - name: ./configure uses: ./.github/actions/configure-x32 with: @@ -109,6 +123,10 @@ jobs: uses: actions/checkout@v3 - name: brew uses: ./.github/actions/brew + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" - name: ./configure uses: ./.github/actions/configure-macos with: diff --git a/.gitignore b/.gitignore index 1d55b6d9e20da..d455b3485489b 100644 --- a/.gitignore +++ b/.gitignore @@ -281,6 +281,7 @@ tmp-php.ini # GitHub actions cache # ------------------------------------------------------------------------------ /branch-commit-cache.json +/.ccache/ # ------------------------------------------------------------------------------ # Special cases to invert previous ignore patterns From fe2dc2b4810167e08de5dae20f8d914f109c7a81 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 3 Feb 2023 09:17:33 -0500 Subject: [PATCH 025/103] Avoid crash for reset/end/next/prev() on ffi classes (#9711) (And any PECLs returning `zend_empty_array` in the handler->get_properties overrides) Closes GH-9697 This is similar to the fix used in d9651a941915eb5fb5ad557090b65256fd8509b6 for array_walk. This should make it safer for php-src (and PECLs, long-term) to return the empty immutable array in `handler->get_properties` to avoid wasting memory. See https://github.com/php/php-src/issues/9697#issuecomment-1273613175 The only possible internal iterator position for the empty array is at the end of the empty array (nInternalPointer=0). The `zend_hash*del*` helpers will always set nInternalPointer to 0 when an array becomes empty, regardless of previous insertions/deletions/updates to the array. --- NEWS | 2 ++ ext/ffi/tests/arrayPointer.phpt | 20 ++++++++++++++++++++ ext/standard/array.c | 16 ++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 ext/ffi/tests/arrayPointer.phpt diff --git a/NEWS b/NEWS index ca6ee38b7220b..f16e815291a3d 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ PHP NEWS . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) . Fix incorrect check in cs_8559_5 in map_from_unicode(). (nielsdos) + . Fix bug GH-9697 for reset/end/next/prev() attempting to move pointer of + properties table for certain internal classes such as FFI classes 02 Feb 2023, PHP 8.1.15 diff --git a/ext/ffi/tests/arrayPointer.phpt b/ext/ffi/tests/arrayPointer.phpt new file mode 100644 index 0000000000000..3a2b06563ade5 --- /dev/null +++ b/ext/ffi/tests/arrayPointer.phpt @@ -0,0 +1,20 @@ +--TEST-- +FFI: Test deprecated use of array helper functions on FFI classes doesn't crash +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- + +--EXPECTF-- +bool(false) +bool(false) +bool(false) +bool(false) diff --git a/ext/standard/array.c b/ext/standard/array.c index 3b807c739a874..9a814ea07da47 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1073,6 +1073,10 @@ PHP_FUNCTION(end) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); + if (zend_hash_num_elements(array) == 0) { + /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ + RETURN_FALSE; + } zend_hash_internal_pointer_end(array); if (USED_RET()) { @@ -1100,6 +1104,10 @@ PHP_FUNCTION(prev) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); + if (zend_hash_num_elements(array) == 0) { + /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ + RETURN_FALSE; + } zend_hash_move_backwards(array); if (USED_RET()) { @@ -1127,6 +1135,10 @@ PHP_FUNCTION(next) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); + if (zend_hash_num_elements(array) == 0) { + /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ + RETURN_FALSE; + } zend_hash_move_forward(array); if (USED_RET()) { @@ -1154,6 +1166,10 @@ PHP_FUNCTION(reset) ZEND_PARSE_PARAMETERS_END(); HashTable *array = get_ht_for_iap(array_zv, /* separate */ true); + if (zend_hash_num_elements(array) == 0) { + /* array->nInternalPointer is already 0 if the array is empty, even after removing elements */ + RETURN_FALSE; + } zend_hash_internal_pointer_reset(array); if (USED_RET()) { From 4199b72c50031cf16df476bf29f87c4c751b4770 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 14 Jan 2023 16:55:16 +0000 Subject: [PATCH 026/103] Fix GH-10315: FPM unknown child alert not valid This changes the log level for an unknown child during wait as this is not unuasual if FPM master has pid 1 and also possible in some cases for higher pid processes. Based on that and the fact that this is not really a problem, there is just a debug level message emitted for pid 1 and for higher pid a warning is emitted. Closes GH-10319 --- NEWS | 3 +++ sapi/fpm/fpm/fpm_children.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f16e815291a3d..f13e1646df3a7 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ PHP NEWS - FFI: . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) +- FPM: + . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) + - Opcache: . Fix incorrect page_size check. (nielsdos) diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index 6a5787c7ec8d4..2f8e3dc4d0acc 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -297,8 +297,10 @@ void fpm_children_bury(void) break; } } + } else if (fpm_globals.parent_pid == 1) { + zlog(ZLOG_DEBUG, "unknown child (%d) exited %s - most likely an orphan process (master process is the init process)", pid, buf); } else { - zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://github.com/php/php-src/issues).", pid, buf); + zlog(ZLOG_WARNING, "unknown child (%d) exited %s - potentially a bug or pre exec child (e.g. s6-notifyoncheck)", pid, buf); } } } From 5b13e830742a17516963b757bf0ebc00db27586b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 20 Jan 2023 22:17:27 +0100 Subject: [PATCH 027/103] Fix GH-10385: FPM successful config test early exit This introduces an enum `fpm_init_return_status` to propagate the status up to fpm_main. This also makes the code clearer by not using magic integer return numbers. Closes GH-10388 --- NEWS | 1 + sapi/fpm/fpm/fpm.c | 10 +++++----- sapi/fpm/fpm/fpm.h | 8 +++++++- sapi/fpm/fpm/fpm_main.c | 12 +++++++----- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index f13e1646df3a7..2626b2d0a0305 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,7 @@ PHP NEWS - FPM: . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) + . Fixed bug GH-10385 (FPM successful config test early exit). (nielsdos) - Opcache: . Fix incorrect page_size check. (nielsdos) diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c index 30cb9da010bf1..cb86f403b89c9 100644 --- a/sapi/fpm/fpm/fpm.c +++ b/sapi/fpm/fpm/fpm.c @@ -41,7 +41,7 @@ struct fpm_globals_s fpm_globals = { .send_config_pipe = {0, 0}, }; -int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon, int force_stderr) /* {{{ */ +enum fpm_init_return_status fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon, int force_stderr) /* {{{ */ { fpm_globals.argc = argc; fpm_globals.argv = argv; @@ -67,22 +67,22 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int t 0 > fpm_event_init_main()) { if (fpm_globals.test_successful) { - exit(FPM_EXIT_OK); + return FPM_INIT_EXIT_OK; } else { zlog(ZLOG_ERROR, "FPM initialization failed"); - return -1; + return FPM_INIT_ERROR; } } if (0 > fpm_conf_write_pid()) { zlog(ZLOG_ERROR, "FPM initialization failed"); - return -1; + return FPM_INIT_ERROR; } fpm_stdio_init_final(); zlog(ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid); - return 0; + return FPM_INIT_CONTINUE; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h index f0610ca46dc62..ec036a2d68198 100644 --- a/sapi/fpm/fpm/fpm.h +++ b/sapi/fpm/fpm/fpm.h @@ -34,8 +34,14 @@ #endif +enum fpm_init_return_status { + FPM_INIT_ERROR, + FPM_INIT_CONTINUE, + FPM_INIT_EXIT_OK, +}; + int fpm_run(int *max_requests); -int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon, int force_stderr); +enum fpm_init_return_status fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf, int run_as_root, int force_daemon, int force_stderr); struct fpm_globals_s { pid_t parent_pid; diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 5d83ee08af2c7..7cb0a0a33b814 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1532,7 +1532,6 @@ int main(int argc, char *argv[]) int force_stderr = 0; int php_information = 0; int php_allow_to_run_as_root = 0; - int ret; #if ZEND_RC_DEBUG bool old_rc_debug; #endif @@ -1800,21 +1799,24 @@ consult the installation file that came with this distribution, or visit \n\ zend_rc_debug = 0; #endif - ret = fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf, php_allow_to_run_as_root, force_daemon, force_stderr); + enum fpm_init_return_status ret = fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf, php_allow_to_run_as_root, force_daemon, force_stderr); #if ZEND_RC_DEBUG zend_rc_debug = old_rc_debug; #endif - if (ret < 0) { - + if (ret == FPM_INIT_ERROR) { if (fpm_globals.send_config_pipe[1]) { int writeval = 0; zlog(ZLOG_DEBUG, "Sending \"0\" (error) to parent via fd=%d", fpm_globals.send_config_pipe[1]); zend_quiet_write(fpm_globals.send_config_pipe[1], &writeval, sizeof(writeval)); close(fpm_globals.send_config_pipe[1]); } - return FPM_EXIT_CONFIG; + exit_status = FPM_EXIT_CONFIG; + goto out; + } else if (ret == FPM_INIT_EXIT_OK) { + exit_status = FPM_EXIT_OK; + goto out; } if (fpm_globals.send_config_pipe[1]) { From 49551d7c29ea2b4ebf904cd5a03e16f1b9f66634 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 21 Jan 2023 20:49:31 +0100 Subject: [PATCH 028/103] Sync boost/context assembly files for fibers Fixes GH-10398 The stack was misaligned upon entering the trampoline function [1], this causes a CPU trap when the SSE instruction is executed to copy data from the stack. This was fixed upstream [2]. This commit syncs all upstream changes from the boost/context assembly files to our copy. [1] https://github.com/php/php-src/pull/10407#issuecomment-1404180877 [2] https://github.com/boostorg/context/pull/219 Closes GH-10407. --- NEWS | 3 + Zend/asm/jump_i386_sysv_elf_gas.S | 44 ++++--- Zend/asm/jump_ppc32_sysv_macho_gas.S | 184 +++++++++++++-------------- Zend/asm/jump_ppc64_sysv_macho_gas.S | 18 +-- Zend/asm/jump_x86_64_sysv_elf_gas.S | 79 +++++++++--- Zend/asm/make_i386_sysv_elf_gas.S | 26 ++-- Zend/asm/make_i386_sysv_macho_gas.S | 4 +- Zend/asm/make_ppc32_sysv_macho_gas.S | 83 +++++++----- Zend/asm/make_ppc64_sysv_macho_gas.S | 16 +-- Zend/asm/make_x86_64_sysv_elf_gas.S | 71 ++++++++++- 10 files changed, 333 insertions(+), 195 deletions(-) diff --git a/NEWS b/NEWS index 2626b2d0a0305..ea21713af4c31 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ PHP NEWS - FFI: . Fixed incorrect bitshifting and masking in ffi bitfield. (nielsdos) +- Fiber: + . Fixed assembly on alpine x86. (nielsdos) + - FPM: . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) . Fixed bug GH-10385 (FPM successful config test early exit). (nielsdos) diff --git a/Zend/asm/jump_i386_sysv_elf_gas.S b/Zend/asm/jump_i386_sysv_elf_gas.S index b96d4b5c0e70e..47be9e77822e0 100644 --- a/Zend/asm/jump_i386_sysv_elf_gas.S +++ b/Zend/asm/jump_i386_sysv_elf_gas.S @@ -12,14 +12,14 @@ * ---------------------------------------------------------------------------------- * * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | * + * | fc_mxcsr|fc_x87_cw| guard | EDI | ESI | EBX | EBP | EIP | * * ---------------------------------------------------------------------------------- * * ---------------------------------------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * * ---------------------------------------------------------------------------------- * - * | 0x20 | 0x24 | | * + * | 0x20 | 0x24 | 0x28 | | * * ---------------------------------------------------------------------------------- * - * | to | data | | * + * | hidden | to | data | | * * ---------------------------------------------------------------------------------- * * * ****************************************************************************************/ @@ -30,50 +30,60 @@ .align 2 .type jump_fcontext,@function jump_fcontext: - leal -0x18(%esp), %esp /* prepare stack */ + leal -0x1c(%esp), %esp /* prepare stack */ #if !defined(BOOST_USE_TSX) stmxcsr (%esp) /* save MMX control- and status-word */ fnstcw 0x4(%esp) /* save x87 control-word */ #endif - movl %edi, 0x8(%esp) /* save EDI */ - movl %esi, 0xc(%esp) /* save ESI */ - movl %ebx, 0x10(%esp) /* save EBX */ - movl %ebp, 0x14(%esp) /* save EBP */ +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + movl %gs:0x14, %ecx /* read stack guard from TLS record */ + movl %ecx, 0x8(%esp) /* save stack guard */ +#endif + + movl %edi, 0xc(%esp) /* save EDI */ + movl %esi, 0x10(%esp) /* save ESI */ + movl %ebx, 0x14(%esp) /* save EBX */ + movl %ebp, 0x18(%esp) /* save EBP */ /* store ESP (pointing to context-data) in ECX */ movl %esp, %ecx /* first arg of jump_fcontext() == fcontext to jump to */ - movl 0x20(%esp), %eax + movl 0x24(%esp), %eax /* second arg of jump_fcontext() == data to be transferred */ - movl 0x24(%esp), %edx + movl 0x28(%esp), %edx /* restore ESP (pointing to context-data) from EAX */ movl %eax, %esp /* address of returned transport_t */ - movl 0x1c(%esp), %eax + movl 0x20(%esp), %eax /* return parent fcontext_t */ movl %ecx, (%eax) /* return data */ movl %edx, 0x4(%eax) - movl 0x18(%esp), %ecx /* restore EIP */ + movl 0x1c(%esp), %ecx /* restore EIP */ #if !defined(BOOST_USE_TSX) ldmxcsr (%esp) /* restore MMX control- and status-word */ fldcw 0x4(%esp) /* restore x87 control-word */ #endif - movl 0x8(%esp), %edi /* restore EDI */ - movl 0xc(%esp), %esi /* restore ESI */ - movl 0x10(%esp), %ebx /* restore EBX */ - movl 0x14(%esp), %ebp /* restore EBP */ +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + movl 0x8(%esp), %edx /* load stack guard */ + movl %edx, %gs:0x14 /* restore stack guard to TLS record */ +#endif + + movl 0xc(%esp), %edi /* restore EDI */ + movl 0x10(%esp), %esi /* restore ESI */ + movl 0x14(%esp), %ebx /* restore EBX */ + movl 0x18(%esp), %ebp /* restore EBP */ - leal 0x20(%esp), %esp /* prepare stack */ + leal 0x24(%esp), %esp /* prepare stack */ /* jump to context */ jmp *%ecx diff --git a/Zend/asm/jump_ppc32_sysv_macho_gas.S b/Zend/asm/jump_ppc32_sysv_macho_gas.S index c555237afa2e9..fef90c295f8c9 100644 --- a/Zend/asm/jump_ppc32_sysv_macho_gas.S +++ b/Zend/asm/jump_ppc32_sysv_macho_gas.S @@ -80,122 +80,122 @@ _jump_fcontext: ; reserve space on stack subi r1, r1, 244 - stfd f14, 0(r1) # save F14 - stfd f15, 8(r1) # save F15 - stfd f16, 16(r1) # save F16 - stfd f17, 24(r1) # save F17 - stfd f18, 32(r1) # save F18 - stfd f19, 40(r1) # save F19 - stfd f20, 48(r1) # save F20 - stfd f21, 56(r1) # save F21 - stfd f22, 64(r1) # save F22 - stfd f23, 72(r1) # save F23 - stfd f24, 80(r1) # save F24 - stfd f25, 88(r1) # save F25 - stfd f26, 96(r1) # save F26 - stfd f27, 104(r1) # save F27 - stfd f28, 112(r1) # save F28 - stfd f29, 120(r1) # save F29 - stfd f30, 128(r1) # save F30 - stfd f31, 136(r1) # save F31 - mffs f0 # load FPSCR - stfd f0, 144(r1) # save FPSCR + stfd f14, 0(r1) ; save F14 + stfd f15, 8(r1) ; save F15 + stfd f16, 16(r1) ; save F16 + stfd f17, 24(r1) ; save F17 + stfd f18, 32(r1) ; save F18 + stfd f19, 40(r1) ; save F19 + stfd f20, 48(r1) ; save F20 + stfd f21, 56(r1) ; save F21 + stfd f22, 64(r1) ; save F22 + stfd f23, 72(r1) ; save F23 + stfd f24, 80(r1) ; save F24 + stfd f25, 88(r1) ; save F25 + stfd f26, 96(r1) ; save F26 + stfd f27, 104(r1) ; save F27 + stfd f28, 112(r1) ; save F28 + stfd f29, 120(r1) ; save F29 + stfd f30, 128(r1) ; save F30 + stfd f31, 136(r1) ; save F31 + mffs f0 ; load FPSCR + stfd f0, 144(r1) ; save FPSCR - stw r13, 152(r1) # save R13 - stw r14, 156(r1) # save R14 - stw r15, 160(r1) # save R15 - stw r16, 164(r1) # save R16 - stw r17, 168(r1) # save R17 - stw r18, 172(r1) # save R18 - stw r19, 176(r1) # save R19 - stw r20, 180(r1) # save R20 - stw r21, 184(r1) # save R21 - stw r22, 188(r1) # save R22 - stw r23, 192(r1) # save R23 - stw r24, 196(r1) # save R24 - stw r25, 200(r1) # save R25 - stw r26, 204(r1) # save R26 - stw r27, 208(r1) # save R27 - stw r28, 212(r1) # save R28 - stw r29, 216(r1) # save R29 - stw r30, 220(r1) # save R30 - stw r31, 224(r1) # save R31 - stw r3, 228(r1) # save hidden + stw r13, 152(r1) ; save R13 + stw r14, 156(r1) ; save R14 + stw r15, 160(r1) ; save R15 + stw r16, 164(r1) ; save R16 + stw r17, 168(r1) ; save R17 + stw r18, 172(r1) ; save R18 + stw r19, 176(r1) ; save R19 + stw r20, 180(r1) ; save R20 + stw r21, 184(r1) ; save R21 + stw r22, 188(r1) ; save R22 + stw r23, 192(r1) ; save R23 + stw r24, 196(r1) ; save R24 + stw r25, 200(r1) ; save R25 + stw r26, 204(r1) ; save R26 + stw r27, 208(r1) ; save R27 + stw r28, 212(r1) ; save R28 + stw r29, 216(r1) ; save R29 + stw r30, 220(r1) ; save R30 + stw r31, 224(r1) ; save R31 + stw r3, 228(r1) ; save hidden - # save CR + ; save CR mfcr r0 stw r0, 232(r1) - # save LR + ; save LR mflr r0 stw r0, 236(r1) - # save LR as PC + ; save LR as PC stw r0, 240(r1) - # store RSP (pointing to context-data) in R6 + ; store RSP (pointing to context-data) in R6 mr r6, r1 - # restore RSP (pointing to context-data) from R4 + ; restore RSP (pointing to context-data) from R4 mr r1, r4 - lfd f14, 0(r1) # restore F14 - lfd f15, 8(r1) # restore F15 - lfd f16, 16(r1) # restore F16 - lfd f17, 24(r1) # restore F17 - lfd f18, 32(r1) # restore F18 - lfd f19, 40(r1) # restore F19 - lfd f20, 48(r1) # restore F20 - lfd f21, 56(r1) # restore F21 - lfd f22, 64(r1) # restore F22 - lfd f23, 72(r1) # restore F23 - lfd f24, 80(r1) # restore F24 - lfd f25, 88(r1) # restore F25 - lfd f26, 96(r1) # restore F26 - lfd f27, 104(r1) # restore F27 - lfd f28, 112(r1) # restore F28 - lfd f29, 120(r1) # restore F29 - lfd f30, 128(r1) # restore F30 - lfd f31, 136(r1) # restore F31 - lfd f0, 144(r1) # load FPSCR - mtfsf 0xff, f0 # restore FPSCR + lfd f14, 0(r1) ; restore F14 + lfd f15, 8(r1) ; restore F15 + lfd f16, 16(r1) ; restore F16 + lfd f17, 24(r1) ; restore F17 + lfd f18, 32(r1) ; restore F18 + lfd f19, 40(r1) ; restore F19 + lfd f20, 48(r1) ; restore F20 + lfd f21, 56(r1) ; restore F21 + lfd f22, 64(r1) ; restore F22 + lfd f23, 72(r1) ; restore F23 + lfd f24, 80(r1) ; restore F24 + lfd f25, 88(r1) ; restore F25 + lfd f26, 96(r1) ; restore F26 + lfd f27, 104(r1) ; restore F27 + lfd f28, 112(r1) ; restore F28 + lfd f29, 120(r1) ; restore F29 + lfd f30, 128(r1) ; restore F30 + lfd f31, 136(r1) ; restore F31 + lfd f0, 144(r1) ; load FPSCR + mtfsf 0xff, f0 ; restore FPSCR - lwz r13, 152(r1) # restore R13 - lwz r14, 156(r1) # restore R14 - lwz r15, 160(r1) # restore R15 - lwz r16, 164(r1) # restore R16 - lwz r17, 168(r1) # restore R17 - lwz r18, 172(r1) # restore R18 - lwz r19, 176(r1) # restore R19 - lwz r20, 180(r1) # restore R20 - lwz r21, 184(r1) # restore R21 - lwz r22, 188(r1) # restore R22 - lwz r23, 192(r1) # restore R23 - lwz r24, 196(r1) # restore R24 - lwz r25, 200(r1) # restore R25 - lwz r26, 204(r1) # restore R26 - lwz r27, 208(r1) # restore R27 - lwz r28, 212(r1) # restore R28 - lwz r29, 216(r1) # restore R29 - lwz r30, 220(r1) # restore R30 - lwz r31, 224(r1) # restore R31 - lwz r3, 228(r1) # restore hidden + lwz r13, 152(r1) ; restore R13 + lwz r14, 156(r1) ; restore R14 + lwz r15, 160(r1) ; restore R15 + lwz r16, 164(r1) ; restore R16 + lwz r17, 168(r1) ; restore R17 + lwz r18, 172(r1) ; restore R18 + lwz r19, 176(r1) ; restore R19 + lwz r20, 180(r1) ; restore R20 + lwz r21, 184(r1) ; restore R21 + lwz r22, 188(r1) ; restore R22 + lwz r23, 192(r1) ; restore R23 + lwz r24, 196(r1) ; restore R24 + lwz r25, 200(r1) ; restore R25 + lwz r26, 204(r1) ; restore R26 + lwz r27, 208(r1) ; restore R27 + lwz r28, 212(r1) ; restore R28 + lwz r29, 216(r1) ; restore R29 + lwz r30, 220(r1) ; restore R30 + lwz r31, 224(r1) ; restore R31 + lwz r3, 228(r1) ; restore hidden - # restore CR + ; restore CR lwz r0, 232(r1) mtcr r0 - # restore LR + ; restore LR lwz r0, 236(r1) mtlr r0 - # load PC + ; load PC lwz r0, 240(r1) - # restore CTR + ; restore CTR mtctr r0 - # adjust stack + ; adjust stack addi r1, r1, 244 - # return transfer_t + ; return transfer_t stw r6, 0(r3) stw r5, 4(r3) - # jump to context + ; jump to context bctr diff --git a/Zend/asm/jump_ppc64_sysv_macho_gas.S b/Zend/asm/jump_ppc64_sysv_macho_gas.S index 74fcb2ab3528f..dcc6c645db619 100644 --- a/Zend/asm/jump_ppc64_sysv_macho_gas.S +++ b/Zend/asm/jump_ppc64_sysv_macho_gas.S @@ -12,7 +12,7 @@ * ------------------------------------------------- * * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | * * ------------------------------------------------- * - * | TOC | R14 | R15 | R16 | * + * | R13 | R14 | R15 | R16 | * * ------------------------------------------------- * * ------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * @@ -61,7 +61,7 @@ * ------------------------------------------------- * * | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | * * ------------------------------------------------- * - * | TOC saved | FCTX | DATA | | * + * | FCTX | DATA | | | * * ------------------------------------------------- * * * *******************************************************/ @@ -138,27 +138,27 @@ _jump_fcontext: ; load PC ld r12, 176(r1) - # restore CTR + ; restore CTR mtctr r12 - # adjust stack + ; adjust stack addi r1, r1, 184 - # zero in r3 indicates first jump to context-function + ; zero in r3 indicates first jump to context-function cmpdi r3, 0 beq use_entry_arg - # return transfer_t + ; return transfer_t std r6, 0(r3) std r5, 8(r3) - # jump to context + ; jump to context bctr use_entry_arg: - # copy transfer_t into transfer_fn arg registers + ; copy transfer_t into transfer_fn arg registers mr r3, r6 mr r4, r5 - # jump to context + ; jump to context bctr diff --git a/Zend/asm/jump_x86_64_sysv_elf_gas.S b/Zend/asm/jump_x86_64_sysv_elf_gas.S index c675c8c774c23..58f0e241d70ff 100644 --- a/Zend/asm/jump_x86_64_sysv_elf_gas.S +++ b/Zend/asm/jump_x86_64_sysv_elf_gas.S @@ -12,20 +12,29 @@ * ---------------------------------------------------------------------------------- * * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * + * | fc_mxcsr|fc_x87_cw| guard | R12 | R13 | * * ---------------------------------------------------------------------------------- * * ---------------------------------------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * * ---------------------------------------------------------------------------------- * * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * * ---------------------------------------------------------------------------------- * - * | R15 | RBX | RBP | RIP | * + * | R14 | R15 | RBX | RBP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | | * + * ---------------------------------------------------------------------------------- * + * | RIP | | * * ---------------------------------------------------------------------------------- * * * ****************************************************************************************/ # if defined __CET__ # include +# define SHSTK_ENABLED (__CET__ & 0x2) +# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) # else # define _CET_ENDBR # endif @@ -36,19 +45,32 @@ .align 16 jump_fcontext: _CET_ENDBR - leaq -0x38(%rsp), %rsp /* prepare stack */ + leaq -0x40(%rsp), %rsp /* prepare stack */ #if !defined(BOOST_USE_TSX) stmxcsr (%rsp) /* save MMX control- and status-word */ fnstcw 0x4(%rsp) /* save x87 control-word */ #endif - movq %r12, 0x8(%rsp) /* save R12 */ - movq %r13, 0x10(%rsp) /* save R13 */ - movq %r14, 0x18(%rsp) /* save R14 */ - movq %r15, 0x20(%rsp) /* save R15 */ - movq %rbx, 0x28(%rsp) /* save RBX */ - movq %rbp, 0x30(%rsp) /* save RBP */ +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + movq %fs:0x28, %rcx /* read stack guard from TLS record */ + movq %rcx, 0x8(%rsp) /* save stack guard */ +#endif + + movq %r12, 0x10(%rsp) /* save R12 */ + movq %r13, 0x18(%rsp) /* save R13 */ + movq %r14, 0x20(%rsp) /* save R14 */ + movq %r15, 0x28(%rsp) /* save R15 */ + movq %rbx, 0x30(%rsp) /* save RBX */ + movq %rbp, 0x38(%rsp) /* save RBP */ + +#if BOOST_CONTEXT_SHADOW_STACK + /* grow the stack to reserve space for shadow stack pointer(SSP) */ + leaq -0x8(%rsp), %rsp + /* read the current SSP and store it */ + rdsspq %rcx + movq %rcx, (%rsp) +#endif /* store RSP (pointing to context-data) in RAX */ movq %rsp, %rax @@ -56,21 +78,44 @@ jump_fcontext: /* restore RSP (pointing to context-data) from RDI */ movq %rdi, %rsp - movq 0x38(%rsp), %r8 /* restore return-address */ +#if BOOST_CONTEXT_SHADOW_STACK + /* first 8 bytes are SSP */ + movq (%rsp), %rcx + leaq 0x8(%rsp), %rsp + + /* Restore target(new) shadow stack */ + rstorssp -8(%rcx) + /* restore token for previous shadow stack is pushed */ + /* on previous shadow stack after saveprevssp */ + saveprevssp + + /* when return, jump_fcontext jump to restored return address */ + /* (r8) instead of RET. This miss of RET implies us to unwind */ + /* shadow stack accordingly. Otherwise mismatch occur */ + movq $1, %rcx + incsspq %rcx +#endif + + movq 0x40(%rsp), %r8 /* restore return-address */ #if !defined(BOOST_USE_TSX) ldmxcsr (%rsp) /* restore MMX control- and status-word */ fldcw 0x4(%rsp) /* restore x87 control-word */ #endif - movq 0x8(%rsp), %r12 /* restore R12 */ - movq 0x10(%rsp), %r13 /* restore R13 */ - movq 0x18(%rsp), %r14 /* restore R14 */ - movq 0x20(%rsp), %r15 /* restore R15 */ - movq 0x28(%rsp), %rbx /* restore RBX */ - movq 0x30(%rsp), %rbp /* restore RBP */ +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + movq 0x8(%rsp), %rdx /* load stack guard */ + movq %rdx, %fs:0x28 /* restore stack guard to TLS record */ +#endif + + movq 0x10(%rsp), %r12 /* restore R12 */ + movq 0x18(%rsp), %r13 /* restore R13 */ + movq 0x20(%rsp), %r14 /* restore R14 */ + movq 0x28(%rsp), %r15 /* restore R15 */ + movq 0x30(%rsp), %rbx /* restore RBX */ + movq 0x38(%rsp), %rbp /* restore RBP */ - leaq 0x40(%rsp), %rsp /* prepare stack */ + leaq 0x48(%rsp), %rsp /* prepare stack */ /* return transfer_t from jump */ #if !defined(_ILP32) diff --git a/Zend/asm/make_i386_sysv_elf_gas.S b/Zend/asm/make_i386_sysv_elf_gas.S index b76de260d211f..9261e566c0d45 100644 --- a/Zend/asm/make_i386_sysv_elf_gas.S +++ b/Zend/asm/make_i386_sysv_elf_gas.S @@ -12,14 +12,14 @@ * ---------------------------------------------------------------------------------- * * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | * + * | fc_mxcsr|fc_x87_cw| guard | EDI | ESI | EBX | EBP | EIP | * * ---------------------------------------------------------------------------------- * * ---------------------------------------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * * ---------------------------------------------------------------------------------- * - * | 0x20 | 0x24 | | * + * | 0x20 | 0x24 | 0x28 | | * * ---------------------------------------------------------------------------------- * - * | to | data | | * + * | hidden | to | data | | * * ---------------------------------------------------------------------------------- * * * ****************************************************************************************/ @@ -40,23 +40,29 @@ make_fcontext: /* shift address in EAX to lower 16 byte boundary */ andl $-16, %eax - /* reserve space for context-data on context-stack */ - leal -0x28(%eax), %eax + /* reserve space for context-data on context-stack, and align the stack */ + leal -0x34(%eax), %eax /* third arg of make_fcontext() == address of context-function */ /* stored in EBX */ movl 0xc(%esp), %ecx - movl %ecx, 0x10(%eax) + movl %ecx, 0x14(%eax) /* save MMX control- and status-word */ stmxcsr (%eax) /* save x87 control-word */ fnstcw 0x4(%eax) +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + /* save stack guard */ + movl %gs:0x14, %ecx /* read stack guard from TLS record */ + movl %ecx, 0x8(%eax) /* save stack guard */ +#endif + /* return transport_t */ /* FCTX == EDI, DATA == ESI */ - leal 0x8(%eax), %ecx - movl %ecx, 0x1c(%eax) + leal 0xc(%eax), %ecx + movl %ecx, 0x20(%eax) /* compute abs address of label trampoline */ call 1f @@ -66,7 +72,7 @@ make_fcontext: addl $trampoline-1b, %ecx /* save address of trampoline as return address */ /* will be entered after calling jump_fcontext() first time */ - movl %ecx, 0x18(%eax) + movl %ecx, 0x1c(%eax) /* compute abs address of label finish */ call 2f @@ -76,7 +82,7 @@ make_fcontext: addl $finish-2b, %ecx /* save address of finish as return-address for context-function */ /* will be entered after context-function returns */ - movl %ecx, 0x14(%eax) + movl %ecx, 0x18(%eax) ret /* return pointer to context-data */ diff --git a/Zend/asm/make_i386_sysv_macho_gas.S b/Zend/asm/make_i386_sysv_macho_gas.S index fdcdb7c80fbff..519e406248bb2 100644 --- a/Zend/asm/make_i386_sysv_macho_gas.S +++ b/Zend/asm/make_i386_sysv_macho_gas.S @@ -38,8 +38,8 @@ _make_fcontext: /* shift address in EAX to lower 16 byte boundary */ andl $-16, %eax - /* reserve space for context-data on context-stack */ - leal -0x2c(%eax), %eax + /* reserve space for context-data on context-stack, and align the stack */ + leal -0x34(%eax), %eax /* third arg of make_fcontext() == address of context-function */ /* stored in EBX */ diff --git a/Zend/asm/make_ppc32_sysv_macho_gas.S b/Zend/asm/make_ppc32_sysv_macho_gas.S index 8f35eff9abbff..1102ee90ef076 100644 --- a/Zend/asm/make_ppc32_sysv_macho_gas.S +++ b/Zend/asm/make_ppc32_sysv_macho_gas.S @@ -77,61 +77,78 @@ .globl _make_fcontext .align 2 _make_fcontext: - # save return address into R6 + ; save return address into R6 mflr r6 - # first arg of make_fcontext() == top address of context-function - # shift address in R3 to lower 16 byte boundary + ; first arg of make_fcontext() == top address of context-function + ; shift address in R3 to lower 16 byte boundary clrrwi r3, r3, 4 - # reserve space for context-data on context-stack - # including 64 byte of linkage + parameter area (R1 16 == 0) + ; reserve space for context-data on context-stack + ; including 64 byte of linkage + parameter area (R1 % 16 == 0) subi r3, r3, 336 - # third arg of make_fcontext() == address of context-function - stw r5, 240(r3) + ; third arg of make_fcontext() == address of context-function + ; store as trampoline's R31 + stw r5, 224(r3) - # set back-chain to zero + ; set back-chain to zero li r0, 0 stw r0, 244(r3) - mffs f0 # load FPSCR - stfd f0, 144(r3) # save FPSCR + mffs f0 ; load FPSCR + stfd f0, 144(r3) ; save FPSCR - # compute address of returned transfer_t + ; compute address of returned transfer_t addi r0, r3, 252 mr r4, r0 stw r4, 228(r3) - # load LR + ; load LR mflr r0 - # jump to label 1 - bl 1f -1: - # load LR into R4 + ; jump to label 1 + bcl 20, 31, L1 +L1: + ; load LR into R4 mflr r4 - # compute abs address of label finish - addi r4, r4, finish - 1b - # restore LR + ; compute abs address of trampoline, use as PC + addi r5, r4, lo16(Ltrampoline - L1) + stw r5, 240(r3) + ; compute abs address of label finish + addi r4, r4, lo16(Lfinish - L1) + ; restore LR mtlr r0 - # save address of finish as return-address for context-function - # will be entered after context-function returns + ; save address of finish as return-address for context-function + ; will be entered after context-function returns stw r4, 236(r3) - # restore return address from R6 + ; restore return address from R6 mtlr r6 - blr # return pointer to context-data + blr ; return pointer to context-data -finish: - # save return address into R0 - mflr r0 - # save return address on stack, set up stack frame - stw r0, 4(r1) - # allocate stack space, R1 16 == 0 - stwu r1, -16(r1) +Ltrampoline: + ; We get R31 = context-function, R3 = address of transfer_t, + ; but we need to pass R3:R4 = transfer_t. + mtctr r31 + lwz r4, 4(r3) + lwz r3, 0(r3) + bctr - # exit code is zero +Lfinish: + ; load address of _exit into CTR + bcl 20, 31, L2 +L2: + mflr r4 + addis r4, r4, ha16(Lexitp - L2) + lwz r4, lo16(Lexitp - L2)(r4) + mtctr r4 + ; exit code is zero li r3, 0 - # exit application - bl _exit@plt + ; exit application + bctr + +.const_data +.align 2 +Lexitp: + .long __exit diff --git a/Zend/asm/make_ppc64_sysv_macho_gas.S b/Zend/asm/make_ppc64_sysv_macho_gas.S index 7b947bb6b030b..fb5cada265a64 100644 --- a/Zend/asm/make_ppc64_sysv_macho_gas.S +++ b/Zend/asm/make_ppc64_sysv_macho_gas.S @@ -12,7 +12,7 @@ * ------------------------------------------------- * * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | * * ------------------------------------------------- * - * | TOC | R14 | R15 | R16 | * + * | R13 | R14 | R15 | R16 | * * ------------------------------------------------- * * ------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * @@ -61,7 +61,7 @@ * ------------------------------------------------- * * | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | * * ------------------------------------------------- * - * | TOC saved | FCTX | DATA | | * + * | FCTX | DATA | | | * * ------------------------------------------------- * * * @@ -77,19 +77,19 @@ _make_fcontext: ; reserve space for context-data on context-stack ; including 64 byte of linkage + parameter area (R1 16 == 0) - subi r3, r3, 248 + subi r3, r3, 240 ; third arg of make_fcontext() == address of context-function stw r5, 176(r3) ; set back-chain to zero - li %r0, 0 - std %r0, 184(%r3) + li r0, 0 + std r0, 184(r3) ; compute address of returned transfer_t - addi %r0, %r3, 232 - mr %r4, %r0 - std %r4, 152(%r3) + addi r0, r3, 224 + mr r4, r0 + std r4, 152(r3) ; load LR mflr r0 diff --git a/Zend/asm/make_x86_64_sysv_elf_gas.S b/Zend/asm/make_x86_64_sysv_elf_gas.S index d422c6972df9c..4294398a2edc2 100644 --- a/Zend/asm/make_x86_64_sysv_elf_gas.S +++ b/Zend/asm/make_x86_64_sysv_elf_gas.S @@ -12,20 +12,29 @@ * ---------------------------------------------------------------------------------- * * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | * + * | fc_mxcsr|fc_x87_cw| guard | R12 | R13 | * * ---------------------------------------------------------------------------------- * * ---------------------------------------------------------------------------------- * * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * * ---------------------------------------------------------------------------------- * * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * * ---------------------------------------------------------------------------------- * - * | R15 | RBX | RBP | RIP | * + * | R14 | R15 | RBX | RBP | * + * ---------------------------------------------------------------------------------- * + * ---------------------------------------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ---------------------------------------------------------------------------------- * + * | 0x40 | 0x44 | | * + * ---------------------------------------------------------------------------------- * + * | RIP | | * * ---------------------------------------------------------------------------------- * * * ****************************************************************************************/ # if defined __CET__ # include +# define SHSTK_ENABLED (__CET__ & 0x2) +# define BOOST_CONTEXT_SHADOW_STACK (SHSTK_ENABLED && SHADOW_STACK_SYSCALL) # else # define _CET_ENDBR # endif @@ -36,6 +45,11 @@ .align 16 make_fcontext: _CET_ENDBR +#if BOOST_CONTEXT_SHADOW_STACK + /* the new shadow stack pointer (SSP) */ + movq -0x8(%rdi), %r9 +#endif + /* first arg of make_fcontext() == top of context-stack */ movq %rdi, %rax @@ -44,36 +58,79 @@ make_fcontext: /* reserve space for context-data on context-stack */ /* on context-function entry: (RSP -0x8) % 16 == 0 */ - leaq -0x40(%rax), %rax + leaq -0x48(%rax), %rax /* third arg of make_fcontext() == address of context-function */ /* stored in RBX */ - movq %rdx, 0x28(%rax) + movq %rdx, 0x30(%rax) /* save MMX control- and status-word */ stmxcsr (%rax) /* save x87 control-word */ fnstcw 0x4(%rax) +#if defined(BOOST_CONTEXT_TLS_STACK_PROTECTOR) + /* save stack guard */ + movq %fs:0x28, %rcx /* read stack guard from TLS record */ + movq %rcx, 0x8(%rsp) /* save stack guard */ +#endif + /* compute abs address of label trampoline */ leaq trampoline(%rip), %rcx /* save address of trampoline as return-address for context-function */ /* will be entered after calling jump_fcontext() first time */ - movq %rcx, 0x38(%rax) + movq %rcx, 0x40(%rax) /* compute abs address of label finish */ leaq finish(%rip), %rcx /* save address of finish as return-address for context-function */ /* will be entered after context-function returns */ - movq %rcx, 0x30(%rax) + movq %rcx, 0x38(%rax) + +#if BOOST_CONTEXT_SHADOW_STACK + /* Populate the shadow stack and normal stack */ + /* get original SSP */ + rdsspq %r8 + /* restore new shadow stack */ + rstorssp -0x8(%r9) + /* save the restore token on the original shadow stack */ + saveprevssp + /* push the address of "jmp trampoline" to the new shadow stack */ + /* as well as the stack */ + call 1f + jmp trampoline +1: + /* save address of "jmp trampoline" as return-address */ + /* for context-function */ + pop 0x38(%rax) + /* Get the new SSP. */ + rdsspq %r9 + /* restore original shadow stack */ + rstorssp -0x8(%r8) + /* save the restore token on the new shadow stack. */ + saveprevssp + + /* reserve space for the new SSP */ + leaq -0x8(%rax), %rax + /* save the new SSP to this fcontext */ + movq %r9, (%rax) +#endif ret /* return pointer to context-data */ trampoline: + _CET_ENDBR /* store return address on stack */ /* fix stack alignment */ - _CET_ENDBR +#if BOOST_CONTEXT_SHADOW_STACK + /* save address of "jmp *%rbp" as return-address */ + /* on stack and shadow stack */ + call 2f + jmp *%rbp +2: +#else push %rbp +#endif /* jump to context-function */ jmp *%rbx From a21195650e53e34266806a8c379dd5a91f0dbb61 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 6 Feb 2023 18:35:06 +0300 Subject: [PATCH 029/103] Fix possible exit_counters memory leak in ZTS build --- ext/opcache/jit/zend_jit.c | 15 +++++++++++---- ext/opcache/jit/zend_jit_trace.c | 7 +++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 28404f2d2bdf0..b58614e50311e 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4759,6 +4759,13 @@ static void zend_jit_globals_ctor(zend_jit_globals *jit_globals) zend_jit_trace_init_caches(); } +#ifdef ZTS +static void zend_jit_globals_dtor(zend_jit_globals *jit_globals) +{ + zend_jit_trace_free_caches(); +} +#endif + static int zend_jit_parse_config_num(zend_long jit) { if (jit == 0) { @@ -4871,7 +4878,7 @@ ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int ZEND_EXT_API void zend_jit_init(void) { #ifdef ZTS - jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, NULL); + jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, zend_jit_globals_dtor); #else zend_jit_globals_ctor(&jit_globals); #endif @@ -5071,9 +5078,9 @@ ZEND_EXT_API void zend_jit_shutdown(void) zend_jit_perf_jitdump_close(); } #endif - if (JIT_G(exit_counters)) { - free(JIT_G(exit_counters)); - } +#ifndef ZTS + zend_jit_trace_free_caches(); +#endif } static void zend_jit_reset_counters(void) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 555a868b2d553..14cd945bbe650 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8324,6 +8324,13 @@ static void zend_jit_trace_reset_caches(void) #endif } +static void zend_jit_trace_free_caches(void) +{ + if (JIT_G(exit_counters)) { + free(JIT_G(exit_counters)); + } +} + static void zend_jit_trace_restart(void) { ZEND_JIT_TRACE_NUM = 1; From afbb28dfb7cb86af42e5369e9f2c1e93e6027ec2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 7 Feb 2023 11:38:17 +0100 Subject: [PATCH 030/103] ext/opcache/zend_jit: cast function to fix -Wincompatible-pointer-types (#10527) * ext/opcache/zend_jit: cast function to fix -Wincompatible-pointer-types Regression by commit a21195650e53e34266806a8c379dd5a91f0dbb61 * TSRM/win32: fix ts_allocate_dtor cast The dtor was casted to ts_allocate_ctor; luckily, ts_allocate_dtor and ts_allocate_ctor just happen to be the same type. --- TSRM/tsrm_win32.c | 2 +- ext/opcache/jit/zend_jit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c index 4b5c58d6982a1..0cb4d36d4d7ab 100644 --- a/TSRM/tsrm_win32.c +++ b/TSRM/tsrm_win32.c @@ -91,7 +91,7 @@ static void tsrm_win32_dtor(tsrm_win32_globals *globals) TSRM_API void tsrm_win32_startup(void) {/*{{{*/ #ifdef ZTS - ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor); + ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_dtor)tsrm_win32_dtor); #else tsrm_win32_ctor(&win32_globals); #endif diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index b58614e50311e..d4699a4abc111 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4878,7 +4878,7 @@ ZEND_EXT_API int zend_jit_debug_config(zend_long old_val, zend_long new_val, int ZEND_EXT_API void zend_jit_init(void) { #ifdef ZTS - jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, zend_jit_globals_dtor); + jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, (ts_allocate_dtor) zend_jit_globals_dtor); #else zend_jit_globals_ctor(&jit_globals); #endif From c95125d37030a06cfea1a9e172601139525d3d74 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 7 Feb 2023 12:05:01 +0100 Subject: [PATCH 031/103] Disable timestamp for GitHub actions ccache --- .github/workflows/push.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 9fc0d05747c45..7c8e5698c7aae 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -48,6 +48,7 @@ jobs: # GitHub has no way to query the job name (github.job is the # job id, not the job name) key: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}-${{hashFiles('main/php_version.h')}}" + append-timestamp: false - name: ./configure uses: ./.github/actions/configure-x64 with: @@ -97,6 +98,7 @@ jobs: uses: hendrikmuhs/ccache-action@v1.2 with: key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" + append-timestamp: false - name: ./configure uses: ./.github/actions/configure-x32 with: @@ -127,6 +129,7 @@ jobs: uses: hendrikmuhs/ccache-action@v1.2 with: key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" + append-timestamp: false - name: ./configure uses: ./.github/actions/configure-macos with: From 131b862ac06fec7ab0f35a6033fda2cb72560453 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 7 Feb 2023 14:09:17 +0100 Subject: [PATCH 032/103] ext/opcache/zend_jit: call TSRM dtor before unloading opcache.so (#10533) Commit a21195650e53e added a TSRM destructor, but that destructor will get called by tsrm_shutdown(), which is after opcache.so has already been unloaded, resulting in a shutdown crash, e.g.: #0 0x00007fad01737500 in ?? () #1 0x000055ac54e723c4 in tsrm_shutdown () at TSRM/TSRM.c:194 #2 0x000055ac54c42180 in main (argc=80, argv=0x55ac57bc14d0) at sapi/cli/php_cli.c:1388 By calling ts_free_id() before opcache.so gets unloaded, we can easily fix this crash bug. --- ext/opcache/jit/zend_jit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d4699a4abc111..d2f6df0537c9d 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -5078,7 +5078,9 @@ ZEND_EXT_API void zend_jit_shutdown(void) zend_jit_perf_jitdump_close(); } #endif -#ifndef ZTS +#ifdef ZTS + ts_free_id(jit_globals_id); +#else zend_jit_trace_free_caches(); #endif } From 4df4264ac95ca35a6f550af56e32283896e42042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Thu, 24 Mar 2022 15:56:20 +0100 Subject: [PATCH 033/103] Fix PDO OCI Bug #60994 (Reading a multibyte CLOB caps at 8192 chars) --- ext/pdo_oci/config.m4 | 8 ++++++++ ext/pdo_oci/oci_statement.c | 32 +++++++++++++++++++++++--------- ext/pdo_oci/tests/bug60994.phpt | 31 +++++++++++++++++++++---------- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/ext/pdo_oci/config.m4 b/ext/pdo_oci/config.m4 index 1f5f436c3214e..05ecebf272c62 100644 --- a/ext/pdo_oci/config.m4 +++ b/ext/pdo_oci/config.m4 @@ -182,6 +182,14 @@ if test "$PHP_PDO_OCI" != "no"; then -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD ]) + dnl Can handle bytes vs. characters? + PHP_CHECK_LIBRARY(clntsh, OCILobRead2, + [ + AC_DEFINE(HAVE_OCILOBREAD2,1,[ ]) + ], [], [ + -L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD + ]) + PHP_CHECK_PDO_INCLUDES PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I$pdo_cv_inc_path) diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c index e77c78eef2d03..f3be69f9c32c2 100644 --- a/ext/pdo_oci/oci_statement.c +++ b/ext/pdo_oci/oci_statement.c @@ -616,6 +616,7 @@ struct oci_lob_self { OCILobLocator *lob; oci_lob_env *E; ub4 offset; + ub1 csfrm; }; static ssize_t oci_blob_write(php_stream *stream, const char *buf, size_t count) @@ -641,23 +642,34 @@ static ssize_t oci_blob_write(php_stream *stream, const char *buf, size_t count) static ssize_t oci_blob_read(php_stream *stream, char *buf, size_t count) { struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract; - ub4 amt; - sword r; +#if HAVE_OCILOBREAD2 + oraub8 byte_amt = (oraub8) count; + oraub8 char_amt = 0; - amt = (ub4) count; - r = OCILobRead(self->E->svc, self->E->err, self->lob, - &amt, self->offset, buf, (ub4) count, + sword r = OCILobRead2(self->E->svc, self->E->err, self->lob, + &byte_amt, &char_amt, (oraub8) self->offset, buf, (oraub8) count, + OCI_ONE_PIECE, NULL, NULL, 0, self->csfrm); +#else + ub4 byte_amt = (ub4) count; + + sword r = OCILobRead(self->E->svc, self->E->err, self->lob, + &byte_amt, self->offset, buf, (ub4) count, NULL, NULL, 0, SQLCS_IMPLICIT); +#endif if (r != OCI_SUCCESS && r != OCI_NEED_DATA) { - return (size_t)-1; + return (ssize_t)-1; } - self->offset += amt; - if (amt < count) { +#if HAVE_OCILOBREAD2 + self->offset += self->csfrm == 0 ? byte_amt : char_amt; +#else + self->offset += byte_amt; +#endif + if (byte_amt < count) { stream->eof = 1; } - return amt; + return byte_amt; } static int oci_blob_close(php_stream *stream, int close_handle) @@ -724,6 +736,8 @@ static php_stream *oci_create_lob_stream(zval *dbh, pdo_stmt_t *stmt, OCILobLoca self->E->svc = self->S->H->svc; self->E->err = self->S->err; + OCILobCharSetForm(self->S->H->env, self->S->err, self->lob, &self->csfrm); + stm = php_stream_alloc(&oci_blob_stream_ops, self, 0, "r+b"); if (stm) { diff --git a/ext/pdo_oci/tests/bug60994.phpt b/ext/pdo_oci/tests/bug60994.phpt index 15ec56c3e0283..6f5c9161dc8e5 100644 --- a/ext/pdo_oci/tests/bug60994.phpt +++ b/ext/pdo_oci/tests/bug60994.phpt @@ -21,18 +21,19 @@ $dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); $dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); @$dbh->exec('DROP TABLE pdo_oci_bug60994'); -$dbh->exec('CREATE TABLE pdo_oci_bug60994 (id NUMBER, data CLOB)'); +$dbh->exec('CREATE TABLE pdo_oci_bug60994 (id NUMBER, data CLOB, data2 NCLOB)'); $id = null; -$insert = $dbh->prepare('INSERT INTO pdo_oci_bug60994 (id, data) VALUES (:id, :data)'); +$insert = $dbh->prepare('INSERT INTO pdo_oci_bug60994 (id, data, data2) VALUES (:id, :data, :data2)'); $insert->bindParam(':id', $id, \PDO::PARAM_STR); -$select = $dbh->prepare("SELECT data FROM pdo_oci_bug60994 WHERE id = :id"); +$select = $dbh->prepare("SELECT data, data2 FROM pdo_oci_bug60994 WHERE id = :id"); echo PHP_EOL, 'Test 1: j', PHP_EOL; $string1 = 'abc' . str_repeat('j', 8187) . 'xyz'; // 8193 chars total works fine here (even 1 million works fine, subject to memory_limit) $id = 1; $insert->bindParam(':data', $string1, \PDO::PARAM_STR, strlen($string1)); // length in bytes +$insert->bindParam(':data2', $string1, \PDO::PARAM_STR, strlen($string1)); $insert->execute(); $select->bindParam(':id', $id, \PDO::PARAM_STR); $select->execute(); @@ -44,12 +45,15 @@ echo 'size of string1 is ', strlen($string1), ' bytes, ', mb_strlen($string1), ' echo 'size of stream1 is ', strlen($stream1), ' bytes, ', mb_strlen($stream1), ' chars.', PHP_EOL; echo 'beg of stream1 is ', $start1, PHP_EOL; echo 'end of stream1 is ', $ending1, PHP_EOL; - +if ($string1 != $stream1 || $stream1 != stream_get_contents($row['DATA2'])) { + echo 'Expected nclob value to match clob value for stream1', PHP_EOL; +} echo PHP_EOL, 'Test 2: £', PHP_EOL; $string2 = 'abc' . str_repeat('£', 8187) . 'xyz'; // 8193 chars total is when it breaks $id = 2; $insert->bindParam(':data', $string2, \PDO::PARAM_STR, strlen($string2)); // length in bytes +$insert->bindParam(':data2', $string2, \PDO::PARAM_STR, strlen($string2)); $insert->execute(); $select->bindParam(':id', $id, \PDO::PARAM_STR); $select->execute(); @@ -61,12 +65,15 @@ echo 'size of string2 is ', strlen($string2), ' bytes, ', mb_strlen($string2), ' echo 'size of stream2 is ', strlen($stream2), ' bytes, ', mb_strlen($stream2), ' chars.', PHP_EOL; echo 'beg of stream2 is ', $start2, PHP_EOL; echo 'end of stream2 is ', $ending2, PHP_EOL; - +if ($string2 != $stream2 || $stream2 != stream_get_contents($row['DATA2'])) { + echo 'Expected nclob value to match clob value for stream2', PHP_EOL; +} echo PHP_EOL, 'Test 3: Җ', PHP_EOL; $string3 = 'abc' . str_repeat('Җ', 8187) . 'xyz'; // 8193 chars total is when it breaks $id = 3; $insert->bindParam(':data', $string3, \PDO::PARAM_STR, strlen($string3)); // length in bytes +$insert->bindParam(':data2', $string3, \PDO::PARAM_STR, strlen($string3)); $insert->execute(); $select->bindParam(':id', $id, \PDO::PARAM_STR); $select->execute(); @@ -78,12 +85,15 @@ echo 'size of string3 is ', strlen($string3), ' bytes, ', mb_strlen($string3), ' echo 'size of stream3 is ', strlen($stream3), ' bytes, ', mb_strlen($stream3), ' chars.', PHP_EOL; echo 'beg of stream3 is ', $start3, PHP_EOL; echo 'end of stream3 is ', $ending3, PHP_EOL; - +if ($string3 != $stream3 || $stream3 != stream_get_contents($row['DATA2'])) { + echo 'Expected nclob value to match clob value for stream3', PHP_EOL; +} echo PHP_EOL, 'Test 4: の', PHP_EOL; $string4 = 'abc' . str_repeat('の', 8187) . 'xyz'; // 8193 chars total is when it breaks $id = 4; $insert->bindParam(':data', $string4, \PDO::PARAM_STR, strlen($string4)); // length in bytes +$insert->bindParam(':data2', $string4, \PDO::PARAM_STR, strlen($string4)); $insert->execute(); $select->bindParam(':id', $id, \PDO::PARAM_STR); $select->execute(); @@ -95,13 +105,14 @@ echo 'size of string4 is ', strlen($string4), ' bytes, ', mb_strlen($string4), ' echo 'size of stream4 is ', strlen($stream4), ' bytes, ', mb_strlen($stream4), ' chars.', PHP_EOL; echo 'beg of stream4 is ', $start4, PHP_EOL; echo 'end of stream4 is ', $ending4, PHP_EOL; +if ($string4 != $stream4 || $stream4 != stream_get_contents($row['DATA2'])) { + echo 'Expected nclob value to match clob value for stream4', PHP_EOL; +} ?> ---XFAIL-- -Fails due to Bug 60994 --EXPECT-- Test 1: j -size of string1 is 1000006 bytes, 1000006 chars. -size of stream1 is 1000006 bytes, 1000006 chars. +size of string1 is 8193 bytes, 8193 chars. +size of stream1 is 8193 bytes, 8193 chars. beg of stream1 is abcjjjjjjj end of stream1 is jjjjjjjxyz From ba282f1b2f425ea4e3e86a87c3b842a9bfa42710 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 7 Feb 2023 09:28:50 -0600 Subject: [PATCH 034/103] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index ea21713af4c31..bb3d77ca491b4 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ PHP NEWS - Opcache: . Fix incorrect page_size check. (nielsdos) +- PDO OCI: + . Fixed bug #60994 (Reading a multibyte CLOB caps at 8192 chars). + (Michael Voříšek) + - Phar: . Fix incorrect check in phar tar parsing. (nielsdos) From 0752baa583e4d16fffd06eb7276724c7233dc0e2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 28 Dec 2022 10:04:06 +0100 Subject: [PATCH 035/103] Zend/zend_cpuinfo, ext/standard/crc32_x86: fix -Wstrict-prototypes In plain C, a function without arguments must be explicitly declared (void). Close GH-10528 --- Zend/zend_cpuinfo.h | 2 +- ext/standard/crc32_x86.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_cpuinfo.h b/Zend/zend_cpuinfo.h index fcaf33d5e721c..ebfbab799795d 100644 --- a/Zend/zend_cpuinfo.h +++ b/Zend/zend_cpuinfo.h @@ -208,7 +208,7 @@ static inline int zend_cpu_supports_avx2(void) { /* __builtin_cpu_supports has pclmul from gcc9 */ #if PHP_HAVE_BUILTIN_CPU_SUPPORTS && (!defined(__GNUC__) || (ZEND_GCC_VERSION >= 9000)) ZEND_NO_SANITIZE_ADDRESS -static inline int zend_cpu_supports_pclmul() { +static inline int zend_cpu_supports_pclmul(void) { #if PHP_HAVE_BUILTIN_CPU_INIT __builtin_cpu_init(); #endif diff --git a/ext/standard/crc32_x86.c b/ext/standard/crc32_x86.c index eec023264002f..fdcbed8782557 100644 --- a/ext/standard/crc32_x86.c +++ b/ext/standard/crc32_x86.c @@ -323,7 +323,7 @@ typedef size_t (*crc32_x86_simd_func_t)(X86_CRC32_TYPE type, uint32_t *crc, cons ZEND_NO_SANITIZE_ADDRESS ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */ -static crc32_x86_simd_func_t resolve_crc32_x86_simd_update() { +static crc32_x86_simd_func_t resolve_crc32_x86_simd_update(void) { if (zend_cpu_supports_sse42() && zend_cpu_supports_pclmul()) { return crc32_sse42_pclmul_update; } From e6281db857b567eccc27ed856ab94efcf1a0f769 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 16 Jan 2023 09:42:03 +0100 Subject: [PATCH 036/103] php.ini-production: disable opcache.huge_code_pages by default There are only very narrow circumstances under which this option has been reported to provide 1% performance gain due to reduction of TLB misses. In many setups, this option only increases memory usage, and will actually decrease performance. To avoid this, let's leave it disabled by default, and let it be an explicit decision to enable it. For a discussion, see https://github.com/php/php-src/pull/10301 Closes GH-10336 --- php.ini-development | 7 ++++++- php.ini-production | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/php.ini-development b/php.ini-development index a963e0d62ec65..e61f19b87cace 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1888,7 +1888,12 @@ ldap.max_links = -1 ;opcache.file_cache_fallback=1 ; Enables or disables copying of PHP code (text segment) into HUGE PAGES. -; This should improve performance, but requires appropriate OS configuration. +; Under certain circumstances (if only a single global PHP process is +; started from which all others fork), this can increase performance +; by a tiny amount because TLB misses are reduced. On the other hand, this +; delays PHP startup, increases memory usage and degrades performance +; under memory pressure - use with care. +; Requires appropriate OS configuration. ;opcache.huge_code_pages=0 ; Validate cached file permissions. diff --git a/php.ini-production b/php.ini-production index 0864b40c60497..73a4db3c31bd5 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1890,8 +1890,13 @@ ldap.max_links = -1 ;opcache.file_cache_fallback=1 ; Enables or disables copying of PHP code (text segment) into HUGE PAGES. -; This should improve performance, but requires appropriate OS configuration. -;opcache.huge_code_pages=1 +; Under certain circumstances (if only a single global PHP process is +; started from which all others fork), this can increase performance +; by a tiny amount because TLB misses are reduced. On the other hand, this +; delays PHP startup, increases memory usage and degrades performance +; under memory pressure - use with care. +; Requires appropriate OS configuration. +;opcache.huge_code_pages=0 ; Validate cached file permissions. ;opcache.validate_permission=0 From 71ddede5655fe654002ae18af6a18e033f717287 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 6 Feb 2023 21:59:07 +0100 Subject: [PATCH 037/103] Fix GH-10168: heap-buffer-overflow at zval_undefined_cv The problem is that we're using the variable_ptr in the opcode handler *after* it has already been destroyed. The solution is to create a specialised version of zend_assign_to_variable which takes in two destination zval pointers. Closes GH-10524 --- NEWS | 2 + Zend/tests/gh10168_1.phpt | 32 +++ Zend/tests/gh10168_2.phpt | 32 +++ Zend/tests/gh10168_3.phpt | 29 +++ Zend/zend_execute.c | 10 +- Zend/zend_execute.h | 50 +++- Zend/zend_vm_def.h | 20 +- Zend/zend_vm_execute.h | 504 +++++++++++++++++++++++++------------- 8 files changed, 486 insertions(+), 193 deletions(-) create mode 100644 Zend/tests/gh10168_1.phpt create mode 100644 Zend/tests/gh10168_2.phpt create mode 100644 Zend/tests/gh10168_3.phpt diff --git a/NEWS b/NEWS index bb3d77ca491b4..ce886d1638c7a 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS Generator emits an unavoidable fatal error or crashes). (Arnaud) . Fixed bug GH-10437 (Segfault/assertion when using fibers in shutdown function after bailout). (trowski) + . Fixed bug GH-10168: use-after-free when utilizing assigned object freed + during assignment. (nielsdos) - Date: . Fix GH-10447 ('p' format specifier does not yield 'Z' for 00:00). (Derick) diff --git a/Zend/tests/gh10168_1.phpt b/Zend/tests/gh10168_1.phpt new file mode 100644 index 0000000000000..6433453ed2448 --- /dev/null +++ b/Zend/tests/gh10168_1.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): array variation +--FILE-- + 0; + var_dump(self::$instances); + } + + function __destruct() { + unset(self::$instances[NULL]); + } +} +new Test(); +new Test(); + +?> +--EXPECTF-- +Notice: Object of class Test could not be converted to int in %s on line %d +array(1) { + [""]=> + object(Test)#1 (0) { + } +} + +Notice: Object of class Test could not be converted to int in %s on line %d +array(0) { +} diff --git a/Zend/tests/gh10168_2.phpt b/Zend/tests/gh10168_2.phpt new file mode 100644 index 0000000000000..abab8b72f1cb9 --- /dev/null +++ b/Zend/tests/gh10168_2.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign global variation +--FILE-- + 0; + // Destructor called after comparison, so a will be NULL + var_dump($GLOBALS['a']); + } + + function __destruct() { + unset($GLOBALS['a']); + } +} +new Test(); +new Test(); + +?> +--EXPECTF-- +Notice: Object of class Test could not be converted to int in %s on line %d +object(Test)#1 (0) { +} + +Notice: Object of class Test could not be converted to int in %s on line %d + +Warning: Undefined global variable $a in %s on line %d +NULL diff --git a/Zend/tests/gh10168_3.phpt b/Zend/tests/gh10168_3.phpt new file mode 100644 index 0000000000000..fb8729c99661a --- /dev/null +++ b/Zend/tests/gh10168_3.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop +--FILE-- + +--EXPECTF-- +object(Test)#1 (0) { +} +object(Test)#2 (0) { +} diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 922b45c42baf4..49af6fc76957c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3562,7 +3562,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { } } -ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) +ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr) { bool ret; zval value; @@ -3582,6 +3582,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze } else { zval_ptr_dtor_nogc(&value); } + if (result_variable_ptr) { + ZVAL_COPY(result_variable_ptr, variable_ptr); + } if (value_type & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(ref)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { @@ -3595,6 +3598,11 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze return variable_ptr; } +ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) +{ + return zend_assign_to_typed_ref_and_result(variable_ptr, orig_value, value_type, strict, NULL); +} + ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) { zval *val = orig_val; if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 3e61967cb2bea..1091b1ebe652b 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -108,6 +108,7 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret); ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); +ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr); ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict); static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) @@ -137,12 +138,22 @@ static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *v } } +static zend_always_inline void zend_handle_garbage_from_variable_assignment(zend_refcounted *garbage) +{ + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { /* we need to split */ + /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ + if (UNEXPECTED(GC_MAY_LEAK(garbage))) { + gc_possible_root(garbage); + } + } +} + static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) { do { if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { - zend_refcounted *garbage; - if (Z_ISREF_P(variable_ptr)) { if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict); @@ -153,21 +164,42 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval break; } } - garbage = Z_COUNTED_P(variable_ptr); + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); zend_copy_to_variable(variable_ptr, value, value_type); - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { /* we need to split */ - /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ - if (UNEXPECTED(GC_MAY_LEAK(garbage))) { - gc_possible_root(garbage); + zend_handle_garbage_from_variable_assignment(garbage); + return variable_ptr; + } + } while (0); + + zend_copy_to_variable(variable_ptr, value, value_type); + return variable_ptr; +} + +static zend_always_inline zval* zend_assign_to_two_variables(zval *result_variable_ptr, zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) +{ + do { + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + if (Z_ISREF_P(variable_ptr)) { + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { + variable_ptr = zend_assign_to_typed_ref_and_result(variable_ptr, value, value_type, strict, result_variable_ptr); + return variable_ptr; + } + + variable_ptr = Z_REFVAL_P(variable_ptr); + if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { + break; } } + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + zend_copy_to_variable(variable_ptr, value, value_type); + ZVAL_COPY(result_variable_ptr, variable_ptr); + zend_handle_garbage_from_variable_assignment(garbage); return variable_ptr; } } while (0); zend_copy_to_variable(variable_ptr, value, value_type); + ZVAL_COPY(result_variable_ptr, variable_ptr); return variable_ptr; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 4845a92b95a7e..09d7b95896ec8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2577,6 +2577,9 @@ ZEND_VM_C_LABEL(try_assign_dim_array): Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_CONST) { @@ -2588,10 +2591,11 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZEND_VM_C_GOTO(assign_dim_error); } value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); - value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -2685,12 +2689,14 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); } + FREE_OP1_VAR_PTR(); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a5a5eabf2b037..6f1b9b49f725a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23464,6 +23464,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23475,10 +23478,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23612,6 +23616,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23623,10 +23630,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23761,6 +23769,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23772,10 +23783,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23910,6 +23922,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23921,10 +23936,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24017,12 +24033,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24037,12 +24055,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26163,6 +26183,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26174,10 +26197,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26311,6 +26335,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26322,10 +26349,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26460,6 +26488,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26471,10 +26502,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26609,6 +26641,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26620,10 +26655,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27346,12 +27382,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27366,12 +27404,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27430,12 +27470,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27450,12 +27492,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27694,6 +27738,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27705,10 +27752,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27842,6 +27890,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27853,10 +27904,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27991,6 +28043,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28002,10 +28057,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28140,6 +28196,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28151,10 +28210,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30370,6 +30430,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30381,10 +30444,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30518,6 +30582,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30529,10 +30596,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30667,6 +30735,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30678,10 +30749,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30816,6 +30888,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30827,10 +30902,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30923,12 +30999,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30943,12 +31021,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41421,6 +41501,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41432,10 +41515,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41569,6 +41653,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41580,10 +41667,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41718,6 +41806,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41729,10 +41820,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41867,6 +41959,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41878,10 +41973,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41974,12 +42070,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41994,12 +42091,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45199,6 +45297,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45210,10 +45311,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45347,6 +45449,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45358,10 +45463,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45496,6 +45602,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45507,10 +45616,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45645,6 +45755,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45656,10 +45769,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -46670,12 +46784,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46690,12 +46805,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46740,12 +46856,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46760,12 +46877,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47177,6 +47295,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47188,10 +47309,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47325,6 +47447,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47336,10 +47461,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47474,6 +47600,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47485,10 +47614,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47623,6 +47753,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47634,10 +47767,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50514,6 +50648,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50525,10 +50662,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50662,6 +50800,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50673,10 +50814,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50811,6 +50953,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50822,10 +50967,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50960,6 +51106,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50971,10 +51120,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -51067,12 +51217,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -51087,12 +51238,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } From 8c8a38a75ce638598732f316f895ecaca7ad9259 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 7 Feb 2023 12:16:03 +0100 Subject: [PATCH 038/103] ext/curl: suppress -Wdeprecated-declarations Closes GH-10531. --- NEWS | 3 +++ ext/curl/interface.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/NEWS b/NEWS index ce886d1638c7a..38fb6baefd980 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,9 @@ PHP NEWS . Fixed bug GH-10168: use-after-free when utilizing assigned object freed during assignment. (nielsdos) +- Curl: + . Fixed deprecation warning at compile time. (Max Kellermann) + - Date: . Fix GH-10447 ('p' format specifier does not yield 'Z' for 00:00). (Derick) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 4fc0415e78757..36300dacfcfba 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -62,6 +62,12 @@ #include "curl_private.h" #include "curl_arginfo.h" +#ifdef __GNUC__ +/* don't complain about deprecated CURLOPT_* we're exposing to PHP; we + need to keep using those to avoid breaking PHP API compatibiltiy */ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */ static MUTEX_T *php_curl_openssl_tsl = NULL; From 704aadd098f0d77a283eabd65d2f4a0e8b412b3f Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Wed, 8 Feb 2023 14:52:40 +0000 Subject: [PATCH 039/103] Fix memory leaks in ext-tidy We must not instantiate the object prior checking error conditions Moreover, we need to release the HUGE amount of memory for files which are over 4GB when throwing a ValueError Closes GH-10545 --- NEWS | 4 ++ ext/tidy/tests/parsing_file_too_large.phpt | 56 +++++++++++++++++++++ ext/tidy/tests/parsing_inexistent_file.phpt | 22 ++++++++ ext/tidy/tidy.c | 9 ++-- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 ext/tidy/tests/parsing_file_too_large.phpt create mode 100644 ext/tidy/tests/parsing_inexistent_file.phpt diff --git a/NEWS b/NEWS index 38fb6baefd980..6d6114f7c0fec 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,10 @@ PHP NEWS . Fix bug GH-9697 for reset/end/next/prev() attempting to move pointer of properties table for certain internal classes such as FFI classes +- Tidy: + . Fix memory leaks when attempting to open a non-existing file or a file over + 4GB. (Girgias) + 02 Feb 2023, PHP 8.1.15 - Apache: diff --git a/ext/tidy/tests/parsing_file_too_large.phpt b/ext/tidy/tests/parsing_file_too_large.phpt new file mode 100644 index 0000000000000..603a588b4f8f0 --- /dev/null +++ b/ext/tidy/tests/parsing_file_too_large.phpt @@ -0,0 +1,56 @@ +--TEST-- +Trying to parse a file that is too large (over 4GB) +--EXTENSIONS-- +tidy +--SKIPIF-- + +--INI-- +memory_limit="5G" +--FILE-- +parseFile($path)); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump(tidy_parse_file($path)); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + $tidy = new tidy($path); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +?> +--CLEAN-- + +--EXPECT-- +int(0) +ValueError: Input string is too long +ValueError: Input string is too long +ValueError: Input string is too long diff --git a/ext/tidy/tests/parsing_inexistent_file.phpt b/ext/tidy/tests/parsing_inexistent_file.phpt new file mode 100644 index 0000000000000..26dfea798574e --- /dev/null +++ b/ext/tidy/tests/parsing_inexistent_file.phpt @@ -0,0 +1,22 @@ +--TEST-- +Trying to parse a non existent file +--EXTENSIONS-- +tidy +--FILE-- +parseFile("does_not_exist.html")); + +var_dump(tidy_parse_file("does_not_exist.html")); + +$tidy = new tidy("does_not_exist.html"); +?> +--EXPECTF-- +Warning: tidy::parseFile(): Cannot load "does_not_exist.html" into memory in %s on line %d +bool(false) + +Warning: tidy_parse_file(): Cannot load "does_not_exist.html" into memory in %s on line %d +bool(false) + +Warning: tidy::__construct(): Cannot load "does_not_exist.html" into memory in %s on line %d diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index acf73b8a7c68b..1d757f44fae76 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -1059,19 +1059,20 @@ PHP_FUNCTION(tidy_parse_file) Z_PARAM_BOOL(use_include_path) ZEND_PARSE_PARAMETERS_END(); - tidy_instanciate(tidy_ce_doc, return_value); - obj = Z_TIDY_P(return_value); - if (!(contents = php_tidy_file_to_mem(ZSTR_VAL(inputfile), use_include_path))) { php_error_docref(NULL, E_WARNING, "Cannot load \"%s\" into memory%s", ZSTR_VAL(inputfile), (use_include_path) ? " (using include path)" : ""); RETURN_FALSE; } if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + zend_string_release_ex(contents, 0); zend_value_error("Input string is too long"); RETURN_THROWS(); } + tidy_instanciate(tidy_ce_doc, return_value); + obj = Z_TIDY_P(return_value); + TIDY_APPLY_CONFIG(obj->ptdoc->doc, options_str, options_ht); if (php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc) == FAILURE) { @@ -1362,6 +1363,7 @@ PHP_METHOD(tidy, __construct) } if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + zend_string_release_ex(contents, 0); zend_value_error("Input string is too long"); RETURN_THROWS(); } @@ -1400,6 +1402,7 @@ PHP_METHOD(tidy, parseFile) } if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + zend_string_release_ex(contents, 0); zend_value_error("Input string is too long"); RETURN_THROWS(); } From 13c34aac05dd704564fee15a788129754fa39eb5 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 11 Feb 2023 00:21:01 +0100 Subject: [PATCH 040/103] Mark test as XFAIL See https://github.com/php/php-src/pull/10546 --- Zend/tests/gh10168_3.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/tests/gh10168_3.phpt b/Zend/tests/gh10168_3.phpt index fb8729c99661a..35c8ed42f8470 100644 --- a/Zend/tests/gh10168_3.phpt +++ b/Zend/tests/gh10168_3.phpt @@ -1,5 +1,6 @@ --TEST-- GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop +--XFAIL-- --FILE-- Date: Sat, 11 Feb 2023 13:22:27 +0100 Subject: [PATCH 041/103] Temporarily disable odbc in ci The unixodbc.h header is suddenly missing. --- .github/actions/configure-x64/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml index ee802334490ae..72abc69da5eae 100644 --- a/.github/actions/configure-x64/action.yml +++ b/.github/actions/configure-x64/action.yml @@ -70,10 +70,10 @@ runs: --with-lmdb \ --with-qdbm \ --with-snmp \ - --with-unixODBC \ + `#--with-unixODBC` \ --with-imap \ --with-imap-ssl \ - --with-pdo-odbc=unixODBC,/usr \ + `#--with-pdo-odbc=unixODBC,/usr` \ --with-pdo-oci=shared,instantclient,/opt/oracle/instantclient \ --with-oci8=shared,instantclient,/opt/oracle/instantclient \ --with-config-file-path=/etc \ From c840f71524067aa474c00c3eacfb83bd860bfc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 23 Jan 2023 21:15:24 +0100 Subject: [PATCH 042/103] crypt: Fix validation of malformed BCrypt hashes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHP’s implementation of crypt_blowfish differs from the upstream Openwall version by adding a “PHP Hack”, which allows one to cut short the BCrypt salt by including a `$` character within the characters that represent the salt. Hashes that are affected by the “PHP Hack” may erroneously validate any password as valid when used with `password_verify` and when comparing the return value of `crypt()` against the input. The PHP Hack exists since the first version of PHP’s own crypt_blowfish implementation that was added in 1e820eca02dcf322b41fd2fe4ed2a6b8309f8ab5. No clear reason is given for the PHP Hack’s existence. This commit removes it, because BCrypt hashes containing a `$` character in their salt are not valid BCrypt hashes. --- ext/standard/crypt_blowfish.c | 8 -- .../tests/crypt/bcrypt_salt_dollar.phpt | 82 +++++++++++++++++++ 2 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 ext/standard/tests/crypt/bcrypt_salt_dollar.phpt diff --git a/ext/standard/crypt_blowfish.c b/ext/standard/crypt_blowfish.c index 3806a290aee40..351d40308089e 100644 --- a/ext/standard/crypt_blowfish.c +++ b/ext/standard/crypt_blowfish.c @@ -371,7 +371,6 @@ static const unsigned char BF_atoi64[0x60] = { #define BF_safe_atoi64(dst, src) \ { \ tmp = (unsigned char)(src); \ - if (tmp == '$') break; /* PHP hack */ \ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ tmp = BF_atoi64[tmp]; \ if (tmp > 63) return -1; \ @@ -399,13 +398,6 @@ static int BF_decode(BF_word *dst, const char *src, int size) *dptr++ = ((c3 & 0x03) << 6) | c4; } while (dptr < end); - if (end - dptr == size) { - return -1; - } - - while (dptr < end) /* PHP hack */ - *dptr++ = 0; - return 0; } diff --git a/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt new file mode 100644 index 0000000000000..32e335f4b087e --- /dev/null +++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt @@ -0,0 +1,82 @@ +--TEST-- +bcrypt correctly rejects salts containing $ +--FILE-- + +--EXPECT-- +string(8) "$2y$04$$" +string(2) "*0" +bool(false) +string(9) "$2y$04$0$" +string(2) "*0" +bool(false) +string(10) "$2y$04$00$" +string(2) "*0" +bool(false) +string(11) "$2y$04$000$" +string(2) "*0" +bool(false) +string(12) "$2y$04$0000$" +string(2) "*0" +bool(false) +string(13) "$2y$04$00000$" +string(2) "*0" +bool(false) +string(14) "$2y$04$000000$" +string(2) "*0" +bool(false) +string(15) "$2y$04$0000000$" +string(2) "*0" +bool(false) +string(16) "$2y$04$00000000$" +string(2) "*0" +bool(false) +string(17) "$2y$04$000000000$" +string(2) "*0" +bool(false) +string(18) "$2y$04$0000000000$" +string(2) "*0" +bool(false) +string(19) "$2y$04$00000000000$" +string(2) "*0" +bool(false) +string(20) "$2y$04$000000000000$" +string(2) "*0" +bool(false) +string(21) "$2y$04$0000000000000$" +string(2) "*0" +bool(false) +string(22) "$2y$04$00000000000000$" +string(2) "*0" +bool(false) +string(23) "$2y$04$000000000000000$" +string(2) "*0" +bool(false) +string(24) "$2y$04$0000000000000000$" +string(2) "*0" +bool(false) +string(25) "$2y$04$00000000000000000$" +string(2) "*0" +bool(false) +string(26) "$2y$04$000000000000000000$" +string(2) "*0" +bool(false) +string(27) "$2y$04$0000000000000000000$" +string(2) "*0" +bool(false) +string(28) "$2y$04$00000000000000000000$" +string(2) "*0" +bool(false) +string(29) "$2y$04$000000000000000000000$" +string(2) "*0" +bool(false) +string(30) "$2y$04$0000000000000000000000$" +string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K" +bool(false) From a92acbad873a05470af1a47cb785a18eadd827b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 23 Jan 2023 22:13:57 +0100 Subject: [PATCH 043/103] crypt: Fix possible buffer overread in php_crypt() --- ext/standard/crypt.c | 1 + ext/standard/tests/password/password_bcrypt_short.phpt | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 ext/standard/tests/password/password_bcrypt_short.phpt diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c index 8c105cf910e85..8316c8b960639 100644 --- a/ext/standard/crypt.c +++ b/ext/standard/crypt.c @@ -135,6 +135,7 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch } else if ( salt[0] == '$' && salt[1] == '2' && + salt[2] != 0 && salt[3] == '$') { char output[PHP_MAX_SALT_LEN + 1]; diff --git a/ext/standard/tests/password/password_bcrypt_short.phpt b/ext/standard/tests/password/password_bcrypt_short.phpt new file mode 100644 index 0000000000000..085bc8a239045 --- /dev/null +++ b/ext/standard/tests/password/password_bcrypt_short.phpt @@ -0,0 +1,8 @@ +--TEST-- +Test that password_hash() does not overread buffers when a short hash is passed +--FILE-- + +--EXPECT-- +bool(false) From af2ddc64262216848d2e95108c121967a2b0a8a9 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 12 Feb 2023 20:53:06 -0700 Subject: [PATCH 044/103] Update NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 907a06b90ec97..82d773a3b2a23 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.0.28 +- Core: + . Fixed bug #81744 (Password_verify() always return true with some hash). + (CVE-2023-0567). (Tim Düsterhus) 05 Jan 2023, PHP 8.0.27 From ec10b28d64decbc54aa1e585dce580f0bd7a5953 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 27 Jan 2023 19:28:27 +0100 Subject: [PATCH 045/103] Fix array overrun when appending slash to paths Fix it by extending the array sizes by one character. As the input is limited to the maximum path length, there will always be place to append the slash. As the php_check_specific_open_basedir() simply uses the strings to compare against each other, no new failures related to too long paths are introduced. We'll let the DOM and XML case handle a potentially too long path in the library code. --- ext/dom/document.c | 2 +- ext/xmlreader/php_xmlreader.c | 2 +- main/fopen_wrappers.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index dbbabb8bffde6..fa6a6377ad5ce 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1174,7 +1174,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so int validate, recover, resolve_externals, keep_blanks, substitute_ent; int resolved_path_len; int old_error_reporting = 0; - char *directory=NULL, resolved_path[MAXPATHLEN]; + char *directory=NULL, resolved_path[MAXPATHLEN + 1]; if (id != NULL) { intern = Z_DOMOBJ_P(id); diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index ecc52aa1d6f4c..d8f8105010c71 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -1024,7 +1024,7 @@ PHP_METHOD(XMLReader, XML) xmlreader_object *intern = NULL; char *source, *uri = NULL, *encoding = NULL; int resolved_path_len, ret = 0; - char *directory=NULL, resolved_path[MAXPATHLEN]; + char *directory=NULL, resolved_path[MAXPATHLEN + 1]; xmlParserInputBufferPtr inputbfr; xmlTextReaderPtr reader; diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 39a9c82d5984e..5e4a619c8fe70 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -129,10 +129,10 @@ PHPAPI ZEND_INI_MH(OnUpdateBaseDir) */ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path) { - char resolved_name[MAXPATHLEN]; - char resolved_basedir[MAXPATHLEN]; + char resolved_name[MAXPATHLEN + 1]; + char resolved_basedir[MAXPATHLEN + 1]; char local_open_basedir[MAXPATHLEN]; - char path_tmp[MAXPATHLEN]; + char path_tmp[MAXPATHLEN + 1]; char *path_file; size_t resolved_basedir_len; size_t resolved_name_len; From b5ccaaf613066e3862cca86dbe1f39d3c376649a Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 12 Feb 2023 21:04:31 -0700 Subject: [PATCH 046/103] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 82d773a3b2a23..a6dfbec2629dc 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug #81744 (Password_verify() always return true with some hash). (CVE-2023-0567). (Tim Düsterhus) + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) 05 Jan 2023, PHP 8.0.27 From d721dcc2efd91dbefbca2e1d0e11982af30f4cc3 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 10 Feb 2023 18:07:34 +0100 Subject: [PATCH 047/103] Fix colletion of unfinished function call in fibers Fixes GH-10496. Co-authored-by: Bob Weinand --- NEWS | 2 ++ Zend/tests/fibers/gh10496.phpt | 33 +++++++++++++++++++++++++++++++++ Zend/zend_execute.c | 30 +++++++++++++++++++++++++++--- Zend/zend_execute.h | 3 ++- Zend/zend_fibers.c | 2 +- Zend/zend_generators.c | 2 +- 6 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/fibers/gh10496.phpt diff --git a/NEWS b/NEWS index 6d6114f7c0fec..8976f64b3f43d 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,8 @@ PHP NEWS - Fiber: . Fixed assembly on alpine x86. (nielsdos) + . Fixed bug GH-10496 (segfault when garbage collector is invoked inside of + fiber). (Bob, Arnaud) - FPM: . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) diff --git a/Zend/tests/fibers/gh10496.phpt b/Zend/tests/fibers/gh10496.phpt new file mode 100644 index 0000000000000..76ea5fea78c98 --- /dev/null +++ b/Zend/tests/fibers/gh10496.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug GH-10496 (Segfault when garbage collector is invoked inside of fiber) +--FILE-- +start(); +unset($f); +gc_collect_cycles(); +print "Collected\n"; + +?> +--EXPECT-- +Cleaned +Dtor x() +Collected diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 49af6fc76957c..848d479651f86 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4459,7 +4459,24 @@ ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, cleanup_live_vars(execute_data, op_num, catch_op_num); } -ZEND_API HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer) +ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer) +{ + bool suspended_by_yield = false; + + if (Z_TYPE_INFO(EX(This)) & ZEND_CALL_GENERATOR) { + ZEND_ASSERT(EX(return_value)); + + /* The generator object is stored in EX(return_value) */ + zend_generator *generator = (zend_generator*) EX(return_value); + ZEND_ASSERT(execute_data == generator->execute_data); + + suspended_by_yield = !(generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING); + } + + return zend_unfinished_execution_gc_ex(execute_data, call, gc_buffer, suspended_by_yield); +} + +ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield) { if (!EX(func) || !ZEND_USER_CODE(EX(func)->common.type)) { return NULL; @@ -4495,8 +4512,15 @@ ZEND_API HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data } if (call) { - /* -1 required because we want the last run opcode, not the next to-be-run one. */ - uint32_t op_num = execute_data->opline - op_array->opcodes - 1; + uint32_t op_num = execute_data->opline - op_array->opcodes; + if (suspended_by_yield) { + /* When the execution was suspended by yield, EX(opline) points to + * next opline to execute. Otherwise, it points to the opline that + * suspended execution. */ + op_num--; + ZEND_ASSERT(EX(func)->op_array.opcodes[op_num].opcode == ZEND_YIELD + || EX(func)->op_array.opcodes[op_num].opcode == ZEND_YIELD_FROM); + } zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer); } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 1091b1ebe652b..eaad706cee3d5 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -410,7 +410,8 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data); ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_execute_data *call, uint32_t op_num, zend_get_gc_buffer *buf); ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); -ZEND_API HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer); +ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer); +ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield); zval * ZEND_FASTCALL zend_handle_named_arg( zend_execute_data **call_ptr, zend_string *arg_name, diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 051a9dceaea7a..a0892effdf2a7 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -652,7 +652,7 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n HashTable *lastSymTable = NULL; zend_execute_data *ex = fiber->execute_data; for (; ex; ex = ex->prev_execute_data) { - HashTable *symTable = zend_unfinished_execution_gc(ex, ex->call, buf); + HashTable *symTable = zend_unfinished_execution_gc_ex(ex, ex->call, buf, false); if (symTable) { if (lastSymTable) { zval *val; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a192170cae3ba..5d7bef3854f5e 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -372,7 +372,7 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int * call = zend_generator_revert_call_stack(generator->frozen_call_stack); } - zend_unfinished_execution_gc(execute_data, call, gc_buffer); + zend_unfinished_execution_gc_ex(execute_data, call, gc_buffer, true); if (UNEXPECTED(generator->frozen_call_stack)) { zend_generator_revert_call_stack(call); From 95016138a54b3352a0988878cd71c2ebe7cdeca5 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 13 Feb 2023 16:30:21 +0000 Subject: [PATCH 048/103] Fix GH-10496: Fibers must not be garbage collected while implicitly suspended by resumption of another fiber --- .../fibers/{gh10496.phpt => gh10496-001.phpt} | 2 +- Zend/tests/fibers/gh10496-002.phpt | 26 +++++++++++++++++++ Zend/zend_fibers.c | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) rename Zend/tests/fibers/{gh10496.phpt => gh10496-001.phpt} (83%) create mode 100644 Zend/tests/fibers/gh10496-002.phpt diff --git a/Zend/tests/fibers/gh10496.phpt b/Zend/tests/fibers/gh10496-001.phpt similarity index 83% rename from Zend/tests/fibers/gh10496.phpt rename to Zend/tests/fibers/gh10496-001.phpt index 76ea5fea78c98..9ca371fa2a6c5 100644 --- a/Zend/tests/fibers/gh10496.phpt +++ b/Zend/tests/fibers/gh10496-001.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug GH-10496 (Segfault when garbage collector is invoked inside of fiber) +Bug GH-10496 001 (Segfault when garbage collector is invoked inside of fiber) --FILE-- start(); + })(); + })(); +}); +$f->start(); +$f->resume(); + +?> +--EXPECT-- +Success diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index a0892effdf2a7..59aa63ba21b43 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -644,7 +644,7 @@ static HashTable *zend_fiber_object_gc(zend_object *object, zval **table, int *n zend_get_gc_buffer_add_zval(buf, &fiber->fci.function_name); zend_get_gc_buffer_add_zval(buf, &fiber->result); - if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) { + if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL) { zend_get_gc_buffer_use(buf, table, num); return NULL; } From 28d68f501360cc2a0f239925ab61d76943a19712 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Mon, 13 Feb 2023 13:16:07 -0600 Subject: [PATCH 049/103] PHP-8.1 is now for PHP 8.1.17-dev --- NEWS | 10 +++++++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 8976f64b3f43d..fdd0aef2aaea7 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.16 +?? ??? ????, PHP 8.1.17 - Core: . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) @@ -52,6 +52,14 @@ PHP NEWS . Fix memory leaks when attempting to open a non-existing file or a file over 4GB. (Girgias) +14 Feb 2023, PHP 8.1.16 + +- Core: + . Fixed bug #81744 (Password_verify() always return true with some hash). + (CVE-2023-0567). (Tim Düsterhus) + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) + 02 Feb 2023, PHP 8.1.15 - Apache: diff --git a/Zend/zend.h b/Zend/zend.h index 16b0ce6a1bd82..18e605c5bc27a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.16-dev" +#define ZEND_VERSION "4.1.17-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 6bf3274d2705b..ca3d695120da4 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.16-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.17-dev],[https://bugs.php.net],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 4231920700d72..b5568bffa819e 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 16 +#define PHP_RELEASE_VERSION 17 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.16-dev" -#define PHP_VERSION_ID 80116 +#define PHP_VERSION "8.1.17-dev" +#define PHP_VERSION_ID 80117 From 1a5fc6e1a3315053d43e96489a4bd320a34da4d5 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 13 Feb 2023 20:38:28 +0100 Subject: [PATCH 050/103] Fix assertion failure when var_dump'ing void FFI result (#10568) --- ext/ffi/ffi.c | 2 ++ ext/ffi/tests/gh10568.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 ext/ffi/tests/gh10568.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 107d2862c1256..ee5183ce9d46c 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1982,6 +1982,8 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) } switch (type->kind) { + case ZEND_FFI_TYPE_VOID: + return NULL; case ZEND_FFI_TYPE_BOOL: case ZEND_FFI_TYPE_CHAR: case ZEND_FFI_TYPE_ENUM: diff --git a/ext/ffi/tests/gh10568.phpt b/ext/ffi/tests/gh10568.phpt new file mode 100644 index 0000000000000..bd76671438d1b --- /dev/null +++ b/ext/ffi/tests/gh10568.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-10568 (Assertion failure when var_dump'ing void FFI result) +--EXTENSIONS-- +ffi +--SKIPIF-- + +--INI-- +ffi.enable=1 +--FILE-- +strlen("abc")); +?> +DONE +--EXPECT-- +object(FFI\CData:void)#2 (0) { +} +DONE From d94ddbed2c428f288f95b08790d6c407a887594d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 14 Feb 2023 09:29:29 +0100 Subject: [PATCH 051/103] Fix updating SSA object type for *_ASSIGN_OP (#10458) The code fetched the class entry into ce for objects and static properties. However, when the actual update needs to take place (when result_def exists), the class entry in ce was reset to NULL. So the SSA object type update never happened. Fetch the class entry in the result_def>=0 case instead after the reset of ce to NULL. --- Zend/Optimizer/zend_inference.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 33b01dda038f4..17373db2b636a 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2464,7 +2464,7 @@ static zend_always_inline int _zend_update_type_info( if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { prop_info = zend_fetch_prop_info(op_array, ssa, opline, ssa_op); orig = t1; - t1 = zend_fetch_prop_type(script, prop_info, &ce); + t1 = zend_fetch_prop_type(script, prop_info, NULL); t2 = OP1_DATA_INFO(); } else if (opline->opcode == ZEND_ASSIGN_DIM_OP) { if (t1 & MAY_BE_ARRAY_OF_REF) { @@ -2475,7 +2475,7 @@ static zend_always_inline int _zend_update_type_info( t2 = OP1_DATA_INFO(); } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline); - t1 = zend_fetch_prop_type(script, prop_info, &ce); + t1 = zend_fetch_prop_type(script, prop_info, NULL); t2 = OP1_DATA_INFO(); } else { if (t1 & MAY_BE_REF) { @@ -2537,7 +2537,7 @@ static zend_always_inline int _zend_update_type_info( } else if (opline->opcode == ZEND_ASSIGN_OBJ_OP) { /* The return value must also satisfy the property type */ if (prop_info) { - t1 = zend_fetch_prop_type(script, prop_info, NULL); + t1 = zend_fetch_prop_type(script, prop_info, &ce); if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) { /* DOUBLE may be auto-converted to LONG */ @@ -2549,7 +2549,7 @@ static zend_always_inline int _zend_update_type_info( } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) { /* The return value must also satisfy the property type */ if (prop_info) { - t1 = zend_fetch_prop_type(script, prop_info, NULL); + t1 = zend_fetch_prop_type(script, prop_info, &ce); if ((t1 & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_LONG && (tmp & (MAY_BE_LONG|MAY_BE_DOUBLE)) == MAY_BE_DOUBLE) { /* DOUBLE may be auto-converted to LONG */ From e45850c195dcd5534394cf357a3f776d4916b655 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 19 Jan 2023 14:11:18 +0000 Subject: [PATCH 052/103] Fix repeated warning for file uploads limit exceeding --- main/rfc1867.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main/rfc1867.c b/main/rfc1867.c index c2f606c64aa1a..b43cfae5a1e2f 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -911,7 +911,10 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ skip_upload = 1; } else if (upload_cnt <= 0) { skip_upload = 1; - sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); + if (upload_cnt == 0) { + --upload_cnt; + sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); + } } /* Return with an error if the posted data is garbled */ From 716de0cff539f46294ef70fe75d548cd66766370 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 19 Jan 2023 14:31:25 +0000 Subject: [PATCH 053/103] Introduce max_multipart_body_parts INI This fixes GHSA-54hq-v5wp-fqgv DOS vulnerabality by limitting number of parsed multipart body parts as currently all parts were always parsed. --- main/main.c | 1 + main/rfc1867.c | 11 ++ ...-54hq-v5wp-fqgv-max-body-parts-custom.phpt | 53 +++++++++ ...54hq-v5wp-fqgv-max-body-parts-default.phpt | 54 +++++++++ .../ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt | 52 +++++++++ sapi/fpm/tests/tester.inc | 106 +++++++++++++++--- 6 files changed, 262 insertions(+), 15 deletions(-) create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt diff --git a/main/main.c b/main/main.c index 40684f32dc146..c58ea58bf5ac7 100644 --- a/main/main.c +++ b/main/main.c @@ -751,6 +751,7 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) + PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals) diff --git a/main/rfc1867.c b/main/rfc1867.c index b43cfae5a1e2f..3086e8da3dbe7 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -687,6 +687,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ void *event_extra_data = NULL; unsigned int llen = 0; int upload_cnt = INI_INT("max_file_uploads"); + int body_parts_cnt = INI_INT("max_multipart_body_parts"); const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(); php_rfc1867_getword_t getword; php_rfc1867_getword_conf_t getword_conf; @@ -708,6 +709,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ return; } + if (body_parts_cnt < 0) { + body_parts_cnt = PG(max_input_vars) + upload_cnt; + } + int body_parts_limit = body_parts_cnt; + /* Get the boundary */ boundary = strstr(content_type_dup, "boundary"); if (!boundary) { @@ -792,6 +798,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ char *pair = NULL; int end = 0; + if (--body_parts_cnt < 0) { + php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit); + goto fileupload_done; + } + while (isspace(*cd)) { ++cd; } diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt new file mode 100644 index 0000000000000..d2239ac3c410b --- /dev/null +++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt @@ -0,0 +1,53 @@ +--TEST-- +FPM: GHSA-54hq-v5wp-fqgv - max_multipart_body_parts ini custom value +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +echo $tester + ->request(stdin: [ + 'parts' => [ + 'count' => 30, + ] + ]) + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +Warning: Unknown: Multipart body parts limit exceeded 10. To increase the limit change max_multipart_body_parts in php.ini. in Unknown on line 0 +int(10) +--CLEAN-- + diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt new file mode 100644 index 0000000000000..42b5afbf9ee7d --- /dev/null +++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: GHSA-54hq-v5wp-fqgv - max_multipart_body_parts ini default +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +echo $tester + ->request(stdin: [ + 'parts' => [ + 'count' => 30, + ] + ]) + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +Warning: Unknown: Input variables exceeded 20. To increase the limit change max_input_vars in php.ini. in Unknown on line 0 + +Warning: Unknown: Multipart body parts limit exceeded 25. To increase the limit change max_multipart_body_parts in php.ini. in Unknown on line 0 +int(20) +--CLEAN-- + diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt new file mode 100644 index 0000000000000..da81174c72806 --- /dev/null +++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt @@ -0,0 +1,52 @@ +--TEST-- +FPM: GHSA-54hq-v5wp-fqgv - exceeding max_file_uploads +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +echo $tester + ->request(stdin: [ + 'parts' => [ + 'count' => 10, + 'param' => 'filename' + ] + ]) + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +Warning: Maximum number of allowable file uploads has been exceeded in Unknown on line 0 +int(5) +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 6197cdba53f5c..e51aa0f691435 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -567,13 +567,17 @@ class Tester * @param string $query * @param array $headers * @param string|null $uri + * @param string|null $scriptFilename + * @param string|null $stdin * * @return array */ private function getRequestParams( string $query = '', array $headers = [], - string $uri = null + string $uri = null, + string $scriptFilename = null, + ?string $stdin = null ): array { if (is_null($uri)) { $uri = $this->makeSourceFile(); @@ -582,8 +586,8 @@ class Tester $params = array_merge( [ 'GATEWAY_INTERFACE' => 'FastCGI/1.0', - 'REQUEST_METHOD' => 'GET', - 'SCRIPT_FILENAME' => $uri, + 'REQUEST_METHOD' => is_null($stdin) ? 'GET' : 'POST', + 'SCRIPT_FILENAME' => $scriptFilename ?: $uri, 'SCRIPT_NAME' => $uri, 'QUERY_STRING' => $query, 'REQUEST_URI' => $uri . ($query ? '?' . $query : ""), @@ -597,7 +601,7 @@ class Tester 'SERVER_PROTOCOL' => 'HTTP/1.1', 'DOCUMENT_ROOT' => __DIR__, 'CONTENT_TYPE' => '', - 'CONTENT_LENGTH' => 0 + 'CONTENT_LENGTH' => strlen($stdin ?? "") // Default to 0 ], $headers ); @@ -607,20 +611,86 @@ class Tester }); } + /** + * Parse stdin and generate data for multipart config. + * + * @param array $stdin + * @param array $headers + * + * @return void + * @throws \Exception + */ + private function parseStdin(array $stdin, array &$headers) + { + $parts = $stdin['parts'] ?? null; + if (empty($parts)) { + throw new \Exception('The stdin array needs to contain parts'); + } + $boundary = $stdin['boundary'] ?? 'AaB03x'; + if ( ! isset($headers['CONTENT_TYPE'])) { + $headers['CONTENT_TYPE'] = 'multipart/form-data; boundary=' . $boundary; + } + $count = $parts['count'] ?? null; + if ( ! is_null($count)) { + $dispositionType = $parts['disposition'] ?? 'form-data'; + $dispositionParam = $parts['param'] ?? 'name'; + $namePrefix = $parts['prefix'] ?? 'f'; + $nameSuffix = $parts['suffix'] ?? ''; + $value = $parts['value'] ?? 'test'; + $parts = []; + for ($i = 0; $i < $count; $i++) { + $parts[] = [ + 'disposition' => $dispositionType, + 'param' => $dispositionParam, + 'name' => "$namePrefix$i$nameSuffix", + 'value' => $value + ]; + } + } + $out = ''; + $nl = "\r\n"; + foreach ($parts as $part) { + if (!is_array($part)) { + $part = ['name' => $part]; + } elseif ( ! isset($part['name'])) { + throw new \Exception('Each part has to have a name'); + } + $name = $part['name']; + $dispositionType = $part['disposition'] ?? 'form-data'; + $dispositionParam = $part['param'] ?? 'name'; + $value = $part['value'] ?? 'test'; + $partHeaders = $part['headers'] ?? []; + + $out .= "--$boundary$nl"; + $out .= "Content-disposition: $dispositionType; $dispositionParam=\"$name\"$nl"; + foreach ($partHeaders as $headerName => $headerValue) { + $out .= "$headerName: $headerValue$nl"; + } + $out .= $nl; + $out .= "$value$nl"; + } + $out .= "--$boundary--$nl"; + + return $out; + } + /** * Execute request. * - * @param string $query - * @param array $headers - * @param string|null $uri - * @param string|null $address - * @param string|null $successMessage - * @param string|null $errorMessage - * @param bool $connKeepAlive - * @param bool $expectError - * @param int $readLimit + * @param string $query + * @param array $headers + * @param string|null $uri + * @param string|null $address + * @param string|null $successMessage + * @param string|null $errorMessage + * @param bool $connKeepAlive + * @param string|null $scriptFilename = null + * @param string|array|null $stdin = null + * @param bool $expectError + * @param int $readLimit * * @return Response + * @throws \Exception */ public function request( string $query = '', @@ -630,6 +700,8 @@ class Tester string $successMessage = null, string $errorMessage = null, bool $connKeepAlive = false, + string $scriptFilename = null, + string|array $stdin = null, bool $expectError = false, int $readLimit = -1, ): Response { @@ -637,12 +709,16 @@ class Tester return new Response(null, true); } - $params = $this->getRequestParams($query, $headers, $uri); + if (is_array($stdin)) { + $stdin = $this->parseStdin($stdin, $headers); + } + + $params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $stdin); $this->trace('Request params', $params); try { $this->response = new Response( - $this->getClient($address, $connKeepAlive)->request_data($params, false, $readLimit) + $this->getClient($address, $connKeepAlive)->request_data($params, $stdin, $readLimit) ); if ($expectError) { $this->error('Expected request error but the request was successful'); From 054c7b09f91946c0618171072fc650af2ff61f0a Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 14 Feb 2023 10:23:59 +0000 Subject: [PATCH 054/103] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index a6dfbec2629dc..f14370becbdb0 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS . Fixed bug #81746 (1-byte array overrun in common path resolve code). (CVE-2023-0568). (Niels Dossche) +- FPM + . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart + request body). (CVE-2023-0662) (Jakub Zelenka) + 05 Jan 2023, PHP 8.0.27 - PDO/SQLite: From caaaf759908a7366c877399273cafdd246c5402c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 14 Feb 2023 10:33:56 +0000 Subject: [PATCH 055/103] Fix incorrect character in NEWS --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f14370becbdb0..d0a31784b0141 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,7 @@ PHP NEWS - FPM . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart - request body). (CVE-2023-0662) (Jakub Zelenka) + request body). (CVE-2023-0662) (Jakub Zelenka) 05 Jan 2023, PHP 8.0.27 From eef29d434a302904dc0310032c38980b0dfaded0 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 14 Feb 2023 10:42:36 +0000 Subject: [PATCH 056/103] Change NEWS for GHSA-54hq-v5wp-fqgv as it is for all SAPIs --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d0a31784b0141..25a6a6e5d031a 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ PHP NEWS . Fixed bug #81746 (1-byte array overrun in common path resolve code). (CVE-2023-0568). (Niels Dossche) -- FPM +- SAPI . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart request body). (CVE-2023-0662) (Jakub Zelenka) From 937b1e38e2677cdc07ddc93e228765469f647e73 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Tue, 14 Feb 2023 10:46:48 +0000 Subject: [PATCH 057/103] Fix missing colon in NEWS --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 25a6a6e5d031a..ed5df77edfc82 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ PHP NEWS . Fixed bug #81746 (1-byte array overrun in common path resolve code). (CVE-2023-0568). (Niels Dossche) -- SAPI +- SAPI: . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart request body). (CVE-2023-0662) (Jakub Zelenka) From e86d8704b44dde164e36b5364036e1988ac566fe Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 14 Feb 2023 14:13:40 +0100 Subject: [PATCH 058/103] more config for new FPM tests --- sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt | 4 +++- .../fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt | 4 +++- sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt index d2239ac3c410b..d5c4c4d469871 100644 --- a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt @@ -21,7 +21,9 @@ php_admin_value[html_errors] = false php_admin_value[max_input_vars] = 20 php_admin_value[max_file_uploads] = 5 php_admin_value[max_multipart_body_parts] = 10 -php_flag[display_errors] = On +php_admin_flag[display_errors] = On +php_admin_flag[display_startup_errors] = On +php_admin_flag[log_errors] = On EOT; $code = << Date: Tue, 14 Feb 2023 15:18:53 +0100 Subject: [PATCH 059/103] [ci skip] Next release will be 8.0.29 --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ed5df77edfc82..9b41aeb1ed7d5 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.0.28 +?? ??? ????, PHP 8.0.29 + + +14 Feb 2023, PHP 8.0.28 - Core: . Fixed bug #81744 (Password_verify() always return true with some hash). From e35e6dc351aa9f9283ff9369cc76fc1cc209b3ed Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 14 Feb 2023 20:27:29 +0100 Subject: [PATCH 060/103] [ci skip] NEWS (#10586) --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 3a3043759b02b..f6eb0e8e09f30 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,7 @@ PHP NEWS function after bailout). (trowski) . Fixed bug GH-10168: use-after-free when utilizing assigned object freed during assignment. (nielsdos) + . Fixed SSA object type update for compound assignment opcodes. (nielsdos) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) From 586e81b25993eb1a7247af452512c785b170fde5 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 14 Feb 2023 13:43:08 -0600 Subject: [PATCH 061/103] Point to the issue tracker on GitHub --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ca3d695120da4..9aa8c5caf2e2d 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.17-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.17-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER From 843ba82b536ce0a3bf3d08030b378655440a75a3 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 14 Feb 2023 13:48:28 -0600 Subject: [PATCH 062/103] Use gtar if it's in the PATH --- scripts/dev/makedist | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/dev/makedist b/scripts/dev/makedist index ad5c3c01b2070..555e7680e2eeb 100755 --- a/scripts/dev/makedist +++ b/scripts/dev/makedist @@ -5,6 +5,10 @@ # Written by Stig Bakken 1997-05-28. # Adapted to Git by Stanislav Malyshev . +# Check whether gtar is present (GNU tar) +tar="$(which gtar)" +tar="${tar:-$(which tar)}" + # Go to project root directory. cd $(CDPATH= cd -- "$(dirname -- "$0")/../../" && pwd -P) @@ -124,7 +128,7 @@ fi # Export PHP. echo "makedist: Exporting $treeish from $git" -git archive --format=tar $remote_option --prefix=$prefix/ $treeish | tar xvf - || exit 4 +git archive --format=tar $remote_option --prefix=$prefix/ $treeish | "$tar" xvf - || exit 4 cd $prefix || exit 5 @@ -166,7 +170,7 @@ cd .. echo "" echo "makedist: Creating $prefix.tar archive." -tar cf "$prefix".tar "$prefix" +"$tar" cf "$prefix".tar "$prefix" rm -rf "$prefix" "$prefix".tar.* echo "makedist: Creating $prefix.tar.gz archive." From d9ac59b0a94676d1ab4da348ff8f59a0ec4e46c3 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 14 Feb 2023 14:13:01 -0600 Subject: [PATCH 063/103] Ensure tar is not bsdtar --- scripts/dev/makedist | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/dev/makedist b/scripts/dev/makedist index 555e7680e2eeb..38553d63d3151 100755 --- a/scripts/dev/makedist +++ b/scripts/dev/makedist @@ -9,6 +9,11 @@ tar="$(which gtar)" tar="${tar:-$(which tar)}" +if [[ $($tar --version) == *"bsdtar"* ]]; then + echo "Found bsdtar at $tar, but this script needs GNU tar." + exit 1 +fi + # Go to project root directory. cd $(CDPATH= cd -- "$(dirname -- "$0")/../../" && pwd -P) From 7b68ff46da9817a258f2679af1adc7977ce5e8c1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Feb 2023 14:07:17 +0100 Subject: [PATCH 064/103] Revert "Fix GH-10168: heap-buffer-overflow at zval_undefined_cv" This reverts commit 71ddede5655fe654002ae18af6a18e033f717287. --- NEWS | 2 - Zend/tests/gh10168_1.phpt | 32 --- Zend/tests/gh10168_2.phpt | 32 --- Zend/tests/gh10168_3.phpt | 30 --- Zend/zend_execute.c | 10 +- Zend/zend_execute.h | 50 +--- Zend/zend_vm_def.h | 20 +- Zend/zend_vm_execute.h | 504 +++++++++++++------------------------- 8 files changed, 193 insertions(+), 487 deletions(-) delete mode 100644 Zend/tests/gh10168_1.phpt delete mode 100644 Zend/tests/gh10168_2.phpt delete mode 100644 Zend/tests/gh10168_3.phpt diff --git a/NEWS b/NEWS index f6eb0e8e09f30..9cc8620f9f5d7 100644 --- a/NEWS +++ b/NEWS @@ -10,8 +10,6 @@ PHP NEWS Generator emits an unavoidable fatal error or crashes). (Arnaud) . Fixed bug GH-10437 (Segfault/assertion when using fibers in shutdown function after bailout). (trowski) - . Fixed bug GH-10168: use-after-free when utilizing assigned object freed - during assignment. (nielsdos) . Fixed SSA object type update for compound assignment opcodes. (nielsdos) - Curl: diff --git a/Zend/tests/gh10168_1.phpt b/Zend/tests/gh10168_1.phpt deleted file mode 100644 index 6433453ed2448..0000000000000 --- a/Zend/tests/gh10168_1.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -GH-10168 (heap-buffer-overflow at zval_undefined_cv): array variation ---FILE-- - 0; - var_dump(self::$instances); - } - - function __destruct() { - unset(self::$instances[NULL]); - } -} -new Test(); -new Test(); - -?> ---EXPECTF-- -Notice: Object of class Test could not be converted to int in %s on line %d -array(1) { - [""]=> - object(Test)#1 (0) { - } -} - -Notice: Object of class Test could not be converted to int in %s on line %d -array(0) { -} diff --git a/Zend/tests/gh10168_2.phpt b/Zend/tests/gh10168_2.phpt deleted file mode 100644 index abab8b72f1cb9..0000000000000 --- a/Zend/tests/gh10168_2.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign global variation ---FILE-- - 0; - // Destructor called after comparison, so a will be NULL - var_dump($GLOBALS['a']); - } - - function __destruct() { - unset($GLOBALS['a']); - } -} -new Test(); -new Test(); - -?> ---EXPECTF-- -Notice: Object of class Test could not be converted to int in %s on line %d -object(Test)#1 (0) { -} - -Notice: Object of class Test could not be converted to int in %s on line %d - -Warning: Undefined global variable $a in %s on line %d -NULL diff --git a/Zend/tests/gh10168_3.phpt b/Zend/tests/gh10168_3.phpt deleted file mode 100644 index 35c8ed42f8470..0000000000000 --- a/Zend/tests/gh10168_3.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop ---XFAIL-- ---FILE-- - ---EXPECTF-- -object(Test)#1 (0) { -} -object(Test)#2 (0) { -} diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 848d479651f86..a46a93ad96fcc 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3562,7 +3562,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { } } -ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr) +ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) { bool ret; zval value; @@ -3582,9 +3582,6 @@ ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *ori } else { zval_ptr_dtor_nogc(&value); } - if (result_variable_ptr) { - ZVAL_COPY(result_variable_ptr, variable_ptr); - } if (value_type & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(ref)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { @@ -3598,11 +3595,6 @@ ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *ori return variable_ptr; } -ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) -{ - return zend_assign_to_typed_ref_and_result(variable_ptr, orig_value, value_type, strict, NULL); -} - ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) { zval *val = orig_val; if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index eaad706cee3d5..bf7b2afdf88bc 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -108,7 +108,6 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret); ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); -ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr); ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict); static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) @@ -138,22 +137,12 @@ static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *v } } -static zend_always_inline void zend_handle_garbage_from_variable_assignment(zend_refcounted *garbage) -{ - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { /* we need to split */ - /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ - if (UNEXPECTED(GC_MAY_LEAK(garbage))) { - gc_possible_root(garbage); - } - } -} - static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) { do { if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + zend_refcounted *garbage; + if (Z_ISREF_P(variable_ptr)) { if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict); @@ -164,42 +153,21 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval break; } } - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + garbage = Z_COUNTED_P(variable_ptr); zend_copy_to_variable(variable_ptr, value, value_type); - zend_handle_garbage_from_variable_assignment(garbage); - return variable_ptr; - } - } while (0); - - zend_copy_to_variable(variable_ptr, value, value_type); - return variable_ptr; -} - -static zend_always_inline zval* zend_assign_to_two_variables(zval *result_variable_ptr, zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) -{ - do { - if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { - if (Z_ISREF_P(variable_ptr)) { - if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { - variable_ptr = zend_assign_to_typed_ref_and_result(variable_ptr, value, value_type, strict, result_variable_ptr); - return variable_ptr; - } - - variable_ptr = Z_REFVAL_P(variable_ptr); - if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { - break; + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { /* we need to split */ + /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ + if (UNEXPECTED(GC_MAY_LEAK(garbage))) { + gc_possible_root(garbage); } } - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); - zend_copy_to_variable(variable_ptr, value, value_type); - ZVAL_COPY(result_variable_ptr, variable_ptr); - zend_handle_garbage_from_variable_assignment(garbage); return variable_ptr; } } while (0); zend_copy_to_variable(variable_ptr, value, value_type); - ZVAL_COPY(result_variable_ptr, variable_ptr); return variable_ptr; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 09d7b95896ec8..4845a92b95a7e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2577,9 +2577,6 @@ ZEND_VM_C_LABEL(try_assign_dim_array): Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_CONST) { @@ -2591,11 +2588,10 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZEND_VM_C_GOTO(assign_dim_error); } value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -2689,14 +2685,12 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP1_VAR_PTR(); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6f1b9b49f725a..a5a5eabf2b037 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23464,9 +23464,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23478,11 +23475,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23616,9 +23612,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23630,11 +23623,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23769,9 +23761,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23783,11 +23772,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23922,9 +23910,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23936,11 +23921,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24033,14 +24017,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24055,14 +24037,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26183,9 +26163,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26197,11 +26174,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26335,9 +26311,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26349,11 +26322,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26488,9 +26460,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26502,11 +26471,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26641,9 +26609,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26655,11 +26620,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27382,14 +27346,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27404,14 +27366,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27470,14 +27430,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27492,14 +27450,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27738,9 +27694,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27752,11 +27705,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27890,9 +27842,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27904,11 +27853,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28043,9 +27991,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28057,11 +28002,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28196,9 +28140,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28210,11 +28151,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30430,9 +30370,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30444,11 +30381,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30582,9 +30518,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30596,11 +30529,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30735,9 +30667,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30749,11 +30678,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30888,9 +30816,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30902,11 +30827,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30999,14 +30923,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -31021,14 +30943,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41501,9 +41421,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41515,11 +41432,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41653,9 +41569,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41667,11 +41580,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41806,9 +41718,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41820,11 +41729,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41959,9 +41867,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41973,11 +41878,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -42070,13 +41974,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -42091,13 +41994,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45297,9 +45199,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45311,11 +45210,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45449,9 +45347,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45463,11 +45358,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45602,9 +45496,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45616,11 +45507,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45755,9 +45645,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45769,11 +45656,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -46784,13 +46670,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46805,13 +46690,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46856,13 +46740,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46877,13 +46760,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47295,9 +47177,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47309,11 +47188,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47447,9 +47325,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47461,11 +47336,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47600,9 +47474,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47614,11 +47485,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47753,9 +47623,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47767,11 +47634,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50648,9 +50514,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50662,11 +50525,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50800,9 +50662,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50814,11 +50673,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50953,9 +50811,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50967,11 +50822,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -51106,9 +50960,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ Z_ADDREF_P(value); } } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); - } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -51120,11 +50971,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -51217,13 +51067,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -51238,13 +51087,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); - } else { - zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZVAL_COPY(EX_VAR(opline->result.var), value); } - /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } From fd3cc17cbdca9f3fabb3780ce043ca9c1e91387e Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Feb 2023 13:21:18 +0000 Subject: [PATCH 065/103] Add max_multipart_body_parts info into php.ini files --- php.ini-development | 5 +++++ php.ini-production | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/php.ini-development b/php.ini-development index e61f19b87cace..c1aca130c380b 100644 --- a/php.ini-development +++ b/php.ini-development @@ -423,6 +423,11 @@ max_input_time = 60 ; How many GET/POST/COOKIE input variables may be accepted ;max_input_vars = 1000 +; How many multipart body parts (combined input variable and file uploads) may +; be accepted. +; Default Value: -1 (Sum of max_input_vars and max_file_uploads) +;max_multipart_body_parts = 1500 + ; Maximum amount of memory a script may consume ; https://php.net/memory-limit memory_limit = 128M diff --git a/php.ini-production b/php.ini-production index 73a4db3c31bd5..a90451fe6dca2 100644 --- a/php.ini-production +++ b/php.ini-production @@ -425,6 +425,11 @@ max_input_time = 60 ; How many GET/POST/COOKIE input variables may be accepted ;max_input_vars = 1000 +; How many multipart body parts (combined input variable and file uploads) may +; be accepted. +; Default Value: -1 (Sum of max_input_vars and max_file_uploads) +;max_multipart_body_parts = 1500 + ; Maximum amount of memory a script may consume ; https://php.net/memory-limit memory_limit = 128M From 52c96f21bef653eb62bb04582f2aaf17ec94367b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 17 Feb 2023 14:56:28 +0100 Subject: [PATCH 066/103] [skip ci] Skip slow tidy test on asan --- ext/tidy/tests/parsing_file_too_large.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/tidy/tests/parsing_file_too_large.phpt b/ext/tidy/tests/parsing_file_too_large.phpt index 603a588b4f8f0..abc64d5c17c37 100644 --- a/ext/tidy/tests/parsing_file_too_large.phpt +++ b/ext/tidy/tests/parsing_file_too_large.phpt @@ -6,6 +6,7 @@ tidy --INI-- memory_limit="5G" From 2fde3afffb5c20ffca896de913436f72d6c30e01 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 2 Dec 2022 11:56:40 +1100 Subject: [PATCH 067/103] ext/json: add php_json_scanner_defs.h as make target To prevent build failures like: make: *** No rule to make target '/code/master/ext/json/php_json_scanner_defs.h', needed by 'ext/json/json_scanner.lo'. Stop. --- ext/json/Makefile.frag | 4 ++-- ext/json/Makefile.frag.w32 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/json/Makefile.frag b/ext/json/Makefile.frag index f5fe3c3306598..d9b8f1349a506 100644 --- a/ext/json/Makefile.frag +++ b/ext/json/Makefile.frag @@ -1,5 +1,5 @@ -$(srcdir)/json_scanner.c: $(srcdir)/json_scanner.re +$(srcdir)/json_scanner.c $(srcdir)/php_json_scanner_defs.h: $(srcdir)/json_scanner.re $(srcdir)/json_parser.tab.h @$(RE2C) $(RE2C_FLAGS) -t $(srcdir)/php_json_scanner_defs.h --no-generation-date -bci -o $@ $(srcdir)/json_scanner.re -$(srcdir)/json_parser.tab.c: $(srcdir)/json_parser.y +$(srcdir)/json_parser.tab.c $(srcdir)/json_parser.tab.h: $(srcdir)/json_parser.y @$(YACC) $(YFLAGS) --defines -l $(srcdir)/json_parser.y -o $@ diff --git a/ext/json/Makefile.frag.w32 b/ext/json/Makefile.frag.w32 index 1463eda70b7ad..75250626dce68 100644 --- a/ext/json/Makefile.frag.w32 +++ b/ext/json/Makefile.frag.w32 @@ -1,5 +1,5 @@ -ext\json\json_scanner.c: ext\json\json_scanner.re +ext\json\json_scanner.c ext\json\php_json_scanner_defs.h: ext\json\json_scanner.re ext\json\json_parser.tab.h $(RE2C) $(RE2C_FLAGS) -t ext/json/php_json_scanner_defs.h --no-generation-date -bci -o ext/json/json_scanner.c ext/json/json_scanner.re -ext\json\json_parser.tab.c: ext\json\json_parser.y +ext\json\json_parser.tab.c ext\json\json_parser.tab.h: ext\json\json_parser.y $(BISON) --defines -l ext/json/json_parser.y -o ext/json/json_parser.tab.c From e83cda0887f8f9a243b42eb4e808b45c5f138cf8 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 2 Dec 2022 13:37:40 +1100 Subject: [PATCH 068/103] ext/Zend: zend_language_scanner_defs.h as make target --- Zend/Makefile.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/Makefile.frag b/Zend/Makefile.frag index 1e0dc92803da8..054a63bf60af5 100644 --- a/Zend/Makefile.frag +++ b/Zend/Makefile.frag @@ -5,7 +5,7 @@ $(builddir)/zend_language_scanner.lo: $(srcdir)/zend_language_parser.h $(builddir)/zend_ini_scanner.lo: $(srcdir)/zend_ini_parser.h -$(srcdir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l +$(srcdir)/zend_language_scanner.c $(srcdir)/zend_language_scanner_defs.h: $(srcdir)/zend_language_scanner.l @(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l) $(srcdir)/zend_language_parser.h: $(srcdir)/zend_language_parser.c From 2b3fa5edacea1af3bf6e915d65d8d36ac5e26689 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 6 Dec 2022 09:26:46 +1100 Subject: [PATCH 069/103] zend win32 RE2C header files to Make targets and generated_files like zend_ini_parser.h, list zend_ini_scanner_defs.h and zend_language_scanner_defs.h. Add all these files to generated_files so they don't get missed. --- win32/build/Makefile | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/win32/build/Makefile b/win32/build/Makefile index 9d063549113aa..64dc71660a0e3 100644 --- a/win32/build/Makefile +++ b/win32/build/Makefile @@ -59,14 +59,17 @@ all: generated_files $(EXT_TARGETS) $(PECL_TARGETS) $(SAPI_TARGETS) build_dirs: $(BUILD_DIR) $(BUILD_DIRS_SUB) $(BUILD_DIR_DEV) !if $(RE2C) == "" -generated_files: build_dirs Zend\zend_ini_parser.c \ +generated_files: build_dirs \ + Zend\zend_ini_parser.c Zend\zend_ini_parser.h \ Zend\zend_language_parser.c \ sapi\phpdbg\phpdbg_parser.c \ $(PHPDEF) $(MCFILE) !else -generated_files: build_dirs Zend\zend_ini_parser.c \ - Zend\zend_language_parser.c Zend\zend_ini_scanner.c \ - Zend\zend_language_scanner.c \ +generated_files: build_dirs \ + Zend\zend_ini_parser.c Zend\zend_ini_parser.h \ + Zend\zend_language_parser.c \ + Zend\zend_ini_scanner.c Zend\zend_ini_scanner_defs.h \ + Zend\zend_language_scanner.c Zend\zend_language_scanner_defs.h \ sapi\phpdbg\phpdbg_parser.c sapi\phpdbg\phpdbg_lexer.c \ $(PHPDEF) $(MCFILE) !endif @@ -87,10 +90,10 @@ sapi\phpdbg\phpdbg_parser.c sapi\phpdbg\phpdbg_parser.h: sapi\phpdbg\phpdbg_pars $(BISON) --output=sapi/phpdbg/phpdbg_parser.c -v -d sapi/phpdbg/phpdbg_parser.y !if $(RE2C) != "" -Zend\zend_ini_scanner.c: Zend\zend_ini_scanner.l +Zend\zend_ini_scanner.c Zend\zend_ini_scanner_defs.h: Zend\zend_ini_scanner.l $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_ini_scanner_defs.h -oZend/zend_ini_scanner.c Zend/zend_ini_scanner.l -Zend\zend_language_scanner.c: Zend\zend_language_scanner.l +Zend\zend_language_scanner.c Zend\zend_language_scanner_defs.h: Zend\zend_language_scanner.l $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l sapi\phpdbg\phpdbg_lexer.c: sapi\phpdbg\phpdbg_lexer.l From 4f731fa2ecd646e8792b18c0ea0ac1e24e8ee561 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Feb 2023 15:55:55 +0000 Subject: [PATCH 070/103] Fix php_json_scanner_defs.h target in ext/json/Makefile.frag --- ext/json/Makefile.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/json/Makefile.frag b/ext/json/Makefile.frag index d9b8f1349a506..45687a11b7bf5 100644 --- a/ext/json/Makefile.frag +++ b/ext/json/Makefile.frag @@ -1,5 +1,5 @@ $(srcdir)/json_scanner.c $(srcdir)/php_json_scanner_defs.h: $(srcdir)/json_scanner.re $(srcdir)/json_parser.tab.h - @$(RE2C) $(RE2C_FLAGS) -t $(srcdir)/php_json_scanner_defs.h --no-generation-date -bci -o $@ $(srcdir)/json_scanner.re + @$(RE2C) $(RE2C_FLAGS) -t $(srcdir)/php_json_scanner_defs.h --no-generation-date -bci -o $(srcdir)/json_scanner.c $(srcdir)/json_scanner.re $(srcdir)/json_parser.tab.c $(srcdir)/json_parser.tab.h: $(srcdir)/json_parser.y - @$(YACC) $(YFLAGS) --defines -l $(srcdir)/json_parser.y -o $@ + @$(YACC) $(YFLAGS) --defines -l $(srcdir)/json_parser.y -o $(srcdir)/json_parser.tab.c From a9e4f5184412013c973224530c78281a7a2a8dfb Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Feb 2023 16:36:43 +0000 Subject: [PATCH 071/103] Update NEWS with scanner and parser build fixes --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 9cc8620f9f5d7..7bb57d67e97cd 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ PHP NEWS . Fixed bug GH-10437 (Segfault/assertion when using fibers in shutdown function after bailout). (trowski) . Fixed SSA object type update for compound assignment opcodes. (nielsdos) + . Fixed language scanner generation build. (Daniel Black) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) @@ -30,6 +31,10 @@ PHP NEWS . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) . Fixed bug GH-10385 (FPM successful config test early exit). (nielsdos) +- JSON: + . Fixed JSON scanner and parser generation build. + (Daniel Black, Jakub Zelenka) + - Opcache: . Fix incorrect page_size check. (nielsdos) From ae16471628be04b9c4c4c5eaf99e70452bb2514f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Feb 2023 15:31:37 +0100 Subject: [PATCH 072/103] Fix GH-10623: ReflectionFunction::getClosureUsedVariables() returns empty array in presence of variadic arguments The code was missing the handling for the RECV_VARIADIC instruction. Additional regression test for GH-10623 Co-authored-by: Fabio Ivona --- NEWS | 4 ++ ext/reflection/php_reflection.c | 4 ++ ext/reflection/tests/gh10623.phpt | 64 +++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 ext/reflection/tests/gh10623.phpt diff --git a/NEWS b/NEWS index 7bb57d67e97cd..4071ddef406c3 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,10 @@ PHP NEWS - Phar: . Fix incorrect check in phar tar parsing. (nielsdos) +- Reflection: + . Fixed bug GH-10623 (Reflection::getClosureUsedVariables opcode fix with + variadic arguments). (nielsdos) + - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 8b53e4fced9b4..f4fc588a3101d 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1747,6 +1747,10 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureUsedVariables) } zend_op *opline = ops->opcodes + ops->num_args; + if (ops->fn_flags & ZEND_ACC_VARIADIC) { + ZEND_ASSERT(opline->opcode == ZEND_RECV_VARIADIC); + opline++; + } for (; opline->opcode == ZEND_BIND_STATIC; opline++) { if (!(opline->extended_value & (ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))) { diff --git a/ext/reflection/tests/gh10623.phpt b/ext/reflection/tests/gh10623.phpt new file mode 100644 index 0000000000000..6e564fb5186d8 --- /dev/null +++ b/ext/reflection/tests/gh10623.phpt @@ -0,0 +1,64 @@ +--TEST-- +GH-10623 (ReflectionFunction::getClosureUsedVariables() returns empty array in presence of variadic arguments) +--FILE-- +getClosureUsedVariables()); + +$closure = function($var, ...$variadic) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +$closure = function($var, ...$variadic) use($data1) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +$closure = function($var, ...$variadic) use($data1, $data2, $data3) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +$closure = function(...$variadic) use($data1) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +$closure = function($var, $var2, ...$variadic) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +$closure = function($var, $var2, $var3, ...$variadic) use($data1, $data2, $data3) {}; +var_dump((new ReflectionFunction($closure))->getClosureUsedVariables()); + +?> +--EXPECT-- +array(1) { + ["data1"]=> + int(1) +} +array(0) { +} +array(1) { + ["data1"]=> + int(1) +} +array(3) { + ["data1"]=> + int(1) + ["data2"]=> + int(2) + ["data3"]=> + int(3) +} +array(1) { + ["data1"]=> + int(1) +} +array(0) { +} +array(3) { + ["data1"]=> + int(1) + ["data2"]=> + int(2) + ["data3"]=> + int(3) +} From 243865ae5747e9147bacc7d7199909001b0286bd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 7 Feb 2023 12:26:19 +0100 Subject: [PATCH 073/103] ext/mbstring: fix new_value length check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8bbd0952e5bba88 added a check rejecting empty strings; in the merge commiot 379d9a1cfc6462 however it was changed to a NULL check, one that did not make sense because ZSTR_VAL() is guaranteed to never be NULL; the length check was accidently removed by that merge commit. This bug was found by GCC's -Waddress warning: ext/mbstring/mbstring.c:748:27: warning: the comparison will always evaluate as ‘true’ for the address of ‘val’ will never be NULL [-Waddress] 748 | if (!new_value || !ZSTR_VAL(new_value)) { | ^ Closes GH-10532 Signed-off-by: George Peter Banyard --- NEWS | 5 ++++- ext/mbstring/mbstring.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 4071ddef406c3..964473c1a42f7 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,9 @@ PHP NEWS . Fixed JSON scanner and parser generation build. (Daniel Black, Jakub Zelenka) +- MBString: + . ext/mbstring: fix new_value length check. (Max Kellermann) + - Opcache: . Fix incorrect page_size check. (nielsdos) @@ -71,7 +74,7 @@ PHP NEWS - SAPI: . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart request body). (CVE-2023-0662) (Jakub Zelenka) - + 02 Feb 2023, PHP 8.1.15 - Apache: diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 40b8acc65fa23..7a210cc347df1 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -745,7 +745,7 @@ static PHP_INI_MH(OnUpdate_mbstring_http_input) php_error_docref("ref.mbstring", E_DEPRECATED, "Use of mbstring.http_input is deprecated"); } - if (!new_value || !ZSTR_VAL(new_value)) { + if (!new_value || !ZSTR_LEN(new_value)) { const char *encoding = php_get_input_encoding(); MBSTRG(http_input_set) = 0; _php_mb_ini_mbstring_http_input_set(encoding, strlen(encoding)); From ed0c0df351e03870b39243ae247bf396045d0998 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Feb 2023 21:43:34 +0100 Subject: [PATCH 074/103] Fix GH-10627: mb_convert_encoding crashes PHP on Windows Fixes GH-10627 The php_mb_convert_encoding() function can return NULL on error, but this case was not handled, which led to a NULL pointer dereference and hence a crash. Closes GH-10628 Signed-off-by: George Peter Banyard --- NEWS | 1 + ext/mbstring/mbstring.c | 9 +++++++++ ext/mbstring/tests/gh10627.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 ext/mbstring/tests/gh10627.phpt diff --git a/NEWS b/NEWS index 964473c1a42f7..26313b462f9cc 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,7 @@ PHP NEWS - MBString: . ext/mbstring: fix new_value length check. (Max Kellermann) + . Fix bug GH-10627 (mb_convert_encoding crashes PHP on Windows). (nielsdos) - Opcache: . Fix incorrect page_size check. (nielsdos) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 7a210cc347df1..87998a8a2f0c0 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2446,6 +2446,9 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons ckey = php_mb_convert_encoding( ZSTR_VAL(key), ZSTR_LEN(key), to_encoding, from_encodings, num_from_encodings, &ckey_len); + if (!ckey) { + continue; + } key = zend_string_init(ckey, ckey_len, 0); efree(ckey); } @@ -2457,6 +2460,12 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons cval = php_mb_convert_encoding( Z_STRVAL_P(entry), Z_STRLEN_P(entry), to_encoding, from_encodings, num_from_encodings, &cval_len); + if (!cval) { + if (key) { + zend_string_release(key); + } + continue; + } ZVAL_STRINGL(&entry_tmp, cval, cval_len); efree(cval); break; diff --git a/ext/mbstring/tests/gh10627.phpt b/ext/mbstring/tests/gh10627.phpt new file mode 100644 index 0000000000000..30dd4e227f39e --- /dev/null +++ b/ext/mbstring/tests/gh10627.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-10627 (mb_convert_encoding crashes PHP on Windows) +--EXTENSIONS-- +mbstring +--FILE-- + 'abc', 'abc' => 'def']; +var_dump(mb_convert_encoding($data, 'UTF-8', 'auto')); + +?> +--EXPECTF-- +Warning: mb_convert_encoding(): Unable to detect character encoding in %s on line %d +array(1) { + [1]=> + string(3) "abc" +} + +Warning: mb_convert_encoding(): Unable to detect character encoding in %s on line %d +array(1) { + ["abc"]=> + string(3) "def" +} From 08e759120690520e99f9f2d38afeb21bcd1de197 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 20 Feb 2023 19:42:35 +0300 Subject: [PATCH 075/103] Fix (at lease part of the) #GH-10635: ARM64 function JIT causes impossible assertion --- ext/opcache/jit/zend_jit_arm64.dasc | 10 +++++----- ext/opcache/jit/zend_jit_x86.dasc | 10 +++++----- ext/opcache/tests/jit/gh10635.phpt | 28 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 ext/opcache/tests/jit/gh10635.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 7bca5be068b18..432d3a6b1e9bb 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -12349,7 +12349,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, type_loaded = 1; prop_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1, 0); if (opline->opcode == ZEND_FETCH_OBJ_W - && (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS))) { + && (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT)))) { uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS; | ldr REG0, EX->run_time_cache @@ -12833,7 +12833,7 @@ static int zend_jit_incdec_obj(dasm_State **Dst, | ldr TMP1, [FCARG1x, #offsetof(zend_object, ce)] | cmp REG2, TMP1 | bne >7 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | MEM_ACCESS_64_WITH_UOFFSET ldr, TMP1, REG0, (opline->extended_value + sizeof(void*) * 2), TMP1 | cbnz TMP1, >7 } @@ -13267,7 +13267,7 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, | ldr TMP2, [FCARG1x, #offsetof(zend_object, ce)] | cmp REG2, TMP2 | bne >7 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | MEM_ACCESS_64_WITH_UOFFSET ldr, TMP1, REG0, ((opline+1)->extended_value + sizeof(void*) * 2), TMP1 | cbnz TMP1, >7 } @@ -13645,7 +13645,7 @@ static int zend_jit_assign_obj(dasm_State **Dst, | ldr TMP1, [FCARG1x, #offsetof(zend_object, ce)] | cmp REG2, TMP1 | bne >5 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | MEM_ACCESS_64_WITH_UOFFSET ldr, FCARG2x, REG0, (opline->extended_value + sizeof(void*) * 2), TMP1 } | MEM_ACCESS_64_WITH_UOFFSET ldr, REG0, REG0, (opline->extended_value + sizeof(void*)), TMP1 @@ -13656,7 +13656,7 @@ static int zend_jit_assign_obj(dasm_State **Dst, | IF_TYPE TMP1w, IS_UNDEF, >5 | mov FCARG1x, TMP2 prop_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1, 0); - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | cbnz FCARG2x, >1 |.cold_code |1: diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index af4500d9835a1..6749f8a1e1cc7 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -13075,7 +13075,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, type_loaded = 1; prop_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1, 0); if (opline->opcode == ZEND_FETCH_OBJ_W - && (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS))) { + && (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT)))) { uint32_t flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS; | mov r0, EX->run_time_cache @@ -13571,7 +13571,7 @@ static int zend_jit_incdec_obj(dasm_State **Dst, | mov r2, aword [r0 + opline->extended_value] | cmp r2, aword [FCARG1a + offsetof(zend_object, ce)] | jne >7 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | cmp aword [r0 + opline->extended_value + sizeof(void*) * 2], 0 | jnz >7 } @@ -14044,7 +14044,7 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, | mov r2, aword [r0 + (opline+1)->extended_value] | cmp r2, aword [FCARG1a + offsetof(zend_object, ce)] | jne >7 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | cmp aword [r0 + (opline+1)->extended_value + sizeof(void*) * 2], 0 | jnz >7 } @@ -14463,7 +14463,7 @@ static int zend_jit_assign_obj(dasm_State **Dst, | mov r2, aword [r0 + opline->extended_value] | cmp r2, aword [FCARG1a + offsetof(zend_object, ce)] | jne >5 - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | mov FCARG2a, aword [r0 + opline->extended_value + sizeof(void*) * 2] } | mov r0, aword [r0 + opline->extended_value + sizeof(void*)] @@ -14472,7 +14472,7 @@ static int zend_jit_assign_obj(dasm_State **Dst, | IF_TYPE byte [FCARG1a + r0 + 8], IS_UNDEF, >5 | add FCARG1a, r0 prop_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1, 0); - if (!ce || ce_is_instanceof || (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) { + if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) { | test FCARG2a, FCARG2a | jnz >1 |.cold_code diff --git a/ext/opcache/tests/jit/gh10635.phpt b/ext/opcache/tests/jit/gh10635.phpt new file mode 100644 index 0000000000000..0f4b43c033b40 --- /dev/null +++ b/ext/opcache/tests/jit/gh10635.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-10635: Function JIT causes impossible assertion +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +a); + } +} +class C { + use T; + private array $a = [1]; +} +$o = new C; +$o->foo(); +unset($o); +$o = new C; +$o->foo(); +unset($o); +?> +DONE +--EXPECT-- +DONE From 70ff10af7211a0551bfdf7e4397f83e4e9a95c46 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 21 Feb 2023 09:25:51 +0300 Subject: [PATCH 076/103] Fix GH-10635: ARM64 function JIT causes impossible assertion (#10638) --- ext/opcache/jit/zend_jit_arm64.dasc | 4 +++- ext/opcache/jit/zend_jit_x86.dasc | 4 +++- ext/opcache/tests/jit/identical_003.phpt | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/identical_003.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 432d3a6b1e9bb..16d0f458e6c3d 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -7722,7 +7722,6 @@ static int zend_jit_identical(dasm_State **Dst, } op1_addr = real_addr; } - | LOAD_ZVAL_ADDR FCARG1x, op1_addr } if (opline->op2_type != IS_CONST) { if (Z_MODE(op2_addr) == IS_REG) { @@ -7734,6 +7733,9 @@ static int zend_jit_identical(dasm_State **Dst, } | LOAD_ZVAL_ADDR FCARG2x, op2_addr } + if (opline->op1_type != IS_CONST) { + | LOAD_ZVAL_ADDR FCARG1x, op1_addr + } } if ((op1_info & op2_info & MAY_BE_ANY) == 0) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 6749f8a1e1cc7..bc0c9520d6f9b 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8309,7 +8309,6 @@ static int zend_jit_identical(dasm_State **Dst, } op1_addr = real_addr; } - | LOAD_ZVAL_ADDR FCARG1a, op1_addr } if (opline->op2_type != IS_CONST) { if (Z_MODE(op2_addr) == IS_REG) { @@ -8321,6 +8320,9 @@ static int zend_jit_identical(dasm_State **Dst, } | LOAD_ZVAL_ADDR FCARG2a, op2_addr } + if (opline->op1_type != IS_CONST) { + | LOAD_ZVAL_ADDR FCARG1a, op1_addr + } } if ((op1_info & op2_info & MAY_BE_ANY) == 0) { diff --git a/ext/opcache/tests/jit/identical_003.phpt b/ext/opcache/tests/jit/identical_003.phpt new file mode 100644 index 0000000000000..389fc366c24ad --- /dev/null +++ b/ext/opcache/tests/jit/identical_003.phpt @@ -0,0 +1,19 @@ +--TEST-- +JIT IDENTICAL: 003 register allocation +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +bool(true) From d51eb1d74ce75b0b77dd444a7fb83edace917651 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 21 Feb 2023 11:06:12 +0100 Subject: [PATCH 077/103] Zend/zend_ini: fix zend_result return values The value "1" was illegal. Signed-off-by: George Peter Banyard --- Zend/zend_ini.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index baef011023c84..1b4710eb503a0 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -57,7 +57,7 @@ static zend_result zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stag } if (stage == ZEND_INI_STAGE_RUNTIME && result == FAILURE) { /* runtime failure is OK */ - return 1; + return FAILURE; } if (ini_entry->value != ini_entry->orig_value) { zend_string_release(ini_entry->value); @@ -68,7 +68,7 @@ static zend_result zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stag ini_entry->orig_value = NULL; ini_entry->orig_modifiable = 0; } - return 0; + return SUCCESS; } /* }}} */ From ed4dc39e7fb8cf7e343aa6f654314e753a6107f0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 21 Feb 2023 11:06:48 +0100 Subject: [PATCH 078/103] ext/curl/interface: fix zend_result return value Closes GH-10640 Signed-off-by: George Peter Banyard --- ext/curl/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 36300dacfcfba..7eb081700c2ef 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2051,7 +2051,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields postval = Z_STR_P(prop); if (php_check_open_basedir(ZSTR_VAL(postval))) { - return 1; + return FAILURE; } prop = zend_read_property(curl_CURLFile_class, Z_OBJ_P(current), "mime", sizeof("mime")-1, 0, &rv); From f592f75e9c42c5b5758da3cf68b442bc408e18db Mon Sep 17 00:00:00 2001 From: ndossche Date: Mon, 20 Feb 2023 14:32:45 +0100 Subject: [PATCH 079/103] Add missing error check on tidyLoadConfig Parse errors were not reported for the default config, they were only reported when explicitly another config was loaded. This means that users may not be aware of errors in their configuration and therefore the behaviour of Tidy might not be what they intended. This patch fixes that issue by using a common function. In fact, the check for -1 might be enough for the current implementation of Tidy, but the Tidy docs say that any value other than 0 indicates an error. So future errors might not be caught when just using an error code of -1. Therefore, this also changes the error code checks of == -1 to < 0 and == 1 to > 0. Closes GH-10636 Signed-off-by: George Peter Banyard --- NEWS | 1 + ext/tidy/tests/019.phpt | 6 +++--- ext/tidy/tests/gh10636.phpt | 12 ++++++++++++ ext/tidy/tests/gh10636_config | 1 + ext/tidy/tidy.c | 23 ++++++++++++----------- 5 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 ext/tidy/tests/gh10636.phpt create mode 100644 ext/tidy/tests/gh10636_config diff --git a/NEWS b/NEWS index 26313b462f9cc..50476cd4fa64d 100644 --- a/NEWS +++ b/NEWS @@ -63,6 +63,7 @@ PHP NEWS - Tidy: . Fix memory leaks when attempting to open a non-existing file or a file over 4GB. (Girgias) + . Add missing error check on tidyLoadConfig. (nielsdos) 14 Feb 2023, PHP 8.1.16 diff --git a/ext/tidy/tests/019.phpt b/ext/tidy/tests/019.phpt index 20a15c7018ce2..444ecc155a45c 100644 --- a/ext/tidy/tests/019.phpt +++ b/ext/tidy/tests/019.phpt @@ -28,13 +28,13 @@ tidy_repair_file($l, $l, $l ,$l); // This doesn't emit any warning, TODO look in echo "Done\n"; ?> --EXPECTF-- -Warning: tidy_repair_string(): Could not load configuration file "1" in %s on line %d +Warning: tidy_repair_string(): Could not load the Tidy configuration file "1" in %s on line %d Warning: tidy_repair_string(): Could not set encoding "1" in %s on line %d -Warning: tidy_repair_string(): Could not load configuration file "" in %s on line %d +Warning: tidy_repair_string(): Could not load the Tidy configuration file "" in %s on line %d -Warning: tidy_repair_string(): Could not load configuration file "1" in %s on line %d +Warning: tidy_repair_string(): Could not load the Tidy configuration file "1" in %s on line %d Warning: tidy_repair_string(): Could not set encoding "1" in %s on line %d Path cannot be empty diff --git a/ext/tidy/tests/gh10636.phpt b/ext/tidy/tests/gh10636.phpt new file mode 100644 index 0000000000000..ce0aa3c08d1b2 --- /dev/null +++ b/ext/tidy/tests/gh10636.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-10636 (Tidy does not output notice when it encountered parse errors in the default configuration file) +--EXTENSIONS-- +tidy +--INI-- +tidy.default_config={PWD}/gh10636_config +--FILE-- + +--EXPECTF-- +Notice: main(): There were errors while parsing the Tidy configuration file "%sgh10636_config" in %s on line %d diff --git a/ext/tidy/tests/gh10636_config b/ext/tidy/tests/gh10636_config new file mode 100644 index 0000000000000..d9c4755a2d744 --- /dev/null +++ b/ext/tidy/tests/gh10636_config @@ -0,0 +1 @@ +indent:@ diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index 1d757f44fae76..5e9961963e231 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -79,14 +79,7 @@ _php_tidy_apply_config_array(_doc, _val_ht); \ } else if (_val_str) { \ TIDY_OPEN_BASE_DIR_CHECK(ZSTR_VAL(_val_str)); \ - switch (tidyLoadConfig(_doc, ZSTR_VAL(_val_str))) { \ - case -1: \ - php_error_docref(NULL, E_WARNING, "Could not load configuration file \"%s\"", ZSTR_VAL(_val_str)); \ - break; \ - case 1: \ - php_error_docref(NULL, E_NOTICE, "There were errors while parsing the configuration file \"%s\"", ZSTR_VAL(_val_str)); \ - break; \ - } \ + php_tidy_load_config(_doc, ZSTR_VAL(_val_str)); \ } @@ -143,9 +136,7 @@ if (php_check_open_basedir(filename)) { \ #define TIDY_SET_DEFAULT_CONFIG(_doc) \ if (TG(default_config) && TG(default_config)[0]) { \ - if (tidyLoadConfig(_doc, TG(default_config)) < 0) { \ - php_error_docref(NULL, E_WARNING, "Unable to load Tidy configuration file at \"%s\"", TG(default_config)); \ - } \ + php_tidy_load_config(_doc, TG(default_config)); \ } /* }}} */ @@ -269,6 +260,16 @@ static void TIDY_CALL php_tidy_panic(ctmbstr msg) php_error_docref(NULL, E_ERROR, "Could not allocate memory for tidy! (Reason: %s)", (char *)msg); } +static void php_tidy_load_config(TidyDoc doc, const char *path) +{ + int ret = tidyLoadConfig(doc, path); + if (ret < 0) { + php_error_docref(NULL, E_WARNING, "Could not load the Tidy configuration file \"%s\"", path); + } else if (ret > 0) { + php_error_docref(NULL, E_NOTICE, "There were errors while parsing the Tidy configuration file \"%s\"", path); + } +} + static int _php_tidy_set_tidy_opt(TidyDoc doc, char *optname, zval *value) { TidyOption opt = tidyGetOptionByName(doc, optname); From 8cac8306c3f5a8bcb1a147249737190e9f037577 Mon Sep 17 00:00:00 2001 From: ndossche Date: Mon, 20 Feb 2023 10:56:10 +0100 Subject: [PATCH 080/103] Fix incorrect error check in browsecap for pcre2_match() pcre2_match() returns error codes < 0, but only the "no match" error code was handled. Fix it by changing the check to >= 0. Closes GH-10632 Signed-off-by: George Peter Banyard --- NEWS | 1 + ext/standard/browscap.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 50476cd4fa64d..49be30909084c 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,7 @@ PHP NEWS . Fix incorrect check in cs_8559_5 in map_from_unicode(). (nielsdos) . Fix bug GH-9697 for reset/end/next/prev() attempting to move pointer of properties table for certain internal classes such as FFI classes + . Fix incorrect error check in browsecap for pcre2_match(). (nielsdos) - Tidy: . Fix memory leaks when attempting to open a non-existing file or a file over diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 2b6cd4e63f6cb..490acac2f99a5 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -612,7 +612,7 @@ static int browser_reg_compare(browscap_entry *entry, zend_string *agent_name, b } rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(agent_name), ZSTR_LEN(agent_name), 0, 0, match_data, php_pcre_mctx()); php_pcre_free_match_data(match_data); - if (PCRE2_ERROR_NOMATCH != rc) { + if (rc >= 0) { /* If we've found a possible browser, we need to do a comparison of the number of characters changed in the user agent being checked versus the previous match found and the current match. */ From 74c880edd12628c581720ae64a822a7b12e5388f Mon Sep 17 00:00:00 2001 From: nielsdos <7771979+nielsdos@users.noreply.github.com> Date: Mon, 20 Feb 2023 17:05:40 +0100 Subject: [PATCH 081/103] Fix Tidy tests failing due to different spelling On my system, with Tidy 5.7.45, I get the following error diff for two tests: 002+ line 1 column 7 - Error: is not recognised! 002- line 1 column 7 - Error: is not recognized! As we can see, the spelling of recognised is different. Use an EXPECTF and %c to mitigate this issue. Signed-off-by: George Peter Banyard --- ext/tidy/tests/006.phpt | 4 ++-- ext/tidy/tests/008.phpt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/tidy/tests/006.phpt b/ext/tidy/tests/006.phpt index 6197f6d362513..a01121deee4be 100644 --- a/ext/tidy/tests/006.phpt +++ b/ext/tidy/tests/006.phpt @@ -8,9 +8,9 @@ tidy echo tidy_get_error_buffer($a); ?> ---EXPECT-- +--EXPECTF-- line 1 column 1 - Warning: missing declaration -line 1 column 7 - Error: is not recognized! +line 1 column 7 - Error: is not recogni%ced! line 1 column 7 - Warning: discarding unexpected line 1 column 17 - Warning: discarding unexpected line 1 column 7 - Warning: inserting missing 'title' element diff --git a/ext/tidy/tests/008.phpt b/ext/tidy/tests/008.phpt index b6cf26a521abc..bb3b779b67b59 100644 --- a/ext/tidy/tests/008.phpt +++ b/ext/tidy/tests/008.phpt @@ -7,9 +7,9 @@ tidy $a = tidy_parse_string(""); echo $a->errorBuffer; ?> ---EXPECT-- +--EXPECTF-- line 1 column 1 - Warning: missing declaration -line 1 column 7 - Error: is not recognized! +line 1 column 7 - Error: is not recogni%ced! line 1 column 7 - Warning: discarding unexpected line 1 column 17 - Warning: discarding unexpected line 1 column 7 - Warning: inserting missing 'title' element From da3ce6015dea228b5aacc2c242977bf996a941af Mon Sep 17 00:00:00 2001 From: nielsdos <7771979+nielsdos@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:40:41 +0100 Subject: [PATCH 082/103] Propagate errors correctly in ps_files_cleanup_dir() In SessionHandler::gc, we use a virtual call to PS(default_mod)->s_gc to call the gc implementation. That return value is checked against FAILURE (-1). One of the call targets of PS(default_mod)->s_gc is ps_gc_files(). ps_gc_files() calls to ps_files_cleanup_dir(). The latter function has some error checks and outputs a notice if something goes wrong. In cases of errors, the function returns 0. This means that the check in SessionHandler::gc will misinterpret this as a success and report that 0 files have been *successfully* cleaned up. Fix it by returning -1 to indicate something *did* go wrong. Closes GH-10644. --- NEWS | 4 ++++ ext/session/mod_files.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 49be30909084c..6f2cd00955898 100644 --- a/NEWS +++ b/NEWS @@ -53,6 +53,10 @@ PHP NEWS . Fixed bug GH-10623 (Reflection::getClosureUsedVariables opcode fix with variadic arguments). (nielsdos) +- Session: + . Fixed ps_files_cleanup_dir() on failure code paths with -1 instead of 0 as + the latter was considered success by callers. (nielsdos). + - Standard: . Fixed bug GH-10292 (Made the default value of the first param of srand() and mt_srand() unknown). (kocsismate) diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 1da25ba583eaa..e774de74e63a0 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -292,7 +292,7 @@ static int ps_files_cleanup_dir(const char *dirname, zend_long maxlifetime) dir = opendir(dirname); if (!dir) { php_error_docref(NULL, E_NOTICE, "ps_files_cleanup_dir: opendir(%s) failed: %s (%d)", dirname, strerror(errno), errno); - return (0); + return -1; } time(&now); @@ -302,7 +302,7 @@ static int ps_files_cleanup_dir(const char *dirname, zend_long maxlifetime) if (dirname_len >= MAXPATHLEN) { php_error_docref(NULL, E_NOTICE, "ps_files_cleanup_dir: dirname(%s) is too long", dirname); closedir(dir); - return (0); + return -1; } /* Prepare buffer (dirname never changes) */ From 0a466e7ad8f762f4d90fa05643033b412ee21330 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Wed, 22 Feb 2023 00:13:25 +0800 Subject: [PATCH 083/103] Fix GH-10647: Spoofchecker isSuspicious/areConfusable methods error code's argument. Closes GH-10653. --- NEWS | 4 ++++ ext/intl/spoofchecker/spoofchecker_main.c | 6 ++++-- ext/intl/tests/gh10647.phpt | 24 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 ext/intl/tests/gh10647.phpt diff --git a/NEWS b/NEWS index 6f2cd00955898..3ee934bca5839 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ PHP NEWS . Fixed bug GH-10315 (FPM unknown child alert not valid). (Jakub Zelenka) . Fixed bug GH-10385 (FPM successful config test early exit). (nielsdos) +- Intl: + . Fixed bug GH-10647 (Spoolchecker isSuspicious/areConfusable methods + error code's argument always returning NULL0. (Nathan Freeman) + - JSON: . Fixed JSON scanner and parser generation build. (Daniel Black, Jakub Zelenka) diff --git a/ext/intl/spoofchecker/spoofchecker_main.c b/ext/intl/spoofchecker/spoofchecker_main.c index 35f7aef810223..a890f468e130f 100644 --- a/ext/intl/spoofchecker/spoofchecker_main.c +++ b/ext/intl/spoofchecker/spoofchecker_main.c @@ -43,7 +43,8 @@ PHP_METHOD(Spoofchecker, isSuspicious) if (error_code) { zval_ptr_dtor(error_code); - ZVAL_LONG(error_code, ret); + ZVAL_LONG(Z_REFVAL_P(error_code), ret); + Z_TRY_ADDREF_P(error_code); } RETVAL_BOOL(ret != 0); } @@ -76,7 +77,8 @@ PHP_METHOD(Spoofchecker, areConfusable) if (error_code) { zval_ptr_dtor(error_code); - ZVAL_LONG(error_code, ret); + ZVAL_LONG(Z_REFVAL_P(error_code), ret); + Z_TRY_ADDREF_P(error_code); } RETVAL_BOOL(ret != 0); } diff --git a/ext/intl/tests/gh10647.phpt b/ext/intl/tests/gh10647.phpt new file mode 100644 index 0000000000000..61c6b87e0ddec --- /dev/null +++ b/ext/intl/tests/gh10647.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug GH-10647 (Spoofchecker::isSuspicious $errorCode always null) +--SKIPIF-- + +--FILE-- +isSuspicious("\u{041F}aypal.com", $error)); +var_dump($error); + +var_dump($x->areConfusable('google.com', 'goog1e.com', $error)); +var_dump($error); +?> +--EXPECTF-- +int(123) +bool(true) +int(%d) +bool(true) +int(%d) From c4c861b01a0d7c228365c5ce240d88cb7c2f4fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 21 Feb 2023 21:15:35 +0100 Subject: [PATCH 084/103] make clean: remove ext/opcache/minilua Closes GH-10656. --- build/Makefile.global | 1 + 1 file changed, 1 insertion(+) diff --git a/build/Makefile.global b/build/Makefile.global index 0b454a06cfd88..aae5bf0de5963 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -121,6 +121,7 @@ clean: rm -f libphp.la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/* rm -f ext/opcache/jit/zend_jit_x86.c rm -f ext/opcache/jit/zend_jit_arm64.c + rm -f ext/opcache/minilua distclean: clean rm -f Makefile config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h main/internal_functions_cli.c main/internal_functions.c Zend/zend_dtrace_gen.h Zend/zend_dtrace_gen.h.bak Zend/zend_config.h From c510083c8c9ba0f81724861112032382efe4cd77 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:36:37 +0100 Subject: [PATCH 085/103] Fix incorrect string length for output_handler in zlib ini code The length of "output_handler" is supposed to be passed, but as sizeof is used, the resulting number includes the NUL character, so the length is off-by-one. Subtract one to pass the correct length. Closes GH-10667. --- NEWS | 4 ++++ ext/zlib/zlib.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 3ee934bca5839..ec5a523980227 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,10 @@ PHP NEWS 4GB. (Girgias) . Add missing error check on tidyLoadConfig. (nielsdos) +- Zlib: + . Fixed output_handler directive value's length which counted the string + terminator. (nieldos) + 14 Feb 2023, PHP 8.1.16 - Core: diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index a53fb2acc4593..9058f4a2129a7 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1279,7 +1279,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression) } else { int_value = zend_atoi(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); } - ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0); + ini_value = zend_ini_string("output_handler", sizeof("output_handler") - 1, 0); if (ini_value && *ini_value && int_value) { php_error_docref("ref.outcontrol", E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!"); From 939c546ea12a722cbdd9b64e90518d22786fb133 Mon Sep 17 00:00:00 2001 From: Danack Date: Thu, 23 Feb 2023 16:01:55 +0000 Subject: [PATCH 086/103] Re-enable UnixODBC testing. The problem installing the package in the CI environment has been fixed. --- .github/actions/configure-x64/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml index 72abc69da5eae..ee802334490ae 100644 --- a/.github/actions/configure-x64/action.yml +++ b/.github/actions/configure-x64/action.yml @@ -70,10 +70,10 @@ runs: --with-lmdb \ --with-qdbm \ --with-snmp \ - `#--with-unixODBC` \ + --with-unixODBC \ --with-imap \ --with-imap-ssl \ - `#--with-pdo-odbc=unixODBC,/usr` \ + --with-pdo-odbc=unixODBC,/usr \ --with-pdo-oci=shared,instantclient,/opt/oracle/instantclient \ --with-oci8=shared,instantclient,/opt/oracle/instantclient \ --with-config-file-path=/etc \ From 8d1c0a1403cac3f1696f65ecfab01fc8179fc445 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 22 Feb 2023 19:39:10 +0100 Subject: [PATCH 087/103] Fix segfault when using ReflectionFiber (fixes #10439) Closes GH-10478 --- NEWS | 2 + ext/reflection/php_reflection.c | 16 ++++- ext/reflection/php_reflection.stub.php | 4 +- ext/reflection/php_reflection_arginfo.h | 8 ++- .../tests/ReflectionFiber_notrace_1.phpt | 31 ++++++++++ .../tests/ReflectionFiber_notrace_2.phpt | 61 +++++++++++++++++++ 6 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 ext/reflection/tests/ReflectionFiber_notrace_1.phpt create mode 100644 ext/reflection/tests/ReflectionFiber_notrace_2.phpt diff --git a/NEWS b/NEWS index ec5a523980227..13b0575e2a58f 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,8 @@ PHP NEWS - Reflection: . Fixed bug GH-10623 (Reflection::getClosureUsedVariables opcode fix with variadic arguments). (nielsdos) + . Fix Segfault when using ReflectionFiber suspended by an internal function. + (danog) - Session: . Fixed ps_files_cleanup_dir() on failure code paths with -1 instead of 0 as diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index f4fc588a3101d..9a9685e7292e7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -7017,7 +7017,13 @@ ZEND_METHOD(ReflectionFiber, getExecutingLine) prev_execute_data = fiber->execute_data->prev_execute_data; } - RETURN_LONG(prev_execute_data->opline->lineno); + while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) { + prev_execute_data = prev_execute_data->prev_execute_data; + } + if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) { + RETURN_LONG(prev_execute_data->opline->lineno); + } + RETURN_NULL(); } ZEND_METHOD(ReflectionFiber, getExecutingFile) @@ -7035,7 +7041,13 @@ ZEND_METHOD(ReflectionFiber, getExecutingFile) prev_execute_data = fiber->execute_data->prev_execute_data; } - RETURN_STR_COPY(prev_execute_data->func->op_array.filename); + while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) { + prev_execute_data = prev_execute_data->prev_execute_data; + } + if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) { + RETURN_STR_COPY(prev_execute_data->func->op_array.filename); + } + RETURN_NULL(); } ZEND_METHOD(ReflectionFiber, getCallable) diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 750eceed66402..592ccf57c27cc 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -756,9 +756,9 @@ public function __construct(Fiber $fiber) {} public function getFiber(): Fiber {} - public function getExecutingFile(): string {} + public function getExecutingFile(): ?string {} - public function getExecutingLine(): int {} + public function getExecutingLine(): ?int {} public function getCallable(): callable {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 6242ac1c31e22..3292c5c7e94ad 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: ab0dd21b2fc7ff18c39275e1ec82211c7058c32a */ + * Stub hash: 164878e6c43f0e4c8bb7a7ae1e5c9650c240d775 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -586,9 +586,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFiber_getFiber, 0, 0, Fiber, 0) ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFiber_getExecutingFile arginfo_class_ReflectionFunction___toString +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getExecutingFile, 0, 0, IS_STRING, 1) +ZEND_END_ARG_INFO() -#define arginfo_class_ReflectionFiber_getExecutingLine arginfo_class_ReflectionAttribute_getTarget +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getExecutingLine, 0, 0, IS_LONG, 1) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getCallable, 0, 0, IS_CALLABLE, 0) ZEND_END_ARG_INFO() diff --git a/ext/reflection/tests/ReflectionFiber_notrace_1.phpt b/ext/reflection/tests/ReflectionFiber_notrace_1.phpt new file mode 100644 index 0000000000000..28e5da39f59d1 --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_notrace_1.phpt @@ -0,0 +1,31 @@ +--TEST-- +ReflectionFiber should not segfault when inspecting fibers with no stack frames before suspend +--FILE-- +start(); + +$reflection = new ReflectionFiber($f); + +var_dump($reflection->getExecutingFile()); +var_dump($reflection->getExecutingLine()); +var_dump($reflection->getTrace()); + +?> +--EXPECTF-- +NULL +NULL +array(1) { + [0]=> + array(4) { + ["function"]=> + string(7) "suspend" + ["class"]=> + string(5) "Fiber" + ["type"]=> + string(2) "::" + ["args"]=> + array(0) { + } + } +} diff --git a/ext/reflection/tests/ReflectionFiber_notrace_2.phpt b/ext/reflection/tests/ReflectionFiber_notrace_2.phpt new file mode 100644 index 0000000000000..85cb4ebd20a71 --- /dev/null +++ b/ext/reflection/tests/ReflectionFiber_notrace_2.phpt @@ -0,0 +1,61 @@ +--TEST-- +ReflectionFiber should not segfault when inspecting fibers where the previous stack frame is a native function +--FILE-- + call_user_func(["Fiber", "suspend"])); +$f->start(); + +$reflection = new \ReflectionFiber($f); + +var_dump($reflection->getExecutingFile()); +var_dump($reflection->getExecutingLine()); +var_dump($reflection->getTrace()); + +?> +--EXPECTF-- +string(%d) "%sReflectionFiber_notrace_2.php" +int(5) +array(3) { + [0]=> + array(4) { + ["function"]=> + string(7) "suspend" + ["class"]=> + string(5) "Fiber" + ["type"]=> + string(2) "::" + ["args"]=> + array(0) { + } + } + [1]=> + array(4) { + ["file"]=> + string(%d) "%sReflectionFiber_notrace_2.php" + ["line"]=> + int(5) + ["function"]=> + string(14) "call_user_func" + ["args"]=> + array(1) { + [0]=> + array(2) { + [0]=> + string(5) "Fiber" + [1]=> + string(7) "suspend" + } + } + } + [2]=> + array(2) { + ["function"]=> + string(14) "test\{closure}" + ["args"]=> + array(0) { + } + } +} From 5f357f341da33f15aebd918b61566dd0d1fa21eb Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Thu, 23 Feb 2023 05:35:39 +0000 Subject: [PATCH 088/103] Fix GH-10672 (pg_lo_open segfaults in the strict_types mode) We need to use the proper ZPP qualifier for zend_string Closes GH-10677 --- NEWS | 3 +++ ext/pgsql/pgsql.c | 2 +- ext/pgsql/tests/gh10672.phpt | 39 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 ext/pgsql/tests/gh10672.phpt diff --git a/NEWS b/NEWS index 13b0575e2a58f..0d4a42041f5ce 100644 --- a/NEWS +++ b/NEWS @@ -50,6 +50,9 @@ PHP NEWS . Fixed bug #60994 (Reading a multibyte CLOB caps at 8192 chars). (Michael Voříšek) +- PGSQL: + . Fix GH-10672 (pg_lo_open segfaults in the strict_types mode). (girgias) + - Phar: . Fix incorrect check in phar tar parsing. (nielsdos) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 4422e4259a532..a0c83fd955abe 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2464,7 +2464,7 @@ PHP_FUNCTION(pg_lo_open) CHECK_PGSQL_LINK(link); } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), - "Ols", &pgsql_link, pgsql_link_ce, &oid_long, &mode) == SUCCESS) { + "OlS", &pgsql_link, pgsql_link_ce, &oid_long, &mode) == SUCCESS) { if (oid_long <= (zend_long)InvalidOid) { zend_value_error("Invalid OID value passed"); RETURN_THROWS(); diff --git a/ext/pgsql/tests/gh10672.phpt b/ext/pgsql/tests/gh10672.phpt new file mode 100644 index 0000000000000..2f334e573dac9 --- /dev/null +++ b/ext/pgsql/tests/gh10672.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-10672 (pg_lo_open segfaults in the strict_types mode) +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + +--EXPECT-- +The large object has been opened successfully. From 91db3a1b85b6e04b78fe24e3c456fd121d9aadb3 Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Thu, 16 Feb 2023 23:53:05 -0500 Subject: [PATCH 089/103] Fixed bug GH-10270 Unable to return CURL_READFUNC_PAUSE in readfunc callback Closes GH-10607 Signed-off-by: George Peter Banyard --- NEWS | 2 ++ ext/curl/interface.c | 2 ++ ext/curl/tests/curl_pause_001.phpt | 47 ++++++++++++++++++++++++++++++ ext/curl/tests/responder/get.inc | 3 ++ 4 files changed, 54 insertions(+) create mode 100644 ext/curl/tests/curl_pause_001.phpt diff --git a/NEWS b/NEWS index 0d4a42041f5ce..72b4906620730 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) + . Fixed bug GH-10270 (Unable to return CURL_READFUNC_PAUSE in readfunc + callback). (Pierrick Charron) - Date: . Fix GH-10447 ('p' format specifier does not yield 'Z' for 00:00). (Derick) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 7eb081700c2ef..8e881a78f3529 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1547,6 +1547,8 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) if (Z_TYPE(retval) == IS_STRING) { length = MIN((int) (size * nmemb), Z_STRLEN(retval)); memcpy(data, Z_STRVAL(retval), length); + } else if (Z_TYPE(retval) == IS_LONG) { + length = Z_LVAL_P(&retval); } zval_ptr_dtor(&retval); } diff --git a/ext/curl/tests/curl_pause_001.phpt b/ext/curl/tests/curl_pause_001.phpt new file mode 100644 index 0000000000000..1fce0dd4afa26 --- /dev/null +++ b/ext/curl/tests/curl_pause_001.phpt @@ -0,0 +1,47 @@ +--TEST-- +Test CURL_READFUNC_PAUSE and curl_pause() +--EXTENSIONS-- +curl +--FILE-- +res++]; + } +} + +$inputHandle = fopen(__FILE__, 'r'); + +$ch = curl_init(); +curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=input"); +curl_setopt($ch, CURLOPT_UPLOAD, 1); +curl_setopt($ch, CURLOPT_READFUNCTION, new Input); +curl_setopt($ch, CURLOPT_INFILE, $inputHandle); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + +$mh = curl_multi_init(); +curl_multi_add_handle($mh, $ch); +do { + $status = curl_multi_exec($mh, $active); + curl_pause($ch, CURLPAUSE_CONT); + if ($active) { + usleep(100); + curl_multi_select($mh); + } +} while ($active && $status == CURLM_OK); + +echo curl_multi_getcontent($ch); +?> +--EXPECT-- +string(15) "Foo bar baz qux" diff --git a/ext/curl/tests/responder/get.inc b/ext/curl/tests/responder/get.inc index 4ed9ae0282346..c139c8c7d43a8 100644 --- a/ext/curl/tests/responder/get.inc +++ b/ext/curl/tests/responder/get.inc @@ -4,6 +4,9 @@ case 'post': var_dump($_POST); break; + case 'input': + var_dump(file_get_contents('php://input')); + break; case 'getpost': var_dump($_GET); var_dump($_POST); From 8959ff39d8c9ec85d81d28caa6cde400c4cca442 Mon Sep 17 00:00:00 2001 From: nielsdos <7771979+nielsdos@users.noreply.github.com> Date: Fri, 24 Feb 2023 16:53:20 +0100 Subject: [PATCH 090/103] Fix incorrect type for return value of zend_update_static_property_ex() zend_update_static_property_ex() returns a zend_result, but the return value is stored here in a bool. A bool is unsigned on my system, so in case zend_update_static_property_ex() returns FAILURE (== -1) this gets converted to 1 instead. This is not a valid zend_result value. This means that (transitive) callers could mistakingly think the function succeeded while it did in fact not succeed. Fix it by changing the type to zend_result. Closes GH-10691. --- NEWS | 2 ++ Zend/zend_API.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 72b4906620730..262327d75f560 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS function after bailout). (trowski) . Fixed SSA object type update for compound assignment opcodes. (nielsdos) . Fixed language scanner generation build. (Daniel Black) + . Fixed zend_update_static_property() calling zend_update_static_property_ex() + misleadingly with the wrong return type. (nielsdos) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index e8ff66fe97ed0..f59035be3f1b3 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4658,7 +4658,7 @@ ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zen ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */ { zend_string *key = zend_string_init(name, name_length, 0); - bool retval = zend_update_static_property_ex(scope, key, value); + zend_result retval = zend_update_static_property_ex(scope, key, value); zend_string_efree(key); return retval; } From b9a5bfc355747f06653ec52b7d29d5de95bbcc99 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 12 Feb 2023 11:54:29 +0100 Subject: [PATCH 091/103] Fix GH-10570: Assertion `(key)->h != 0 && "Hash must be known"' failed. Fixes GH-10570, see GH-10570 for analysis. Closes GH-10572 --- NEWS | 2 ++ Zend/tests/gh10570.phpt | 14 ++++++++++++++ Zend/zend_compile.c | 1 + 3 files changed, 17 insertions(+) create mode 100644 Zend/tests/gh10570.phpt diff --git a/NEWS b/NEWS index 262327d75f560..30cf48f1a271c 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,8 @@ PHP NEWS . Fixed language scanner generation build. (Daniel Black) . Fixed zend_update_static_property() calling zend_update_static_property_ex() misleadingly with the wrong return type. (nielsdos) + . Fixed unknown string hash on property fetch with integer constant name. + (nielsdos) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) diff --git a/Zend/tests/gh10570.phpt b/Zend/tests/gh10570.phpt new file mode 100644 index 0000000000000..edd35c1ca30ec --- /dev/null +++ b/Zend/tests/gh10570.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-10570 (Assertion `(key)->h != 0 && "Hash must be known"' failed.): constant variation +--FILE-- +{90}; + $a->{0} = 0; +} +?> +--EXPECTF-- +Warning: Undefined property: stdClass::$90 in %s on line %d + +Warning: Undefined property: stdClass::$90 in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9ca8c654fc207..0774fb6d19a25 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2924,6 +2924,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node); if (opline->op2_type == IS_CONST) { convert_to_string(CT_CONSTANT(opline->op2)); + zend_string_hash_val(Z_STR_P(CT_CONSTANT(opline->op2))); opline->extended_value = zend_alloc_cache_slots(3); } From 7d2b01eea7dc69789688dad0c6b5c0c5136ca278 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 24 Feb 2023 20:44:47 +0100 Subject: [PATCH 092/103] [skip ci] Add github reference to bug fix in NEWS --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 30cf48f1a271c..077cfcb8e38f9 100644 --- a/NEWS +++ b/NEWS @@ -14,8 +14,8 @@ PHP NEWS . Fixed language scanner generation build. (Daniel Black) . Fixed zend_update_static_property() calling zend_update_static_property_ex() misleadingly with the wrong return type. (nielsdos) - . Fixed unknown string hash on property fetch with integer constant name. - (nielsdos) + . Fix bug GH-10570 (Fixed unknown string hash on property fetch with integer + constant name). (nielsdos) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) From df579adac7b91296e0bfe2d35e5afccfedc6b61d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 25 Feb 2023 13:42:45 +0100 Subject: [PATCH 093/103] Fix GH-10692: PHP crashes on Windows when an inexistent filename is executed Fixes GH-10692 php_fopen_primary_script() does not initialize all fields of zend_file_handle. So when it fails and when fastcgi is true, the zend_destroy_file_handle() function will try to free uninitialized pointers, causing a segmentation fault. Fix it by zero-initializing file handles just like the zend_stream_init_fp() counterpart does. Closes GH-10697. --- NEWS | 2 ++ main/fopen_wrappers.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 077cfcb8e38f9..76b9e953af35f 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ PHP NEWS misleadingly with the wrong return type. (nielsdos) . Fix bug GH-10570 (Fixed unknown string hash on property fetch with integer constant name). (nielsdos) + . Fixed php_fopen_primary_script() call resulted on zend_destroy_file_handle() + freeing dangling pointers on the handle as it was uninitialized. (nielsdos) - Curl: . Fixed deprecation warning at compile time. (Max Kellermann) diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 12cc9c8b10c01..efb110171b148 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -353,6 +353,8 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle) size_t length; bool orig_display_errors; + memset(file_handle, 0, sizeof(zend_file_handle)); + path_info = SG(request_info).request_uri; #if HAVE_PWD_H if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) { From eb7bb3430b06b6657dec3e0580cc40347283f836 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 25 Feb 2023 19:49:47 +0100 Subject: [PATCH 094/103] Fix format string mistake in accel_move_code_to_huge_pages() inode is unsigned, so use %lu instead of %ld --- ext/opcache/ZendAccelerator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 1ffd6cb3e5d46..a912b5e604bb5 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3029,7 +3029,7 @@ static void accel_move_code_to_huge_pages(void) int ret; while (1) { - ret = fscanf(f, "%lx-%lx %4s %lx %9s %ld %s\n", &start, &end, perm, &offset, dev, &inode, name); + ret = fscanf(f, "%lx-%lx %4s %lx %9s %lu %s\n", &start, &end, perm, &offset, dev, &inode, name); if (ret == 7) { if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') { long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); From b09be29ac12fbd5deb11e47465441c73cc260855 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 25 Feb 2023 23:39:00 +0100 Subject: [PATCH 095/103] Fix incorrect error checking in php_openssl_set_server_dh_param() SSL_CTX_set_tmp_dh() and SSL_CTX_set0_tmp_dh_pkey() return 1 on success and 0 on error. But only < 0 was checked which means that errors were never caught. Closes GH-10705. --- NEWS | 3 +++ ext/openssl/xp_ssl.c | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 76b9e953af35f..5f048e0f89afb 100644 --- a/NEWS +++ b/NEWS @@ -54,6 +54,9 @@ PHP NEWS - Opcache: . Fix incorrect page_size check. (nielsdos) +- OpenSSL: + . Fixed php_openssl_set_server_dh_param() DH params errors handling. (nielsdos) + - PDO OCI: . Fixed bug #60994 (Reading a multibyte CLOB caps at 8192 chars). (Michael Voříšek) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 58ba4b0499c84..9aac4a0b70a28 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1222,7 +1222,7 @@ static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* return FAILURE; } - if (SSL_CTX_set0_tmp_dh_pkey(ctx, pkey) < 0) { + if (SSL_CTX_set0_tmp_dh_pkey(ctx, pkey) == 0) { php_error_docref(NULL, E_WARNING, "Failed assigning DH params"); EVP_PKEY_free(pkey); return FAILURE; @@ -1236,7 +1236,7 @@ static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* return FAILURE; } - if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) { + if (SSL_CTX_set_tmp_dh(ctx, dh) == 0) { php_error_docref(NULL, E_WARNING, "Failed assigning DH params"); DH_free(dh); return FAILURE; @@ -1305,7 +1305,10 @@ static int php_openssl_set_server_specific_opts(php_stream *stream, SSL_CTX *ctx php_error_docref(NULL, E_WARNING, "rsa_key_size context option has been removed"); } - php_openssl_set_server_dh_param(stream, ctx); + if (php_openssl_set_server_dh_param(stream, ctx) == FAILURE) { + return FAILURE; + } + zv = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "single_dh_use"); if (zv == NULL || zend_is_true(zv)) { ssl_ctx_options |= SSL_OP_SINGLE_DH_USE; From 6a5b3f0ff9b0b0c65c51ce4445d4518880b81e14 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Thu, 23 Feb 2023 04:08:58 +0000 Subject: [PATCH 096/103] The userland constants do not start with PHP_ --- ext/xml/tests/xml_parser_get_option_variation4.phpt | 2 +- ext/xml/tests/xml_parser_set_option_variation5.phpt | 2 +- ext/xml/xml.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/xml/tests/xml_parser_get_option_variation4.phpt b/ext/xml/tests/xml_parser_get_option_variation4.phpt index 9c12f57544b66..f6d858a7e9c01 100644 --- a/ext/xml/tests/xml_parser_get_option_variation4.phpt +++ b/ext/xml/tests/xml_parser_get_option_variation4.phpt @@ -15,4 +15,4 @@ try { ?> --EXPECT-- -xml_parser_get_option(): Argument #2 ($option) must be a PHP_XML_OPTION_* constant +xml_parser_get_option(): Argument #2 ($option) must be a XML_OPTION_* constant diff --git a/ext/xml/tests/xml_parser_set_option_variation5.phpt b/ext/xml/tests/xml_parser_set_option_variation5.phpt index 382803ca1c74d..c6bad1539701e 100644 --- a/ext/xml/tests/xml_parser_set_option_variation5.phpt +++ b/ext/xml/tests/xml_parser_set_option_variation5.phpt @@ -15,4 +15,4 @@ try { ?> --EXPECT-- -xml_parser_set_option(): Argument #2 ($option) must be a PHP_XML_OPTION_* constant +xml_parser_set_option(): Argument #2 ($option) must be a XML_OPTION_* constant diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 904ad305b173e..b641a0c87d731 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -1457,7 +1457,7 @@ PHP_FUNCTION(xml_parser_set_option) break; } default: - zend_argument_value_error(2, "must be a PHP_XML_OPTION_* constant"); + zend_argument_value_error(2, "must be a XML_OPTION_* constant"); RETURN_THROWS(); break; } @@ -1491,7 +1491,7 @@ PHP_FUNCTION(xml_parser_get_option) RETURN_STRING((char *)parser->target_encoding); break; default: - zend_argument_value_error(2, "must be a PHP_XML_OPTION_* constant"); + zend_argument_value_error(2, "must be a XML_OPTION_* constant"); RETURN_THROWS(); } } From 2133970152edf9ea865cdedf96beeffab033d381 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 26 Feb 2023 14:25:02 +0000 Subject: [PATCH 097/103] Fixed ValueError message in substr_compare() It used some random argument name instead of --- ext/standard/string.c | 2 +- ext/standard/tests/strings/bug40754.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 643094263bfcb..1d965d3e60d17 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5960,7 +5960,7 @@ PHP_FUNCTION(substr_compare) } if ((size_t)offset > ZSTR_LEN(s1)) { - zend_argument_value_error(3, "must be contained in argument #1 ($main_str)"); + zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } diff --git a/ext/standard/tests/strings/bug40754.phpt b/ext/standard/tests/strings/bug40754.phpt index c2a563a7fd97a..f8f8c103d479a 100644 --- a/ext/standard/tests/strings/bug40754.phpt +++ b/ext/standard/tests/strings/bug40754.phpt @@ -81,7 +81,7 @@ string(6) "abcdex" int(0) int(0) substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) -substr_compare(): Argument #3 ($offset) must be contained in argument #1 ($main_str) +substr_compare(): Argument #3 ($offset) must be contained in argument #1 ($haystack) stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) substr_count(): Argument #4 ($length) must be contained in argument #1 ($haystack) From adc5edd411d28259e62ffcd2db93cd91e54b37d6 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 26 Feb 2023 14:27:46 +0000 Subject: [PATCH 098/103] Fixed ValueError message in count_chars() The value of the mode argument must be between 0 and 4 inclusive, not 1 and 4. --- ext/standard/string.c | 2 +- ext/standard/tests/strings/count_chars_basic.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 1d965d3e60d17..368f0123870ce 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5292,7 +5292,7 @@ PHP_FUNCTION(count_chars) ZEND_PARSE_PARAMETERS_END(); if (mymode < 0 || mymode > 4) { - zend_argument_value_error(2, "must be between 1 and 4 (inclusive)"); + zend_argument_value_error(2, "must be between 0 and 4 (inclusive)"); RETURN_THROWS(); } diff --git a/ext/standard/tests/strings/count_chars_basic.phpt b/ext/standard/tests/strings/count_chars_basic.phpt index 50f5aecd6be75..ccf8cd47ac04a 100644 --- a/ext/standard/tests/strings/count_chars_basic.phpt +++ b/ext/standard/tests/strings/count_chars_basic.phpt @@ -1569,4 +1569,4 @@ array(238) { } string(18) " Rabcdefghimnorstu" string(476) "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051535455565758595a5b5c5d5e5f606a6b6c7071767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" -count_chars(): Argument #2 ($mode) must be between 1 and 4 (inclusive) +count_chars(): Argument #2 ($mode) must be between 0 and 4 (inclusive) From 44e5c04e5546e60cdbc31360adf3876b7c706152 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 27 Feb 2023 21:39:18 +0300 Subject: [PATCH 099/103] Fix incorrect inheritance cache update (#10719) --- ext/opcache/ZendAccelerator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index a912b5e604bb5..36ce94028119c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2354,9 +2354,9 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, SHM_UNPROTECT(); zend_shared_alloc_lock(); - entry = ce->inheritance_cache; + entry = proto->inheritance_cache; while (entry) { - entry = zend_accel_inheritance_cache_find(entry, ce, parent, traits_and_interfaces, &needs_autoload); + entry = zend_accel_inheritance_cache_find(entry, proto, parent, traits_and_interfaces, &needs_autoload); if (entry) { if (!needs_autoload) { zend_shared_alloc_unlock(); From 0f21cbc57c0f210cc5ea35b78f354cf2e0949e0e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 27 Feb 2023 19:44:42 +0100 Subject: [PATCH 100/103] Fix GH-10715: phpdbg heap buffer overflow -- by misuse of the option "--run" Fixes GH-10715 When a string starting with a NUL character is passed to phpdbg_vprint(), the vasprintf() will return that 0 characters have been printed. This causes msglen == 0. When phpdbg_process_print() is called with a message of length 0, the -1 to check for '\n' will perform an out of bounds read. Since nothing is printed anyway for msglen == 0, it seems best to just skip the printing routine for this case. Closes GH-10720. --- NEWS | 3 +++ sapi/phpdbg/phpdbg_out.c | 6 +++++- sapi/phpdbg/tests/gh10715.phpt | Bin 0 -> 192 bytes 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 sapi/phpdbg/tests/gh10715.phpt diff --git a/NEWS b/NEWS index 5f048e0f89afb..5e940ee021778 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,9 @@ PHP NEWS . Fixed bug #60994 (Reading a multibyte CLOB caps at 8192 chars). (Michael Voříšek) +- PHPDBG: + . Fixed bug GH-10715 (heap buffer overflow on --run option misuse). (nielsdos) + - PGSQL: . Fix GH-10672 (pg_lo_open segfaults in the strict_types mode). (girgias) diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c index a6eb84de2c182..af2f3b98d2bad 100644 --- a/sapi/phpdbg/phpdbg_out.c +++ b/sapi/phpdbg/phpdbg_out.c @@ -143,7 +143,11 @@ PHPDBG_API int phpdbg_vprint(int type, int fd, const char *strfmt, va_list args) return msglen; } - len = phpdbg_process_print(fd, type, msg, msglen); + if (UNEXPECTED(msglen == 0)) { + len = 0; + } else { + len = phpdbg_process_print(fd, type, msg, msglen); + } if (msg) { free(msg); diff --git a/sapi/phpdbg/tests/gh10715.phpt b/sapi/phpdbg/tests/gh10715.phpt new file mode 100644 index 0000000000000000000000000000000000000000..13edd9afdd8f05df2744b3d5d1257c827d219c40 GIT binary patch literal 192 zcmX|(JqyAx6h)o$D;@ Date: Tue, 28 Feb 2023 22:57:52 +0300 Subject: [PATCH 101/103] Fix Zend/tests/type_declarations/variance/class_order_autoload1.phpt test failre introduced by 44e5c04e5546e60cdbc31360adf3876b7c706152 This ASSERT-ion path was never reached becuase of the bug fixed by 44e5c04e5546e60cdbc31360adf3876b7c706152. It's possible in case of circular class dependencies that may resolved by __autoload(). Unfortunately these circular dependencies can't be stored in the inheritace cahce. --- ext/opcache/ZendAccelerator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 36ce94028119c..97b82378780b8 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2358,14 +2358,14 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, while (entry) { entry = zend_accel_inheritance_cache_find(entry, proto, parent, traits_and_interfaces, &needs_autoload); if (entry) { + zend_shared_alloc_unlock(); + SHM_PROTECT(); if (!needs_autoload) { - zend_shared_alloc_unlock(); - SHM_PROTECT(); - zend_map_ptr_extend(ZCSG(map_ptr_last)); return entry->ce; + } else { + return NULL; } - ZEND_ASSERT(0); // entry = entry->next; // This shouldn't be posible ??? } } From 40a1a86f0ca1836b37d9a17cbacd56573d577789 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 12 Mar 2023 16:38:01 +0100 Subject: [PATCH 102/103] Fix module shutdown crash during ZTS JIT shutdown Commit a21195650e53 fixed a leak by adding a TSRM destructor for the JIT globals in ZTS mode. In case the main thread shuts down the TSRM, it will call all the destructors. The JIT globals destructor will be invoked, but will always access the main thread globals using JIT_G. This means that instead of freeing the JIT globals in the different threads, the one in the main thread is freed repeatedly over and over, crashing PHP. Fix it by always passing the pointer instead of relying on JIT_G. Closes GH-10835. (cherry picked from commit b3e28e22904aca99beb5e8a26a34d7c8b46c69ee) --- ext/opcache/jit/zend_jit.c | 4 ++-- ext/opcache/jit/zend_jit_trace.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d2f6df0537c9d..8c6934dfb6358 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -4762,7 +4762,7 @@ static void zend_jit_globals_ctor(zend_jit_globals *jit_globals) #ifdef ZTS static void zend_jit_globals_dtor(zend_jit_globals *jit_globals) { - zend_jit_trace_free_caches(); + zend_jit_trace_free_caches(jit_globals); } #endif @@ -5081,7 +5081,7 @@ ZEND_EXT_API void zend_jit_shutdown(void) #ifdef ZTS ts_free_id(jit_globals_id); #else - zend_jit_trace_free_caches(); + zend_jit_trace_free_caches(&jit_globals); #endif } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 14cd945bbe650..eac9719a98c2c 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8324,10 +8324,10 @@ static void zend_jit_trace_reset_caches(void) #endif } -static void zend_jit_trace_free_caches(void) +static void zend_jit_trace_free_caches(zend_jit_globals *jit_globals) { - if (JIT_G(exit_counters)) { - free(JIT_G(exit_counters)); + if (jit_globals->exit_counters) { + free(jit_globals->exit_counters); } } From 6bdc7fee4a32b18d2a7585e8a5635593fe70f247 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 14 Mar 2023 20:47:11 +0100 Subject: [PATCH 103/103] Update versions for PHP 8.1.17 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 5e940ee021778..2d55f59fcdfd5 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.17 +16 Mar 2023, PHP 8.1.17 - Core: . Fixed incorrect check condition in ZEND_YIELD. (nielsdos) diff --git a/Zend/zend.h b/Zend/zend.h index 18e605c5bc27a..e9f70603309bd 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.17-dev" +#define ZEND_VERSION "4.1.17" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 9aa8c5caf2e2d..d0c9573802f6a 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.17-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.17],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index b5568bffa819e..91e810bb09d2f 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 #define PHP_RELEASE_VERSION 17 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.17-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.1.17" #define PHP_VERSION_ID 80117