diff options
author | Rasmus Lerdorf <rasmus@php.net> | 2014-10-26 16:58:45 -0700 |
---|---|---|
committer | Rasmus Lerdorf <rasmus@php.net> | 2014-10-26 16:58:45 -0700 |
commit | 8d84b1f67adb71bdb2394b62faad04b22f6226f3 (patch) | |
tree | 0c1c1ed2aaef8eee971575eb5e336631295f4951 /Zend/zend_vm_execute.h | |
parent | fb85d0322d39d49f37e32df6f68c9769f2cce0e4 (diff) | |
parent | 09da8952d0434b53e740ffaca66a8051cd39cf93 (diff) | |
download | php-git-8d84b1f67adb71bdb2394b62faad04b22f6226f3.tar.gz |
Merge branch 'master' of git.php.net:php-src
* 'master' of git.php.net:php-src: (240 commits)
Do not execute anything after quit or clean command
Fix last commit, and do not output unnecessary information
Stabilize execution, always run destructors and extended file breakpoints
Fix nullptr dereference in clean without exec context
remove dodgy param parser, bring userland breakpoint api inline with PHP7
disable output buffering by default
Add question to reset execution in run/exec/clean
- Updated to version 2014.9 (2014i)
actually remove this
disable output buffering, better breakpoint api for userland, remove hand parsing of params
Fix phpdbg output when outputting via php with active output handlers
Fixed Closure::call() NEWS/UPGRADING
Set engine back to initial state after fatal-ed ev command
Fix eventual stack overflow after clean cmd
Fix listing of files with no absolute path
updated libmagic.patch in master
updated libmagic.patch in 5.6
updated libmagic.patch in 5.5
NEWS
NEWS
...
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 3299 |
1 files changed, 1541 insertions, 1758 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4b58d95618..94466c581b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -538,7 +538,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < call->num_args; ++i) { - zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC); + zend_verify_arg_type(fbc, i + 1, p TSRMLS_CC); p++; } if (UNEXPECTED(EG(exception) != NULL)) { @@ -978,7 +978,7 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); CHECK_EXCEPTION(); } @@ -1003,7 +1003,7 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); param++; @@ -1023,57 +1023,6 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval object_zval; - zend_function *constructor; - - SAVE_OPLINE(); - if (UNEXPECTED((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } else if ((Z_CE_P(EX_VAR(opline->op1.var))->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", Z_CE_P(EX_VAR(opline->op1.var))->name->val); - } - } - object_init_ex(&object_zval, Z_CE_P(EX_VAR(opline->op1.var))); - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); - - if (constructor == NULL) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - zval_ptr_dtor(&object_zval); - } - ZEND_VM_JMP(opline->op2.jmp_addr); - } else { - /* We are not handling overloaded classes right now */ - EX(call) = zend_vm_stack_push_call_frame( - VM_FRAME_INFO( - VM_FRAME_NESTED_FUNCTION, - RETURN_VALUE_USED(opline) ? - ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), - constructor, - opline->extended_value, - Z_CE_P(EX_VAR(opline->op1.var)), - Z_OBJ(object_zval), - EX(call) TSRMLS_CC); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - EX(call)->return_value = EX_VAR(opline->result.var); - } else { - EX(call)->return_value = NULL; - } - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); - } -} - static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -1225,7 +1174,7 @@ static int ZEND_FASTCALL ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { trait = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, - opline->extended_value TSRMLS_CC); + ZEND_FETCH_CLASS_TRAIT TSRMLS_CC); if (UNEXPECTED(trait == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1474,7 +1423,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -1713,7 +1662,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC); + zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC); } CHECK_EXCEPTION(); @@ -1772,7 +1721,7 @@ static int ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { iface = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); } else { - iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + iface = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_INTERFACE TSRMLS_CC); if (UNEXPECTED(iface == NULL)) { CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1809,7 +1758,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -1995,7 +1944,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2181,7 +2130,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDL if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2220,7 +2169,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) { Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name)); } else { - Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, opline->extended_value TSRMLS_CC); + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), opline->op2.zv + 1, 0 TSRMLS_CC); CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var))); } } else if (Z_TYPE_P(class_name) == IS_OBJECT) { @@ -2662,10 +2611,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_CONST == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_CONST == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); @@ -2769,6 +2718,72 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval object_zval; + zend_function *constructor; + zend_class_entry *ce; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + } + } + object_init_ex(&object_zval, ce); + constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); + + if (constructor == NULL) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); + } else { + zval_ptr_dtor(&object_zval); + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { + /* We are not handling overloaded classes right now */ + EX(call) = zend_vm_stack_push_call_frame( + VM_FRAME_INFO( + VM_FRAME_NESTED_FUNCTION, + RETURN_VALUE_USED(opline) ? + ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), + constructor, + opline->extended_value, + ce, + Z_OBJ(object_zval), + EX(call) TSRMLS_CC); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); + EX(call)->return_value = EX_VAR(opline->result.var); + } else { + EX(call)->return_value = NULL; + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } +} + static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3840,9 +3855,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -3931,6 +3943,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -4033,7 +4046,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -4324,7 +4337,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -4855,9 +4868,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -5275,6 +5289,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -5379,7 +5394,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -5898,9 +5913,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -6378,9 +6394,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -6469,6 +6482,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -6573,7 +6587,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -7237,9 +7251,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -7442,9 +7457,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -7503,6 +7515,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -7981,9 +7994,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -8386,6 +8400,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -8488,7 +8503,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -9056,9 +9071,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CONST == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CONST == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -9444,10 +9460,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_TMP_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); @@ -10154,27 +10170,6 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); - } else { - result = 0; - } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1.var); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_STRLEN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10643,9 +10638,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -10734,6 +10726,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -10836,7 +10829,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -11451,6 +11444,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11497,9 +11529,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -11917,6 +11950,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -12021,7 +12055,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -12513,9 +12547,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -12993,9 +13028,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -13084,6 +13116,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -13188,7 +13221,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -13780,6 +13813,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -13826,9 +13898,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -14031,9 +14104,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -14092,6 +14162,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -14422,9 +14493,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -14827,6 +14899,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -14929,7 +15002,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -15416,9 +15489,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_TMP_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_TMP_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -15970,10 +16044,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_VAR == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_VAR == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); @@ -16243,6 +16317,72 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval object_zval; + zend_function *constructor; + zend_class_entry *ce; + + SAVE_OPLINE(); + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + } else { + zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + } + } + object_init_ex(&object_zval, ce); + constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval) TSRMLS_CC); + + if (constructor == NULL) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); + } else { + zval_ptr_dtor(&object_zval); + } + ZEND_VM_JMP(opline->op2.jmp_addr); + } else { + /* We are not handling overloaded classes right now */ + EX(call) = zend_vm_stack_push_call_frame( + VM_FRAME_INFO( + VM_FRAME_NESTED_FUNCTION, + RETURN_VALUE_USED(opline) ? + ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED)), + constructor, + opline->extended_value, + ce, + Z_OBJ(object_zval), + EX(call) TSRMLS_CC); + + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); + EX(call)->return_value = EX_VAR(opline->result.var); + } else { + EX(call)->return_value = NULL; + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } +} + static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -17082,27 +17222,6 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); - } else { - result = 0; - } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - zval_ptr_dtor_nogc(free_op1.var); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_STRLEN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -17472,7 +17591,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -17495,21 +17614,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -17565,15 +17680,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -17581,9 +17700,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -17594,33 +17714,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -17646,31 +17751,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -17826,7 +17917,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -17854,21 +17945,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -17920,7 +18007,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -17946,19 +18033,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -18107,9 +18190,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -18179,11 +18259,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18205,6 +18282,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -18246,6 +18324,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18277,6 +18356,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -18334,7 +18414,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18358,7 +18438,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18419,7 +18499,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18445,7 +18525,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -18523,29 +18603,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = opline->op2.zv; zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = opline->op2.zv; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -18559,7 +18643,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -18902,7 +18985,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -19468,6 +19551,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19514,9 +19636,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -19901,7 +20024,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -19924,21 +20047,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -19995,15 +20114,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -20011,9 +20134,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -20024,33 +20148,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -20076,30 +20186,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -20256,7 +20353,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -20284,21 +20381,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -20351,7 +20444,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -20377,19 +20470,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -20460,11 +20549,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20486,6 +20572,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -20527,6 +20614,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20558,6 +20646,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -20616,7 +20705,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20640,7 +20729,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20702,7 +20791,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20728,7 +20817,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -20773,29 +20862,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -20809,7 +20902,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -21526,9 +21618,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -21913,7 +22006,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -21936,21 +22029,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -22007,15 +22096,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -22023,9 +22116,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -22036,33 +22130,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -22088,30 +22168,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); @@ -22268,7 +22335,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -22296,21 +22363,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -22363,7 +22426,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -22389,19 +22452,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -22551,9 +22610,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -22623,11 +22679,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22649,6 +22702,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -22690,6 +22744,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22721,6 +22776,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -22779,7 +22835,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22803,7 +22859,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22865,7 +22921,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22891,7 +22947,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -22936,29 +22992,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -22972,7 +23032,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -23026,10 +23085,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!(free_op2.var != NULL)) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -23046,15 +23108,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL } variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -23853,6 +23914,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_ptr_dtor_nogc(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -23899,9 +23999,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -24011,7 +24112,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -24034,21 +24135,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -24104,15 +24201,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -24120,9 +24221,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -24133,33 +24235,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -24185,31 +24272,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -24464,9 +24537,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -24521,11 +24591,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -24547,6 +24614,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -24573,6 +24641,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -24604,29 +24673,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = NULL; zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = NULL; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -24640,7 +24713,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -25104,9 +25176,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -25476,7 +25549,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -25499,21 +25572,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -25569,15 +25638,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op1, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_VAR != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -25585,9 +25658,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -25598,33 +25672,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -25650,31 +25709,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -25830,7 +25875,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -25858,21 +25903,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -25924,7 +25965,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -25950,19 +25991,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -26032,11 +26069,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26058,6 +26092,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -26099,6 +26134,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26130,6 +26166,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -26187,7 +26224,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26211,7 +26248,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26272,7 +26309,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26298,7 +26335,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -26343,29 +26380,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -26379,7 +26420,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -26432,10 +26472,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!0) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -26452,15 +26495,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE } variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -27154,9 +27196,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_VAR == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -27346,7 +27389,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -27369,21 +27412,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -27438,15 +27477,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -27454,9 +27497,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -27467,33 +27511,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -27519,31 +27548,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -27699,7 +27714,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -27727,21 +27742,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -27793,7 +27804,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -27819,19 +27830,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -27921,7 +27928,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -27945,7 +27952,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28006,7 +28013,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28032,7 +28039,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -28262,7 +28269,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv)); } else { - ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC); + ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, 0 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -28640,9 +28647,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -28736,7 +28744,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -28759,21 +28767,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -28829,15 +28833,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -28845,9 +28853,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -28858,33 +28867,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -28910,30 +28905,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -29090,7 +29072,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -29118,21 +29100,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -29185,7 +29163,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -29211,19 +29189,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -29315,7 +29289,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29339,7 +29313,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29401,7 +29375,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29427,7 +29401,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -29948,9 +29922,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -30044,7 +30019,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -30067,21 +30042,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -30137,15 +30108,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -30153,9 +30128,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -30166,33 +30142,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -30218,30 +30180,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -30398,7 +30347,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -30426,21 +30375,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -30493,7 +30438,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -30519,19 +30464,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -30623,7 +30564,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30647,7 +30588,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30709,7 +30650,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -30735,7 +30676,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -31256,9 +31197,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -31352,7 +31294,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -31375,21 +31317,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -31444,15 +31382,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -31460,9 +31402,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -31473,33 +31416,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -31525,31 +31453,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -31775,9 +31689,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -31871,7 +31786,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zval *object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -31894,21 +31809,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -31963,15 +31874,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -31979,9 +31894,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -31992,33 +31908,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -32044,31 +31945,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -32224,7 +32111,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -32252,21 +32139,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -32318,7 +32201,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); @@ -32344,19 +32227,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -32446,7 +32325,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32470,7 +32349,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32531,7 +32410,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -32557,7 +32436,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -33074,9 +32953,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_UNUSED == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_UNUSED == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -33603,10 +33483,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } - if (IS_CV == IS_VAR && !Z_ISREF_P(retval_ptr)) { - if (opline->extended_value == ZEND_RETURNS_FUNCTION && - (Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF)) { - } else { + if (IS_CV == IS_VAR) { + if (retval_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); @@ -34456,27 +34336,6 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ZEND_VM_NEXT_OPCODE(); } -static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *expr; - zend_bool result; - - SAVE_OPLINE(); - expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - - if (Z_TYPE_P(expr) == IS_OBJECT) { - result = instanceof_function(Z_OBJCE_P(expr), Z_CE_P(EX_VAR(opline->op2.var)) TSRMLS_CC); - } else { - result = 0; - } - ZVAL_BOOL(EX_VAR(opline->result.var), result); - - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34846,7 +34705,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = opline->op2.zv; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -34869,21 +34728,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -34938,15 +34793,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -34954,9 +34813,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi } else { zval *dim = opline->op2.zv; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -34967,33 +34827,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -35019,31 +34864,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -35199,7 +35030,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -35227,21 +35058,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -35293,7 +35120,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -35319,19 +35146,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -35480,9 +35303,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -35552,11 +35372,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35578,6 +35395,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -35619,6 +35437,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35650,6 +35469,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -35707,7 +35527,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35731,7 +35551,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35792,7 +35612,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35818,7 +35638,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -35896,29 +35716,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = opline->op2.zv; zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = opline->op2.zv; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -35932,7 +35756,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -36618,6 +36441,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -36664,9 +36526,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -37107,7 +36970,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -37130,21 +36993,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -37200,15 +37059,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -37216,9 +37079,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina } else { zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -37229,33 +37093,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -37281,30 +37131,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -37461,7 +37298,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -37489,21 +37326,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -37556,7 +37389,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -37582,19 +37415,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -37665,11 +37494,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37691,6 +37517,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -37732,6 +37559,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37763,6 +37591,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -37821,7 +37650,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37845,7 +37674,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37907,7 +37736,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37933,7 +37762,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -37978,29 +37807,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -38014,7 +37847,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -38605,9 +38437,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -38991,7 +38824,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -39014,21 +38847,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - if (!have_get_ptr) { + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); + + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -39084,15 +38913,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op2, free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op2, free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -39100,9 +38933,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina } else { zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -39113,33 +38947,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: zval_ptr_dtor_nogc(free_op2.var); FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -39165,30 +38985,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: zval_ptr_dtor_nogc(free_op2.var); CHECK_EXCEPTION(); @@ -39345,7 +39152,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -39373,21 +39180,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -39440,7 +39243,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -39466,19 +39269,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -39628,9 +39427,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -39700,11 +39496,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39726,6 +39519,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -39767,6 +39561,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39798,6 +39593,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -39856,7 +39652,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39880,7 +39676,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39942,7 +39738,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -39968,7 +39764,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -40013,29 +39809,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); } else { - zend_free_op free_op2, free_op_data1, free_op_data2; + zend_free_op free_op2, free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -40049,7 +39849,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -40103,10 +39902,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_VAR == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!(free_op2.var != NULL)) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -40123,15 +39925,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE } variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -40802,6 +40603,45 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *expr; + zend_bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); + if (UNEXPECTED(ce == NULL)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = instanceof_function(Z_OBJCE_P(expr), ce TSRMLS_CC); + } else { + result = 0; + } + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40848,9 +40688,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -40959,7 +40800,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = NULL; zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -40982,21 +40823,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -41051,15 +40888,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -41067,9 +40908,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b } else { zval *dim = NULL; - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -41080,33 +40922,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -41132,31 +40959,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -41411,9 +41224,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, } ZVAL_COPY(EX_VAR(opline->result.var), retval); } else { - if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } CHECK_EXCEPTION(); @@ -41468,11 +41278,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -41494,6 +41301,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -41520,6 +41328,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -41551,29 +41360,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = NULL; zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = NULL; zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -41587,7 +41400,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -41908,9 +41720,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -42279,7 +42092,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *value; - int have_get_ptr = 0; + zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); @@ -42302,21 +42115,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar } else { /* here we are sure we are dealing with an object */ if (opline->extended_value == ZEND_ASSIGN_OBJ - && Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - have_get_ptr = 1; - binary_op(zptr, zptr, value TSRMLS_CC); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } + && EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { + + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + binary_op(zptr, zptr, value TSRMLS_CC); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } else { zval *z = NULL; zval rv; @@ -42371,15 +42180,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op_data2, free_op_data1; - zval *var_ptr; + zend_free_op free_op_data1; + zval *var_ptr, rv; zval *value, *container; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + } + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(container); + } + if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { Z_ADDREF_P(container); /* undo the effect of get_obj_zval_ptr_ptr() */ } @@ -42387,9 +42200,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar } else { zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC); + zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC); value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); } if (UNEXPECTED(var_ptr == NULL)) { @@ -42400,33 +42214,18 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_dim_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_dim_exit: - FREE_OP(free_op_data1); - FREE_OP_VAR_PTR(free_op_data2); CHECK_EXCEPTION(); ZEND_VM_INC_OPCODE(); @@ -42452,31 +42251,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } - goto assign_op_exit; - } - - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); - - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT) && - UNEXPECTED(Z_OBJ_HANDLER_P(var_ptr, get) && Z_OBJ_HANDLER_P(var_ptr, set))) { - /* proxy object */ - zval rv; - zval *objval = Z_OBJ_HANDLER_P(var_ptr, get)(var_ptr, &rv TSRMLS_CC); - Z_ADDREF_P(objval); - binary_op(objval, objval, value TSRMLS_CC); - Z_OBJ_HANDLER_P(var_ptr, set)(var_ptr, objval TSRMLS_CC); - zval_ptr_dtor(objval); } else { + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + binary_op(var_ptr, var_ptr, value TSRMLS_CC); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } } -assign_op_exit: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -42632,7 +42417,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -42660,21 +42445,17 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - have_get_ptr = 1; - incdec_op(zptr); - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(retval, zptr); - } - } - } + ZVAL_DEREF(zptr); + SEPARATE_ZVAL_NOREF(zptr); - if (!have_get_ptr) { + incdec_op(zptr); + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(retval, zptr); + } + } else { zval rv; if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { @@ -42726,7 +42507,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zval *object; zval *property; zval *retval; - int have_get_ptr = 0; + zval *zptr; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); @@ -42752,19 +42533,15 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in /* here we are sure we are dealing with an object */ - if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) { - zval *zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC); - if (zptr != NULL) { /* NULL means no success in getting PTR */ - have_get_ptr = 1; - ZVAL_DEREF(zptr); - ZVAL_COPY(retval, zptr); + if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr) + && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL) TSRMLS_CC)) != NULL)) { - SEPARATE_ZVAL_NOREF(zptr); - incdec_op(zptr); - } - } + ZVAL_DEREF(zptr); + ZVAL_COPY(retval, zptr); - if (!have_get_ptr) { + SEPARATE_ZVAL_NOREF(zptr); + incdec_op(zptr); + } else { if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) { zval rv; zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), &rv TSRMLS_CC); @@ -42834,11 +42611,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (EXPECTED(opline->extended_value == 0)) { - zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } else { - zend_fetch_dimension_address_W_ref(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); - } + ZVAL_DEREF(container); + zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42860,6 +42634,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -42901,6 +42676,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -42932,6 +42708,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } + ZVAL_DEREF(container); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { @@ -42989,7 +42766,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, (opline->extended_value & ZEND_FETCH_MAKE_REF) != 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43013,7 +42790,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43074,7 +42851,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43100,7 +42877,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); @@ -43145,29 +42922,33 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { - object_ptr = Z_REFVAL_P(object_ptr); - } - if (Z_TYPE_P(object_ptr) == IS_OBJECT) { + ZVAL_DEREF(object_ptr); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); } else { - zend_free_op free_op_data1, free_op_data2; + zend_free_op free_op_data1; + zval rv; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval *variable_ptr; - variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && + EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - if (UNEXPECTED(variable_ptr != NULL)) { - zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); FREE_OP(free_op_data1); } else { - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC); + + value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + variable_ptr = Z_INDIRECT(rv); if (UNEXPECTED(variable_ptr == &EG(error_zval))) { FREE_OP(free_op_data1); if (RETURN_VALUE_USED(opline)) { @@ -43181,7 +42962,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } - FREE_OP_VAR_PTR(free_op_data2); } } } @@ -43234,10 +43014,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && - opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF) && - !Z_ISREF_P(value_ptr)) { + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { if (!0) { PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */ } @@ -43254,15 +43037,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER } variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || - (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); - } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { variable_ptr = &EG(uninitialized_zval); @@ -43829,9 +43611,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* If a function call result is yielded and the function did * not return by reference we throw a notice. */ - if (IS_CV == IS_VAR && !Z_ISREF_P(value_ptr) - && !(opline->extended_value == ZEND_RETURNS_FUNCTION - && (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + if (IS_CV == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -45643,31 +45426,31 @@ void zend_init_opcodes_handlers(void) ZEND_SEND_REF_SPEC_CV_HANDLER, ZEND_SEND_REF_SPEC_CV_HANDLER, ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, - ZEND_NEW_SPEC_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -47398,26 +47181,26 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_TMP_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_VAR_HANDLER, + ZEND_INSTANCEOF_SPEC_TMP_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMP_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_VAR_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER, ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, ZEND_DECLARE_CLASS_SPEC_HANDLER, |