diff options
-rw-r--r-- | Zend/zend_execute.c | 7 | ||||
-rw-r--r-- | Zend/zend_execute.h | 1 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_disasm_x86.c | 1 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_helpers.c | 12 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 34 |
5 files changed, 48 insertions, 7 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 6875ac5e8a..8813ec3d87 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -612,8 +612,6 @@ static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_err zend_get_unmangled_property_name(prop->name)); } -static zend_never_inline zend_bool zend_verify_ref_array_assignable(zend_reference *ref); - /* this should modify object only if it's empty */ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) { @@ -2531,9 +2529,8 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type) return ZEND_TYPE_IS_MASK(type) && (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)); } -/* Checks whether an array can be assigned to the reference. Returns conflicting property if - * assignment is not possible, NULL otherwise. */ -static zend_never_inline zend_bool zend_verify_ref_array_assignable(zend_reference *ref) { +/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */ +ZEND_API zend_bool zend_verify_ref_array_assignable(zend_reference *ref) { zend_property_info *prop; ZEND_ASSERT(ZEND_REF_HAS_TYPE_SOURCES(ref)); ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 2342bbaba4..8636399d3b 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -64,6 +64,7 @@ ZEND_API zend_bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, z ZEND_API ZEND_COLD void zend_verify_arg_error( const zend_function *zf, const zend_arg_info *arg_info, int arg_num, void **cache_slot, zval *value); +ZEND_API zend_bool zend_verify_ref_array_assignable(zend_reference *ref); #define ZEND_REF_TYPE_SOURCES(ref) \ (ref)->sources diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index 790c62af8f..70708729b4 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -444,6 +444,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_assign_op_to_typed_ref); REGISTER_HELPER(zend_jit_only_vars_by_reference); REGISTER_HELPER(zend_jit_invalid_array_access); + REGISTER_HELPER(zend_jit_prepare_assign_dim_ref); REGISTER_HELPER(zend_runtime_jit); REGISTER_HELPER(zend_jit_hot_func); #undef REGISTER_HELPER diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index d2c848af77..da96660a10 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1465,3 +1465,15 @@ static void ZEND_FASTCALL zend_jit_invalid_array_access(zval *container) const char *type = Z_ISUNDEF_P(container) ? "null" : zend_zval_type_name(container); zend_error(E_WARNING, "Trying to access array offset on value of type %s", type); } + +static zval * ZEND_FASTCALL zend_jit_prepare_assign_dim_ref(zval *ref) { + zval *val = Z_REFVAL_P(ref); + if (Z_TYPE_P(val) <= IS_FALSE) { + if (ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(ref)) + && !zend_verify_ref_array_assignable(Z_REF_P(ref))) { + return NULL; + } + ZVAL_ARR(val, zend_new_array(8)); + } + return val; +} diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 06357b7407..d1eba4d47b 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4610,7 +4610,21 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze if (op1_info & MAY_BE_REF) { | LOAD_ZVAL_ADDR FCARG1a, op1_addr - | ZVAL_DEREF FCARG1a, op1_info + | IF_NOT_Z_TYPE FCARG1a, IS_REFERENCE, >1 + | GET_Z_PTR FCARG2a, FCARG1a + | IF_NOT_TYPE byte [FCARG2a + offsetof(zend_reference, val) + offsetof(zval, u1.v.type)], IS_ARRAY, >2 + | lea FCARG1a, [FCARG2a + offsetof(zend_reference, val)] + | jmp >3 + |.cold_code + |2: + | SAVE_VALID_OPLINE opline + | EXT_CALL zend_jit_prepare_assign_dim_ref, r0 + | test r0, r0 + | jz ->exception_handler_undef + | mov FCARG1a, r0 + | jmp >1 + |.code + |1: op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0); } @@ -4618,6 +4632,7 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY)) { | IF_NOT_ZVAL_TYPE op1_addr, IS_ARRAY, >7 } + |3: | SEPARATE_ARRAY op1_addr, op1_info, 1 } else if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_ARRAY))) { @@ -4821,7 +4836,21 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const if (op1_info & MAY_BE_REF) { | LOAD_ZVAL_ADDR FCARG1a, op1_addr - | ZVAL_DEREF FCARG1a, op1_info + | IF_NOT_Z_TYPE FCARG1a, IS_REFERENCE, >1 + | GET_Z_PTR FCARG2a, FCARG1a + | IF_NOT_TYPE byte [FCARG2a + offsetof(zend_reference, val) + offsetof(zval, u1.v.type)], IS_ARRAY, >2 + | lea FCARG1a, [FCARG2a + offsetof(zend_reference, val)] + | jmp >3 + |.cold_code + |2: + | SAVE_VALID_OPLINE opline + | EXT_CALL zend_jit_prepare_assign_dim_ref, r0 + | test r0, r0 + | jz ->exception_handler_undef + | mov FCARG1a, r0 + | jmp >1 + |.code + |1: op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0); } @@ -4829,6 +4858,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY)) { | IF_NOT_ZVAL_TYPE op1_addr, IS_ARRAY, >7 } + |3: | SEPARATE_ARRAY op1_addr, op1_info, 1 } if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { |