diff --git a/Zend/zend_API.c b/Zend/zend_API.c index df8b4252c42a..4b513707df4f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4021,13 +4021,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ ((fcc->object && fcc->calling_scope->__call) || (!fcc->object && fcc->calling_scope->__callstatic)))) { scope = get_scope(frame); - if (fcc->function_handler->common.scope != scope) { - if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE) - || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) { - retval = 0; - fcc->function_handler = NULL; - goto get_function_via_handler; - } + ZEND_ASSERT(!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fcc->function_handler, scope)) { + retval = 0; + fcc->function_handler = NULL; + goto get_function_via_handler; } } } else { @@ -4086,17 +4084,15 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ if (retval && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = get_scope(frame); - if (fcc->function_handler->common.scope != scope) { - if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE) - || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) { - if (error) { - if (*error) { - efree(*error); - } - zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); + ZEND_ASSERT(!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fcc->function_handler, scope)) { + if (error) { + if (*error) { + efree(*error); } - retval = 0; + zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } + retval = 0; } } } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 728695bd9e93..0e403329264c 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1098,21 +1098,14 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } else { fptr = zend_hash_find_ptr_lc(&ce->function_table, method_name); if (fptr) { - if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (UNEXPECTED(fptr->common.scope != scope)) { - if ( - UNEXPECTED(fptr->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fptr), scope)) - ) { - if (ce->__callstatic) { - zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions"); - } else { - zend_bad_method_call(fptr, method_name, scope); - } - - return FAILURE; - } + if (!zend_check_method_accessible(fptr, scope)) { + if (ce->__callstatic) { + zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions"); + } else { + zend_bad_method_call(fptr, method_name, scope); } + + return FAILURE; } } else { if (ce->__callstatic) { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 48e0e86d3b2f..256f08e05d6a 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -89,14 +89,9 @@ ZEND_FUNCTION(clone) RETURN_THROWS(); } - if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { - 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_bad_method_call(clone, clone->common.function_name, scope); - RETURN_THROWS(); - } - } + if (clone && !zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + RETURN_THROWS(); } zend_object *cloned; @@ -953,13 +948,7 @@ ZEND_FUNCTION(get_class_methods) scope = zend_get_executed_scope(); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { - if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) - || (scope && - (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && - zend_check_protected(mptr->common.scope, scope)) - || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && - scope == mptr->common.scope))) - ) { + if (zend_check_method_accessible(mptr, scope)) { ZVAL_STR_COPY(&method_name, mptr->common.function_name); zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name); } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 3d782b03fe17..8166ba55c5ef 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1949,17 +1949,15 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st zval *func = zend_hash_find(&ce->function_table, lc_function_name); if (EXPECTED(func)) { fbc = Z_FUNC_P(func); - if (!(fbc->op_array.fn_flags & ZEND_ACC_PUBLIC)) { + if (!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { zend_class_entry *scope = zend_get_executed_scope(); - if (UNEXPECTED(fbc->common.scope != scope)) { - if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) { - zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); - if (!fallback_fbc) { - zend_bad_method_call(fbc, function_name, scope); - } - fbc = fallback_fbc; + ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fbc, scope)) { + zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); + if (!fallback_fbc) { + zend_bad_method_call(fbc, function_name, scope); } + fbc = fallback_fbc; } } } else { @@ -2115,15 +2113,13 @@ ZEND_API zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */ zend_function *constructor = zobj->ce->constructor; if (constructor) { - if (UNEXPECTED(!(constructor->op_array.fn_flags & ZEND_ACC_PUBLIC))) { + if (UNEXPECTED(!(constructor->common.fn_flags & ZEND_ACC_PUBLIC))) { zend_class_entry *scope = get_fake_or_executed_scope(); - if (UNEXPECTED(constructor->common.scope != scope)) { - if (UNEXPECTED(constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), scope))) { - zend_bad_constructor_call(constructor, scope); - zend_object_store_ctor_failed(zobj); - constructor = NULL; - } + ZEND_ASSERT(!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(constructor, scope)) { + zend_bad_constructor_call(constructor, scope); + zend_object_store_ctor_failed(zobj); + constructor = NULL; } } } diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index fd0e97c5f413..45bbc60cdb33 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -123,49 +123,25 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) zend_object *old_exception; const zend_op *old_opline_before_exception; - if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (EG(current_execute_data)) { - zend_class_entry *scope = zend_get_executed_scope(); - - if (object->ce != scope) { - zend_throw_error(NULL, - "Call to private %s::__destruct() from %s%s", - ZSTR_VAL(object->ce->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); - return; - } - } else { - zend_error(E_WARNING, - "Call to private %s::__destruct() from global scope during shutdown ignored", - ZSTR_VAL(object->ce->name)); + if (destructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { + if (EG(current_execute_data)) { + zend_class_entry *scope = zend_get_executed_scope(); + /* Ensure that if we're calling a protected or private function, we're allowed to do so. */ + ZEND_ASSERT(!(destructor->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(destructor, scope)) { + zend_throw_error(NULL, + "Call to %s %s::__destruct() from %s%s", + zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name), + scope ? "scope " : "global scope", + scope ? ZSTR_VAL(scope->name) : "" + ); return; } } else { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (EG(current_execute_data)) { - zend_class_entry *scope = zend_get_executed_scope(); - - if (!zend_check_protected(zend_get_function_root_class(destructor), scope)) { - zend_throw_error(NULL, - "Call to protected %s::__destruct() from %s%s", - ZSTR_VAL(object->ce->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); - return; - } - } else { - zend_error(E_WARNING, - "Call to protected %s::__destruct() from global scope during shutdown ignored", - ZSTR_VAL(object->ce->name)); - return; - } + zend_error(E_WARNING, + "Call to %s %s::__destruct() from global scope during shutdown ignored", + zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name)); + return; } } diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 242bf212ba9c..86c3a49f8c8c 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -137,5 +137,16 @@ static inline zend_property_info *zend_get_typed_property_info_for_slot(zend_obj return NULL; } +static zend_always_inline bool zend_check_method_accessible(const zend_function *fn, const zend_class_entry *scope) +{ + if (!(fn->common.fn_flags & ZEND_ACC_PUBLIC) + && fn->common.scope != scope + && (UNEXPECTED(fn->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fn), scope)))) { + return false; + } + + return true; +} #endif /* ZEND_OBJECTS_H */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9f7042386a15..c0e05aef470a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6043,14 +6043,12 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) 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_bad_method_call(clone, clone->common.function_name, scope); - FREE_OP1(); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, 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 cb2af9e49dd6..e79d843e6abf 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5217,14 +5217,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ 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_bad_method_call(clone, clone->common.function_name, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -15466,14 +15464,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND 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_bad_method_call(clone, clone->common.function_name, scope); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -33563,14 +33559,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND 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_bad_method_call(clone, clone->common.function_name, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -41084,14 +41078,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC 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_bad_method_call(clone, clone->common.function_name, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } }