From: Nikita Popov Date: Thu, 14 Jul 2016 16:39:48 +0000 (+0200) Subject: Merge branch 'PHP-7.0' X-Git-Tag: php-7.1.0beta1~61^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0bda0422af0a9a920135bf3d7b7b4784eb0df802;p=php Merge branch 'PHP-7.0' Conflicts: Zend/zend_vm_execute.h --- 0bda0422af0a9a920135bf3d7b7b4784eb0df802 diff --cc Zend/zend_vm_def.h index a40b2cb39c,c1e985ea1d..ecac3c0dd8 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -2437,20 -2302,27 +2437,21 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA SAVE_OPLINE(); value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); + variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_throw_error(NULL, "Cannot create references to/from string offsets nor overloaded objects"); - FREE_UNFETCHED_OP1(); - HANDLE_EXCEPTION(); - } if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + FREE_OP1_VAR_PTR(); FREE_OP2_VAR_PTR(); HANDLE_EXCEPTION(); - } - if (OP2_TYPE == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!OP2_FREE && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (OP2_TYPE == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP2_VAR_PTR(); diff --cc Zend/zend_vm_execute.h index 5a53938ef3,3203af2c85..094fb8f827 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -20326,289 -19714,170 +20332,290 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; - zval *object; - zval *property; + zend_free_op free_op1, free_op2; zval *value; - zval *zptr; + zval *variable_ptr; SAVE_OPLINE(); - object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { - zend_throw_error(NULL, "Using $this when not in object context"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - - HANDLE_EXCEPTION(); - } - - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - - if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_throw_error(NULL, "Cannot use string offset as an object"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - - HANDLE_EXCEPTION(); - } - - do { - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - ZVAL_DEREF(object); - if (UNEXPECTED(!make_real_object(object))) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - break; - } + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); } - - /* here we are sure we are dealing with an object */ - 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) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) { - if (UNEXPECTED(zptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - } else { - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - binary_op(zptr, zptr, value); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } - } - } else { - zend_assign_op_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); } - } while (0); - - FREE_OP(free_op_data1); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - /* assign_obj has two opcodes! */ - ZEND_VM_NEXT_OPCODE_EX(1, 2); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1, free_op_data1; - zval *var_ptr, rv; - zval *value, *container, *dim; + zend_free_op free_op1, free_op2; + zval *value; + zval *variable_ptr; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) { - zend_throw_error(NULL, "Using $this when not in object context"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - HANDLE_EXCEPTION(); + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ } - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_throw_error(NULL, "Cannot use string offset as an array"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *variable_ptr; + zval *value_ptr; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); ++ if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); - } - dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } - do { - if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { - if (IS_VAR != IS_UNUSED) { - ZVAL_DEREF(container); - } - if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op); - break; - } + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ - zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV); - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); + } else { - if (UNEXPECTED(var_ptr == NULL)) { - zend_throw_error(NULL, "Cannot use assign-op operators with overloaded objects nor string offsets"); + if ((IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } - FREE_OP(free_op_data1); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - HANDLE_EXCEPTION(); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - if (UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + } + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(execute_data); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && + (value_ptr == &EG(uninitialized_zval) || + (opline->extended_value == ZEND_RETURNS_FUNCTION && + !Z_ISREF_P(value_ptr)))) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + } else { + ZVAL_MAKE_REF(value_ptr); + } + ZVAL_COPY(&generator->value, value_ptr); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->value, value); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(free_op1); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } - binary_op(var_ptr, var_ptr, value); + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->key, key); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->key))) { + Z_ADDREF(generator->key); + } + } else if (IS_VAR == IS_TMP_VAR) { + ZVAL_COPY_VALUE(&generator->key, key); + } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) { + ZVAL_COPY(&generator->key, Z_REFVAL_P(key)); + zval_ptr_dtor_nogc(free_op2); + } else { + ZVAL_COPY_VALUE(&generator->key, key); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key); } } - } while (0); - FREE_OP(free_op_data1); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE_EX(1, 2); + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE - zend_free_op free_op1; + zend_free_op free_op1, free_op_data1; zval *var_ptr; - zval *value; + zval *value, *container, *dim; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_throw_error(NULL, "Cannot use assign-op operators with overloaded objects nor string offsets"); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - HANDLE_EXCEPTION(); - } + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); +assign_dim_op_new_array: + if (IS_UNUSED == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + goto assign_dim_op_ret_null; + } + } else { + dim = NULL; - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + if (IS_UNUSED == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); } - } else { - ZVAL_DEREF(var_ptr); - SEPARATE_ZVAL_NOREF(var_ptr); + + value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); binary_op(var_ptr, var_ptr, value); @@@ -24165,270 -23085,316 +24172,271 @@@ assign_dim_error ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CONST != IS_UNUSED) USE_OPLINE + zend_free_op free_op1; + zval *value; + zval *variable_ptr; -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(add_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(add_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(sub_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(sub_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CONST != IS_UNUSED) USE_OPLINE + zend_free_op free_op1; + zval *value; + zval *variable_ptr; -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mul_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mul_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(div_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(div_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CONST != IS_UNUSED) USE_OPLINE + zend_free_op free_op1; + zval *variable_ptr; + zval *value_ptr; -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mod_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mod_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_left_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_left_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); ++ if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + HANDLE_EXCEPTION(); -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_right_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_right_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + HANDLE_EXCEPTION(); + } -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(concat_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(concat_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + } else { -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_or_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_or_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + if ((IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_and_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_and_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { -#if 0 || (IS_CONST != IS_UNUSED) USE_OPLINE + zval *function_name; + zend_class_entry *ce; + zend_object *object; + zend_function *fbc; + zend_execute_data *call; -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_xor_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_xor_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} + SAVE_OPLINE(); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ -#if 0 || (IS_CONST != IS_UNUSED) - USE_OPLINE + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); -# if 0 || (IS_UNUSED != IS_UNUSED) - if (EXPECTED(opline->extended_value == 0)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_helper_SPEC_UNUSED_CONST(pow_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } -# endif - if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(pow_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); - } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ { - ZEND_VM_TAIL_CALL(zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(pow_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); } -#else - ZEND_VM_TAIL_CALL(zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(pow_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); -#endif -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC) -{ - USE_OPLINE - zval *object; - zval *property; - zval *zptr; + if (IS_VAR == IS_CONST && + IS_CV == IS_CONST && + EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + IS_CV == IS_CONST && + (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) { + /* do nothing */ + } else if (IS_CV != IS_UNUSED) { - SAVE_OPLINE(); - object = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { - zend_throw_error(NULL, "Using $this when not in object context"); + function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); + } while (0); + } + } - property = EX_CONSTANT(opline->op2); + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), Z_STRVAL_P(function_name)); + } - if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_throw_error(NULL, "Cannot increment/decrement overloaded objects nor string offsets"); + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { + if (IS_VAR == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CV != IS_CONST) { - HANDLE_EXCEPTION(); + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) { + init_func_run_time_cache(&fbc->op_array); + } } - do { - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - ZVAL_DEREF(object); - if (UNEXPECTED(!make_real_object(object))) { - zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + object = NULL; + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + object = Z_OBJ(EX(This)); + ce = object->ce; + } else { + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + /* Allowed for PHP 4 compatibility. */ + zend_error( + E_DEPRECATED, + "Non-static method %s::%s() should not be called statically", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } - break; + } else { + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_throw_error( + zend_ce_error, + "Non-static method %s::%s() cannot be called statically", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); + HANDLE_EXCEPTION(); } } + } - /* here we are sure we are dealing with an object */ - 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) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) { - if (UNEXPECTED(zptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } + if (IS_VAR == IS_UNUSED) { + /* previous opcode is ZEND_FETCH_CLASS */ + if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); } else { - if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) { - if (inc) { - fast_long_increment_function(zptr); - } else { - fast_long_decrement_function(zptr); - } - } else { - ZVAL_DEREF(zptr); - SEPARATE_ZVAL_NOREF(zptr); - - if (inc) { - increment_function(zptr); - } else { - decrement_function(zptr); - } - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), zptr); - } + ce = Z_CE(EX(This)); } - } else { - zend_pre_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); } - } while (0); + } + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, ce, object); + call->prev_execute_data = EX(call); + EX(call) = call; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@@ -35621,122 -26065,129 +35629,124 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS HANDLE_EXCEPTION(); } - offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - - if (IS_UNUSED == IS_CONST || - (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - goto fetch_obj_is_no_object; - } - } else { - goto fetch_obj_is_no_object; + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); } - } + Z_FE_POS(generator->values) = 0; - /* here we are sure we are dealing with an object */ - do { - zend_object *zobj = Z_OBJ_P(container); - zval *retval; + } else if (IS_CV != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); - if (IS_CV == IS_CONST && - EXPECTED(zobj->ce == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) { - uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + sizeof(void*)); + if (IS_CV != IS_TMP_VAR) { + Z_ADDREF_P(val); + } - if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { - retval = OBJ_PROP(zobj, prop_offset); - if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; + if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); ++ zval_ptr_dtor(val); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); } - } else if (EXPECTED(zobj->properties != NULL)) { - retval = zend_hash_find(zobj->properties, Z_STR_P(offset)); - if (EXPECTED(retval)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); - break; + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); ++ zval_ptr_dtor(val); + HANDLE_EXCEPTION(); + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); } + ZEND_VM_NEXT_OPCODE(); } - } - - if (UNEXPECTED(zobj->handlers->read_property == NULL)) { -fetch_obj_is_no_object: - ZVAL_NULL(EX_VAR(opline->result.var)); } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var)); - - if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY(EX_VAR(opline->result.var), retval); + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + HANDLE_EXCEPTION(); } - } - } while (0); - - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *container; - if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - /* Behave like FETCH_OBJ_W */ - zend_free_op free_op1; - zval *property; - - SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - container = _get_obj_zval_ptr_unused(execute_data); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) { - zend_throw_error(NULL, "Using $this when not in object context"); + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + HANDLE_EXCEPTION(); + } + } - HANDLE_EXCEPTION(); + ZVAL_OBJ(&generator->values, &iter->std); } - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zend_throw_error(NULL, "Cannot use temporary expression in write context"); + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + HANDLE_EXCEPTION(); + } + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } - HANDLE_EXCEPTION(); - } - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_throw_error(NULL, "Cannot use string offset as an object"); + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; - HANDLE_EXCEPTION(); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var), 0); - } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } + ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zend_free_op free_op1; - zval *container, *property; - - SAVE_OPLINE(); - container = _get_obj_zval_ptr_unused(execute_data); - - if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(container) == NULL)) { - zend_throw_error(NULL, "Using $this when not in object context"); - - HANDLE_EXCEPTION(); - } + zval *value; - property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_throw_error(NULL, "Cannot use string offset as an object"); + SAVE_OPLINE(); + value = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); +try_strlen: + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + } else { + zend_bool strict; - HANDLE_EXCEPTION(); - } - zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = GET_OP1_UNDEF_CV(value, BP_VAR_R); + } + if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { + value = Z_REFVAL_P(value); + goto try_strlen; + } + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + zend_string *str; + zval tmp; - if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) { - EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var), 0); + ZVAL_COPY(&tmp, value); + if (zend_parse_arg_str_weak(&tmp, &str)) { + ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); + zval_ptr_dtor(&tmp); + break; + } + zval_ptr_dtor(&tmp); + } + zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_NULL(EX_VAR(opline->result.var)); + } while (0); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@@ -40567,301 -29362,330 +40577,302 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS { USE_OPLINE - zval *array_ptr, *result; - HashTable *fe_ht; + zval *varname; + zval *retval; + zend_string *name; + zend_class_entry *ce; SAVE_OPLINE(); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); - array_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); - if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { - result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(array_ptr); + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + zend_string_addref(name); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + GET_OP1_UNDEF_CV(varname, BP_VAR_R); } - Z_FE_POS_P(result) = 0; + name = zval_get_string(varname); + } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashPosition pos = 0; - Bucket *p; + if (IS_VAR == IS_CONST) { + if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) { + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*)); - result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); - if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); - } - fe_ht = Z_OBJPROP_P(array_ptr); - pos = 0; - p = fe_ht->arData; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } - if ((EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(Z_TYPE(p->val) != IS_INDIRECT) || - EXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF))) && - (UNEXPECTED(!p->key) || - EXPECTED(zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS))) { - break; - } - pos++; - p++; + HANDLE_EXCEPTION(); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0); - zend_bool is_empty; - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + goto fetch_static_prop_return; + } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); + } + } else { + if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + if (IS_CV != IS_CONST) { + zend_string_release(name); } - zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + if (IS_CV == IS_CONST && + (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) { - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name)); - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - is_empty = iter->funcs->valid(iter) != SUCCESS; - - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); + goto fetch_static_prop_return; + } + } + retval = zend_std_get_static_property(ce, name, 0); + if (UNEXPECTED(EG(exception))) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && retval) { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval); + } - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + if (IS_CV != IS_CONST) { + zend_string_release(name); + } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - } +fetch_static_prop_return: + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - USE_OPLINE + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - zval *array_ptr, *array_ref; - HashTable *fe_ht; - HashPosition pos = 0; - Bucket *p; +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - SAVE_OPLINE(); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - if (IS_CV == IS_VAR || IS_CV == IS_CV) { - array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - if (Z_ISREF_P(array_ref)) { - array_ptr = Z_REFVAL_P(array_ref); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } else { - array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } +} - if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { - if (IS_CV == IS_VAR || IS_CV == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ref = EX_VAR(opline->result.var); - ZVAL_NEW_REF(array_ref, array_ptr); - array_ptr = Z_REFVAL_P(array_ref); - } - if (IS_CV == IS_CONST) { - zval_copy_ctor_func(array_ptr); - } else { - SEPARATE_ARRAY(array_ptr); - } - fe_ht = Z_ARRVAL_P(array_ptr); - p = fe_ht->arData; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } - if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(Z_TYPE(p->val) != IS_INDIRECT) || - EXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF))) { - break; - } - pos++; - p++; - } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); +} - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - if (IS_CV == IS_VAR || IS_CV == IS_CV) { - if (array_ptr == array_ref) { - ZVAL_NEW_REF(array_ref, array_ref); - array_ptr = Z_REFVAL_P(array_ref); - } - Z_ADDREF_P(array_ref); - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); - } else { - array_ptr = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(array_ptr, array_ref); - } - fe_ht = Z_OBJPROP_P(array_ptr); - p = fe_ht->arData; - while (1) { - if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *value; + zval *variable_ptr; - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } - if ((EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(Z_TYPE(p->val) != IS_INDIRECT) || - EXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF))) && - (UNEXPECTED(!p->key) || - EXPECTED(zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS))) { - break; - } - pos++; - p++; - } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos); + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_class_entry *ce = Z_OBJCE_P(array_ptr); - zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1); - zend_bool is_empty; + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } - if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { - if (IS_CV == IS_VAR) { + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } - } else { + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - } - if (!EG(exception)) { - zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); - } - zend_throw_exception_internal(NULL); - HANDLE_EXCEPTION(); - } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *value; + zval *variable_ptr; - iter->index = 0; - if (iter->funcs->rewind) { - iter->funcs->rewind(iter); - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CV == IS_VAR) { + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - } else { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } - } - HANDLE_EXCEPTION(); - } - } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } - is_empty = iter->funcs->valid(iter) != SUCCESS; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} - if (UNEXPECTED(EG(exception) != NULL)) { - OBJ_RELEASE(&iter->std); - if (IS_CV == IS_VAR) { +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *variable_ptr; + zval *value_ptr; - } else { + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - } - HANDLE_EXCEPTION(); - } - iter->index = -1; /* will be set to 0 before using next handler */ + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { - ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); + - if (IS_CV == IS_VAR) { + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); - } else { + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + HANDLE_EXCEPTION(); + } - } - if (is_empty) { - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); - } else { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - if (IS_CV == IS_VAR) { + if ((IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); } - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE + zval tmp, *varname; + zend_class_entry *ce; - SAVE_OPLINE(); - if (IS_CV != IS_UNUSED) { - zval *ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + SAVE_OPLINE(); - do { - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - } else { - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) { - ptr = Z_REFVAL_P(ptr); - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - break; - } - } - zend_print_variable(ptr); - } - } while (0); + varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + ZVAL_UNDEF(&tmp); + if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R); + } + ZVAL_STR(&tmp, zval_get_string(varname)); + varname = &tmp; } - zend_bailout(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - zval *value; - zval *ref = NULL; - SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + } + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); + } - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - if (IS_CV == IS_VAR) { - ref = value; + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } - value = Z_REFVAL_P(value); - } - if (i_zend_is_true(value)) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - zval_copy_ctor_func(EX_VAR(opline->result.var)); + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ZEND_ASSERT(EG(exception)); + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); } - } else if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); - } else if (IS_CV == IS_VAR && ref) { - zend_reference *r = Z_REF_P(ref); - if (UNEXPECTED(--GC_REFCOUNT(r) == 0)) { - efree_size(r, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } + HANDLE_EXCEPTION(); } - ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + zend_std_unset_static_property(ce, Z_STR_P(varname)); + + if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) { + zend_string_release(Z_STR(tmp)); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@@ -45959,31 -34560,24 +45970,32 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *container; - zend_free_op free_op1; + + zval *variable_ptr; + zval *value_ptr; SAVE_OPLINE(); + value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_throw_error(NULL, "Cannot use temporary expression in write context"); + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); - HANDLE_EXCEPTION(); - } - container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_throw_error(NULL, "Cannot use string offset as an array"); ++ + HANDLE_EXCEPTION(); + + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); + if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); }