From bc288c47230919c326b82133ff5306f4eff690b4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 13 Sep 2018 13:36:09 +0300 Subject: [PATCH] Simplify __clone() visibility check (magic methods still don't respect ZEND_ACC_CHANGED). --- Zend/zend_execute.c | 4 ++ Zend/zend_vm_def.h | 23 +++-------- Zend/zend_vm_execute.h | 92 +++++++++++------------------------------- 3 files changed, 34 insertions(+), 85 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index fa2f17571d..6859654bbe 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2287,6 +2287,10 @@ static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DAT } } +static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_clone_call(zend_function *clone, zend_class_entry *scope) +{ + zend_throw_error(NULL, "Call to %s %s::__clone() from context '%s'", zend_visibility_string(clone->common.fn_flags), ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); +} #if ZEND_INTENSIVE_DEBUGGING diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e51589a40a..0b7ebf8f89 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5029,23 +5029,12 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) HANDLE_EXCEPTION(); } - if (clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (!zend_check_private(clone, scope, clone->common.function_name)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); - FREE_OP1(); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + if (clone->common.scope != scope) { + if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_wrong_clone_call(clone, scope); FREE_OP1(); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d3a937de97..ecde1bcddc 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3048,23 +3048,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ HANDLE_EXCEPTION(); } - if (clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (!zend_check_private(clone, scope, clone->common.function_name)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); - - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + if (clone->common.scope != scope) { + if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_wrong_clone_call(clone, scope); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -12588,23 +12577,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND HANDLE_EXCEPTION(); } - if (clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (!zend_check_private(clone, scope, clone->common.function_name)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); - zval_ptr_dtor_nogc(free_op1); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + if (clone->common.scope != scope) { + if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_wrong_clone_call(clone, scope); zval_ptr_dtor_nogc(free_op1); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -30665,23 +30643,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND HANDLE_EXCEPTION(); } - if (clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (!zend_check_private(clone, scope, clone->common.function_name)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); - - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + if (clone->common.scope != scope) { + if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_wrong_clone_call(clone, scope); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -37428,23 +37395,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC HANDLE_EXCEPTION(); } - if (clone) { - if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (!zend_check_private(clone, scope, clone->common.function_name)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); - - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } - } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - scope = EX(func)->op_array.scope; - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + if (clone->common.scope != scope) { + if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_wrong_clone_call(clone, scope); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); -- 2.40.0