mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Detect calls to abstract methods in get_method() already
Instead of checking for this during DO_FCALL, already detect this case during get_method()/get_static_method(), similar to visibility checks. This causes a minor difference in behavior, in that arguments will no longer be evaluated. I think this is correct though (and consistent with visibility errors).
This commit is contained in:
parent
8522cdd6fa
commit
ee4b11c668
8 changed files with 71 additions and 93 deletions
|
@ -1553,12 +1553,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(c
|
|||
ZSTR_VAL(fbc->common.function_name));
|
||||
}
|
||||
|
||||
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_abstract_method(const zend_function *fbc)
|
||||
{
|
||||
zend_throw_error(NULL, "Cannot call abstract method %s::%s()",
|
||||
ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
||||
}
|
||||
|
||||
static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
|
||||
{
|
||||
zend_uchar c;
|
||||
|
|
|
@ -1234,6 +1234,13 @@ static ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc,
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc) /* {{{ */
|
||||
{
|
||||
zend_throw_error(NULL, "Cannot call abstract method %s::%s()",
|
||||
ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */
|
||||
{
|
||||
zend_object *zobj = *obj_ptr;
|
||||
|
@ -1294,6 +1301,10 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
|
|||
}
|
||||
|
||||
exit:
|
||||
if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
zend_abstract_method_call(fbc);
|
||||
fbc = NULL;
|
||||
}
|
||||
if (UNEXPECTED(!key)) {
|
||||
ZSTR_ALLOCA_FREE(lc_method_name, use_heap);
|
||||
}
|
||||
|
@ -1379,6 +1390,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
|
|||
}
|
||||
}
|
||||
|
||||
if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
zend_abstract_method_call(fbc);
|
||||
fbc = NULL;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(!key)) {
|
||||
zend_string_release_ex(lc_function_name, 0);
|
||||
}
|
||||
|
|
|
@ -4154,27 +4154,9 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
|||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
|
||||
zend_abstract_method(fbc);
|
||||
ZEND_VM_C_LABEL(fcall_except):
|
||||
UNDEF_RESULT();
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
ZEND_VM_C_GOTO(fcall_except);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
|
||||
ret = NULL;
|
||||
|
@ -4197,7 +4179,21 @@ ZEND_VM_C_LABEL(fcall_except):
|
|||
zend_execute_ex(call);
|
||||
}
|
||||
} else {
|
||||
zval retval;
|
||||
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
}
|
||||
}
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
|
|
|
@ -1572,27 +1572,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
|||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
|
||||
zend_abstract_method(fbc);
|
||||
fcall_except:
|
||||
UNDEF_RESULT();
|
||||
if (!0) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
goto fcall_except;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
|
||||
ret = NULL;
|
||||
|
@ -1615,7 +1597,21 @@ fcall_except:
|
|||
zend_execute_ex(call);
|
||||
}
|
||||
} else {
|
||||
zval retval;
|
||||
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
if (!0) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
}
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
|
@ -1677,27 +1673,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
|||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
|
||||
zend_abstract_method(fbc);
|
||||
fcall_except:
|
||||
UNDEF_RESULT();
|
||||
if (!1) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
goto fcall_except;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
|
||||
ret = NULL;
|
||||
|
@ -1720,7 +1698,21 @@ fcall_except:
|
|||
zend_execute_ex(call);
|
||||
}
|
||||
} else {
|
||||
zval retval;
|
||||
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
if (!1) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
}
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ static int zend_jit_disasm_init(void)
|
|||
REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
|
||||
REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
|
||||
REGISTER_HELPER(zend_jit_copy_extra_args_helper);
|
||||
REGISTER_HELPER(zend_jit_deprecated_or_abstract_helper);
|
||||
REGISTER_HELPER(zend_jit_deprecated_helper);
|
||||
REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
|
||||
REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
|
||||
REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
|
||||
|
|
|
@ -88,7 +88,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H
|
|||
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS);
|
||||
|
||||
void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D);
|
||||
void ZEND_FASTCALL zend_jit_deprecated_or_abstract_helper(OPLINE_D);
|
||||
void ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D);
|
||||
|
||||
void ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags);
|
||||
int ZEND_FASTCALL zend_jit_check_constant(const zval *key);
|
||||
|
|
|
@ -144,22 +144,14 @@ void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
|
|||
}
|
||||
}
|
||||
|
||||
void ZEND_FASTCALL zend_jit_deprecated_or_abstract_helper(OPLINE_D)
|
||||
void ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
|
||||
{
|
||||
zend_execute_data *call = (zend_execute_data *) opline;
|
||||
zend_function *fbc = call->func;
|
||||
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
|
||||
zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
|
||||
} else if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
|
||||
fbc->common.scope ? "::" : "",
|
||||
ZSTR_VAL(fbc->common.function_name));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
|
||||
fbc->common.scope ? "::" : "",
|
||||
ZSTR_VAL(fbc->common.function_name));
|
||||
if (EG(exception)) {
|
||||
#ifndef HAVE_GCC_GLOBAL_REGS
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
|
|
|
@ -7199,31 +7199,25 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
|
|||
|
||||
if (opline->opcode == ZEND_DO_FCALL) {
|
||||
if (!func) {
|
||||
| test dword [r0 + offsetof(zend_op_array, fn_flags)], (ZEND_ACC_DEPRECATED|ZEND_ACC_ABSTRACT)
|
||||
| test dword [r0 + offsetof(zend_op_array, fn_flags)], ZEND_ACC_DEPRECATED
|
||||
| jnz >1
|
||||
|.cold_code
|
||||
|1:
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| EXT_CALL zend_jit_deprecated_helper, r0
|
||||
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
|
||||
| jne ->exception_handler
|
||||
| mov r0, EX:RX->func // reload
|
||||
| jmp >1
|
||||
|.code
|
||||
|1:
|
||||
} else if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| jmp ->exception_handler
|
||||
} else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| EXT_CALL zend_jit_deprecated_helper, r0
|
||||
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
|
||||
| jne ->exception_handler
|
||||
| mov r0, EX:RX->func // reload
|
||||
|
@ -7415,31 +7409,25 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
|
|||
}
|
||||
if (opline->opcode == ZEND_DO_FCALL_BY_NAME) {
|
||||
if (!func) {
|
||||
| test dword [r0 + offsetof(zend_op_array, fn_flags)], (ZEND_ACC_DEPRECATED|ZEND_ACC_ABSTRACT)
|
||||
| test dword [r0 + offsetof(zend_op_array, fn_flags)], ZEND_ACC_DEPRECATED
|
||||
| jnz >1
|
||||
|.cold_code
|
||||
|1:
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| EXT_CALL zend_jit_deprecated_helper, r0
|
||||
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
|
||||
| jne ->exception_handler
|
||||
| mov r0, EX:RX->func // reload
|
||||
| jmp >1
|
||||
|.code
|
||||
|1:
|
||||
} else if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| jmp ->exception_handler
|
||||
} else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
if (!GCC_GLOBAL_REGS) {
|
||||
| mov FCARG1a, RX
|
||||
}
|
||||
| EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
|
||||
| EXT_CALL zend_jit_deprecated_helper, r0
|
||||
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
|
||||
| jne ->exception_handler
|
||||
| mov r0, EX:RX->func // reload
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue