mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
- MFH Bugfix #37632 (Protected method access problem)
This commit is contained in:
parent
9e1b944989
commit
1b172b1371
135
Zend/tests/bug37632.phpt
Executable file
135
Zend/tests/bug37632.phpt
Executable file
@ -0,0 +1,135 @@
|
||||
--TEST--
|
||||
Bug #37632 (Protected method access problem)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A1
|
||||
{
|
||||
protected function test()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
class B1 extends A1
|
||||
{
|
||||
public function doTest(A1 $obj)
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
$obj->test();
|
||||
}
|
||||
}
|
||||
|
||||
class C1 extends A1
|
||||
{
|
||||
protected function test()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$b = new B1;
|
||||
$b->doTest(new C1);
|
||||
|
||||
class A2
|
||||
{
|
||||
static protected function test()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
class B2 extends A2
|
||||
{
|
||||
static public function doTest(A2 $obj)
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
$obj->test();
|
||||
}
|
||||
}
|
||||
|
||||
class C2 extends A2
|
||||
{
|
||||
static protected function test()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
B2::doTest(new C2);
|
||||
|
||||
/* Right now Ctor's cannot be made protected when defined in a ctor. That is
|
||||
* we cannot decrease visibility.
|
||||
*
|
||||
|
||||
interface Ctor
|
||||
{
|
||||
function __construct($x);
|
||||
}
|
||||
|
||||
class A3 implements Ctor
|
||||
{
|
||||
protected function __construct()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
class B3 extends A3
|
||||
{
|
||||
static public function doTest()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
new C3;
|
||||
}
|
||||
}
|
||||
|
||||
class C3 extends A3
|
||||
{
|
||||
protected function __construct()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
B3::doTest();
|
||||
|
||||
*/
|
||||
|
||||
class A4
|
||||
{
|
||||
protected function __construct()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
class B4 extends A4
|
||||
{
|
||||
static public function doTest()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
new C4;
|
||||
}
|
||||
}
|
||||
|
||||
class C4 extends A4
|
||||
{
|
||||
protected function __construct()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
B4::doTest();
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
B1::doTest
|
||||
C1::test
|
||||
B2::doTest
|
||||
C2::test
|
||||
B4::doTest
|
||||
|
||||
Fatal error: Call to protected C4::__construct() from context 'B4' in %sbug37632.php on line %d
|
@ -2028,8 +2028,9 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
|
||||
if (parent_flags & ZEND_ACC_ABSTRACT) {
|
||||
child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
|
||||
child->common.prototype = parent;
|
||||
} else {
|
||||
child->common.prototype = parent->common.prototype;
|
||||
} else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && parent->common.prototype->common.scope->ce_flags && ZEND_ACC_INTERFACE)) {
|
||||
/* ctors only have a prototype if it comes from an interface */
|
||||
child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
|
||||
}
|
||||
|
||||
|
||||
|
@ -724,6 +724,12 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope)
|
||||
}
|
||||
|
||||
|
||||
static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc)
|
||||
{
|
||||
return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope;
|
||||
}
|
||||
|
||||
|
||||
static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC)
|
||||
{
|
||||
zend_object *zobj;
|
||||
@ -784,7 +790,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
|
||||
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
||||
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
||||
*/
|
||||
if (!zend_check_protected(fbc->common.scope, EG(scope))) {
|
||||
if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
|
||||
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
|
||||
}
|
||||
}
|
||||
@ -822,7 +828,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
|
||||
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
||||
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
||||
*/
|
||||
if (!zend_check_protected(EG(scope), fbc->common.scope)) {
|
||||
if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
|
||||
zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
|
||||
}
|
||||
}
|
||||
@ -898,7 +904,7 @@ static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
|
||||
} else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
||||
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
||||
*/
|
||||
if (!zend_check_protected(constructor->common.scope, EG(scope))) {
|
||||
if (!zend_check_protected(zend_get_function_root_class(constructor), EG(scope))) {
|
||||
zend_error(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : "");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user