mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fixed bug #53826
We should handle the case where the method doesn't exist, and where it is not visible the same way.
This commit is contained in:
parent
6e988eaefb
commit
db2e2af13a
3 changed files with 58 additions and 18 deletions
2
NEWS
2
NEWS
|
@ -7,6 +7,8 @@ PHP NEWS
|
||||||
. Added missing hashtable insertion APIs for arr/obj/ref. (Sara)
|
. Added missing hashtable insertion APIs for arr/obj/ref. (Sara)
|
||||||
. Fixed bug #75474 (function scope static variables are not bound to a unique
|
. Fixed bug #75474 (function scope static variables are not bound to a unique
|
||||||
function). (Nikita)
|
function). (Nikita)
|
||||||
|
. Fixed bug #53826 (__callStatic fired in base class through a parent call if
|
||||||
|
the method is private). (Nikita)
|
||||||
|
|
||||||
- FTP:
|
- FTP:
|
||||||
. Convert resource<ftp> to object \FTPConnection. (Sara)
|
. Convert resource<ftp> to object \FTPConnection. (Sara)
|
||||||
|
|
33
Zend/tests/bug53826.phpt
Normal file
33
Zend/tests/bug53826.phpt
Normal file
|
@ -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
|
|
@ -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_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_function *fbc = NULL;
|
zend_function *fbc = NULL;
|
||||||
zend_string *lc_function_name;
|
zend_string *lc_function_name;
|
||||||
zend_object *object;
|
|
||||||
zend_class_entry *scope;
|
zend_class_entry *scope;
|
||||||
|
|
||||||
if (EXPECTED(key != NULL)) {
|
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)) {
|
if (UNEXPECTED(!key)) {
|
||||||
zend_string_release_ex(lc_function_name, 0);
|
zend_string_release_ex(lc_function_name, 0);
|
||||||
}
|
}
|
||||||
if (ce->__call &&
|
return get_static_method_fallback(ce, function_name);
|
||||||
(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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (0);
|
} 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->common.scope != scope)) {
|
||||||
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
|
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
|
||||||
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
|
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
|
||||||
if (ce->__callstatic) {
|
zend_function *fallback_fbc = get_static_method_fallback(ce, function_name);
|
||||||
fbc = zend_get_user_callstatic_function(ce, function_name);
|
if (!fallback_fbc) {
|
||||||
} else {
|
|
||||||
zend_bad_method_call(fbc, function_name, scope);
|
zend_bad_method_call(fbc, function_name, scope);
|
||||||
fbc = NULL;
|
|
||||||
}
|
}
|
||||||
|
fbc = fallback_fbc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue