diff --git a/NEWS b/NEWS index 568638e23574..38cb97bf6f3e 100644 --- a/NEWS +++ b/NEWS @@ -119,6 +119,8 @@ PHP NEWS with chained Pi nodes). (ndossche) . Fixed JIT treating an array as packed after a string key write turned it into a hash. (jorgsowa) + . Fixed function JIT ASSIGN_DIM reporting an undefined value or key out of + order, or when the VM does not, on non-array containers. (jorgsowa) - PDO: . Fixed invalid ATTR_ORACLE_NULLS values being accepted and truncated. diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 9504b5bf79ec..6d94b804136d 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1510,13 +1510,6 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim return; } - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { - const zend_op *op_data = EG(current_execute_data)->opline + 1; - ZEND_ASSERT(op_data->opcode == ZEND_OP_DATA && op_data->op1_type == IS_CV); - zend_jit_undefined_op_helper(op_data->op1.var); - value = &EG(uninitialized_zval); - } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { zend_throw_error(NULL, "[] operator not supported for strings"); if (result) { @@ -1546,16 +1539,26 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim return; } + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + /* EX(opline) no longer points to ASSIGN_DIM after a throw; the VM skips the warning too. */ + if (EXPECTED(!EG(exception))) { + const zend_op *op_data = EG(current_execute_data)->opline + 1; + ZEND_ASSERT(op_data->opcode == ZEND_OP_DATA && op_data->op1_type == IS_CV); + if (!zend_jit_undefined_op_helper_write(arr, op_data->op1.var)) { + if (result) { + ZVAL_UNDEF(result); + } + return; + } + } + value = &EG(uninitialized_zval); + } + ZVAL_COPY_DEREF(var, value); if (result) { ZVAL_COPY(result, var); } } else { - if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { - const zend_op *opline = EG(current_execute_data)->opline; - zend_jit_undefined_op_helper(opline->op2.var); - dim = &EG(uninitialized_zval); - } zend_throw_error(NULL, "Cannot use a scalar value as an array"); if (result) { ZVAL_UNDEF(result); diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_001.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_001.phpt new file mode 100644 index 000000000000..c60b9e6f8678 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT ASSIGN_DIM: undefined OP_DATA is not read when the container is a scalar +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Error: Cannot use a scalar value as an array diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_002.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_002.phpt new file mode 100644 index 000000000000..56ce424c5d77 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_002.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT ASSIGN_DIM: undefined dim is not reported when the container is a scalar +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Error: Cannot use a scalar value as an array diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_003.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_003.phpt new file mode 100644 index 000000000000..3ce0bdd9e77c --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_003.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT ASSIGN_DIM: undefined OP_DATA is not read when appending to a string +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Error: [] operator not supported for strings diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_004.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_004.phpt new file mode 100644 index 000000000000..a793dd6b3169 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_004.phpt @@ -0,0 +1,24 @@ +--TEST-- +JIT ASSIGN_DIM: undefined OP_DATA is reported after the false to array deprecation +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- + +--EXPECTF-- +Deprecated: Automatic conversion of false to array is deprecated in %s on line %d + +Warning: Undefined variable $undef in %s on line %d +array(1) { + [0]=> + NULL +} diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_005.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_005.phpt new file mode 100644 index 000000000000..1246cb6b5ba5 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_005.phpt @@ -0,0 +1,24 @@ +--TEST-- +JIT ASSIGN_DIM: undefined OP_DATA is reported after the false to array deprecation when appending +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- + +--EXPECTF-- +Deprecated: Automatic conversion of false to array is deprecated in %s on line %d + +Warning: Undefined variable $undef in %s on line %d +array(1) { + [0]=> + NULL +} diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_006.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_006.phpt new file mode 100644 index 000000000000..2bc232fd1b48 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_006.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT ASSIGN_DIM: undefined dim is reported before undefined OP_DATA when the container is false +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- + +--EXPECTF-- +Deprecated: Automatic conversion of false to array is deprecated in %s on line %d + +Warning: Undefined variable $undefKey in %s on line %d + +Warning: Undefined variable $undef in %s on line %d +array(1) { + [""]=> + NULL +} diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_007.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_007.phpt new file mode 100644 index 000000000000..ce50f5600828 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_007.phpt @@ -0,0 +1,24 @@ +--TEST-- +JIT ASSIGN_DIM: undefined OP_DATA is not reported when the false to array deprecation throws +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Exception: Automatic conversion of false to array is deprecated diff --git a/ext/opcache/tests/jit/assign_dim_undef_op_data_008.phpt b/ext/opcache/tests/jit/assign_dim_undef_op_data_008.phpt new file mode 100644 index 000000000000..632ff476929a --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_undef_op_data_008.phpt @@ -0,0 +1,27 @@ +--TEST-- +JIT ASSIGN_DIM: container converted from false is overwritten while reporting undefined OP_DATA +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +--FILE-- + +--EXPECT-- +Automatic conversion of false to array is deprecated +Undefined variable $undef +int(1)