diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-02-18 14:16:48 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-02-18 14:17:47 +0100 |
commit | db2e2af13ab6b40d8a3042520e25f2775bcc00a8 (patch) | |
tree | 01d3e6894ca4e11e7ea8efb5425fd4befabbcfaf | |
parent | 6e988eaefb41e781f2e0c84e478e56e57d181908 (diff) | |
download | php-git-db2e2af13ab6b40d8a3042520e25f2775bcc00a8.tar.gz |
Fixed bug #53826
We should handle the case where the method doesn't exist, and
where it is not visible the same way.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug53826.phpt | 33 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 41 |
3 files changed, 58 insertions, 18 deletions
@@ -7,6 +7,8 @@ PHP NEWS . Added missing hashtable insertion APIs for arr/obj/ref. (Sara) . Fixed bug #75474 (function scope static variables are not bound to a unique function). (Nikita) + . Fixed bug #53826 (__callStatic fired in base class through a parent call if + the method is private). (Nikita) - FTP: . Convert resource<ftp> to object \FTPConnection. (Sara) diff --git a/Zend/tests/bug53826.phpt b/Zend/tests/bug53826.phpt new file mode 100644 index 0000000000..3f0a069536 --- /dev/null +++ b/Zend/tests/bug53826.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #53826: __callStatic fired in base class through a parent call if the method is private +--FILE-- +<?php + +class A1 { + public function __call($method, $args) { echo "__call\n"; } + public static function __callStatic($method, $args) { echo "__callStatic\n"; } +} + +class A2 { // A1 with private function test + public function __call($method, $args) { echo "__call\n"; } + public static function __callStatic($method, $args) { echo "__callStatic\n"; } + private function test() {} +} + +class B1 extends A1 { + public function test(){ parent::test(); } +} + +class B2 extends A2 { + public function test(){ parent::test(); } +} + +$test1 = new B1; +$test2 = new B2; +$test1->test(); +$test2->test(); + +?> +--EXPECT-- +__call +__call diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index e99af731f9..b903afb8ba 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1263,11 +1263,29 @@ static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_ } /* }}} */ +static zend_always_inline zend_function *get_static_method_fallback( + zend_class_entry *ce, zend_string *function_name) +{ + zend_object *object; + if (ce->__call && + (object = zend_get_this_object(EG(current_execute_data))) != NULL && + instanceof_function(object->ce, ce)) { + /* Call the top-level defined __call(). + * see: tests/classes/__call_004.phpt */ + + ZEND_ASSERT(object->ce->__call); + return zend_get_user_call_function(object->ce, function_name); + } else if (ce->__callstatic) { + return zend_get_user_callstatic_function(ce, function_name); + } else { + return NULL; + } +} + ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ { zend_function *fbc = NULL; zend_string *lc_function_name; - zend_object *object; zend_class_entry *scope; if (EXPECTED(key != NULL)) { @@ -1293,19 +1311,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (UNEXPECTED(!key)) { zend_string_release_ex(lc_function_name, 0); } - if (ce->__call && - (object = zend_get_this_object(EG(current_execute_data))) != NULL && - instanceof_function(object->ce, ce)) { - /* Call the top-level defined __call(). - * see: tests/classes/__call_004.phpt */ - - ZEND_ASSERT(object->ce->__call); - return zend_get_user_call_function(object->ce, function_name); - } else if (ce->__callstatic) { - return zend_get_user_callstatic_function(ce, function_name); - } else { - return NULL; - } + return get_static_method_fallback(ce, function_name); } } while (0); @@ -1321,12 +1327,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st 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))) { - if (ce->__callstatic) { - fbc = zend_get_user_callstatic_function(ce, function_name); - } else { + zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); + if (!fallback_fbc) { zend_bad_method_call(fbc, function_name, scope); - fbc = NULL; } + fbc = fallback_fbc; } } } |