From 8ee605d8c346d4ba94a68c3402f4680851eb02e0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 25 Feb 2013 16:40:37 +0100 Subject: [PATCH] Allow (...)->foo() type expressions not only for `new` --- Zend/zend_language_parser.y | 5 +- Zend/zend_vm_def.h | 10 +- Zend/zend_vm_execute.h | 1206 ++++++++++++++++++++++++++++++- tests/lang/clone_expr_call.phpt | 25 + 4 files changed, 1210 insertions(+), 36 deletions(-) create mode 100644 tests/lang/clone_expr_call.phpt diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index ccbc9b174c9d..7057e1f12093 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -50,7 +50,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %} %pure_parser -%expect 3 +%expect 2 %token END 0 "end of file" %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE @@ -783,9 +783,8 @@ expr_without_variable: | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); } | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } - | parenthesis_expr { $$ = $1; } + | parenthesis_expr { $$ = $1; } instance_call { $$ = $3; } | new_expr { $$ = $1; } - | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0aaed2e465a8..a85648f06466 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1248,7 +1248,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1334,7 +1334,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) } } -ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1377,7 +1377,7 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper); } @@ -1462,7 +1462,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -2421,7 +2421,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV) } } -ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zval *function_name; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2fe18fbceec7..81711bc4c32b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3515,6 +3515,109 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3539,6 +3642,85 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + char *function_name_strval; + int function_name_strlen; + + call_slot *call = EX(call_slots) + opline->result.num; + + SAVE_OPLINE(); + + function_name = opline->op2.zv; + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); + + call->object = opline->op1.zv; + + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); + + if (IS_CONST != IS_CONST || + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; + + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); + } + if (IS_CONST == IS_CONST && + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); + } + } + } else { + if (UNEXPECTED(EG(exception) != NULL)) { + + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); + } + + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; + } else { + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + INIT_PZVAL_COPY(this_ptr, call->object); + zval_copy_ctor(this_ptr); + call->object = this_ptr; + } + } + call->is_ctor_call = 0; + EX(call) = call; + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4532,6 +4714,189 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + zval_dtor(free_op2.var); + } else { + zval *retval; + + if (1) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (1) { + zval_ptr_dtor(&offset); + } else { + zval_dtor(free_op2.var); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + zval_dtor(free_op2.var); + } else { + zval *retval; + + if (1) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (1) { + zval_ptr_dtor(&offset); + } else { + zval_dtor(free_op2.var); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + char *function_name_strval; + int function_name_strlen; + zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; + + SAVE_OPLINE(); + + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (IS_TMP_VAR != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); + + call->object = opline->op1.zv; + + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); + + if (IS_TMP_VAR != IS_CONST || + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; + + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); + } + if (IS_TMP_VAR == IS_CONST && + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); + } + } + } else { + if (UNEXPECTED(EG(exception) != NULL)) { + zval_dtor(free_op2.var); + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); + } + + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; + } else { + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + INIT_PZVAL_COPY(this_ptr, call->object); + zval_copy_ctor(this_ptr); + call->object = this_ptr; + } + } + call->is_ctor_call = 0; + EX(call) = call; + + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5394,6 +5759,189 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + char *function_name_strval; + int function_name_strlen; + zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; + + SAVE_OPLINE(); + + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (IS_VAR != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); + + call->object = opline->op1.zv; + + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); + + if (IS_VAR != IS_CONST || + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; + + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); + } + if (IS_VAR == IS_CONST && + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); + } + } + } else { + if (UNEXPECTED(EG(exception) != NULL)) { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); + } + + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; + } else { + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + INIT_PZVAL_COPY(this_ptr, call->object); + zval_copy_ctor(this_ptr); + call->object = this_ptr; + } + } + call->is_ctor_call = 0; + EX(call) = call; + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6971,6 +7519,188 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + char *function_name_strval; + int function_name_strlen; + + call_slot *call = EX(call_slots) + opline->result.num; + + SAVE_OPLINE(); + + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Method name must be a string"); + } + + function_name_strval = Z_STRVAL_P(function_name); + function_name_strlen = Z_STRLEN_P(function_name); + + call->object = opline->op1.zv; + + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); + + if (IS_CV != IS_CONST || + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; + + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { + zend_error_noreturn(E_ERROR, "Object does not support method calls"); + } + + /* First, locate the function. */ + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); + } + if (IS_CV == IS_CONST && + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); + } + } + } else { + if (UNEXPECTED(EG(exception) != NULL)) { + + HANDLE_EXCEPTION(); + } + zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); + } + + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; + } else { + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + INIT_PZVAL_COPY(this_ptr, call->object); + zval_copy_ctor(this_ptr); + call->object = this_ptr; + } + } + call->is_ctor_call = 0; + EX(call) = call; + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8889,6 +9619,111 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9775,6 +10610,111 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + zval_dtor(free_op2.var); + } else { + zval *retval; + + if (1) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (1) { + zval_ptr_dtor(&offset); + } else { + zval_dtor(free_op2.var); + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + zval_dtor(free_op2.var); + } else { + zval *retval; + + if (1) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (1) { + zval_ptr_dtor(&offset); + } else { + zval_dtor(free_op2.var); + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10641,6 +11581,111 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -12083,6 +13128,111 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + zend_error(E_NOTICE, "Trying to get property of non-object"); + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + PZVAL_LOCK(&EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + } else { + zval *retval; + + if (0) { + MAKE_REAL_ZVAL_PTR(offset); + } + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + + PZVAL_LOCK(retval); + AI_SET_PTR(&EX_T(opline->result.var), retval); + + if (0) { + zval_ptr_dtor(&offset); + } else { + + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -43016,16 +44166,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_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_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER, @@ -43216,16 +44366,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER, ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_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_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER, @@ -43241,16 +44391,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_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_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER, @@ -43766,11 +44916,11 @@ void zend_init_opcodes_handlers(void) ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_TMP_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER, ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER, diff --git a/tests/lang/clone_expr_call.phpt b/tests/lang/clone_expr_call.phpt new file mode 100644 index 000000000000..50850598ac57 --- /dev/null +++ b/tests/lang/clone_expr_call.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test call on a clone expression in parentheses +--FILE-- +bar = 'bar'; + } + + public function bar() { + return $this->bar; + } +} + +$foo = new Foo; +var_dump((clone $foo)->bar); +var_dump((clone $foo)->bar()); + +?> +--EXPECT-- +string(3) "bar" +string(3) "bar"