Hi all,
in my point view, the zend_check_protected should be used like:
http://ecl.mediain.com.br/diff/protected.diff
This patch breaks a test (Zend/tests/bug37632.phpt):
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);
[...]
However, this also looks wrong to me.
Em Ter, 2008-02-05 às 11:43 +0000, Robin Fernandes escreveu:
> Hi all,
>
> The fix to bug 37212 (http://bugs.php.net/bug.php?id=37632) introduced
> an unusual method accessibility rule. A class can access a protected
> method declared outside of its own direct class hierarchy if that
> method has a prototype in a common superclass.
>
> <?php
> class A {
> static protected function f() {return 'A::f()';}
> }
> class B1 extends A {
> static protected function f() {return 'B1::f()';}
> }
> class B2 extends A {
> static public function test() {echo B1::f();}
> }
> B2::test(); // prints B1::f()
> ?>
>
> This is achieved using by zend_get_function_root_class() when invoking
> zend_check_protected(), e.g.:
> zend_check_protected(zend_get_function_root_class(fbc), EG(scope))
>
> Looking at other uses of zend_check_protected() reveals at least 5
> cases where this rule is not enforced. They are illustrated below. So
> is the rule itself incorrect? or should the inconsistent cases be
> fixed?
>
>
> The examples below were tested on 5.2.5 and the latest 5.3 and 6.0 snaps.
>
> 1. The visibility rule does not apply to properties (static or not):
> <?php
> class A {
> protected $p = 'A::$p';
> static protected $sp = 'A::$sp';
> }
> class B1 extends A {
> protected $p = 'B1::$p';
> static protected $sp = 'B1::$sp';
> }
> class B2 extends A {
> static public function test() {
> $b1 = new B1;
> echo $b1->p; //Fatal error: Cannot access protected property
> B1::$p
> echo B1::$sp; //Fatal error: Cannot access protected property
> B1::$sp
> }
> }
> B2::test();
> ?>
>
>
> 2. It doesn't apply to callbacks either:
> <?php
> class A {
> static protected function f() {return 'A::f()';}
> }
> class B1 extends A {
> static protected function f() {return 'B1::f()';}
> }
> class B2 extends A {
> static public function test() {
> echo call_user_func('B1::f');
> }
> }
> B2::test(); // Warning: call_user_func() expects parameter 1 to be a
> valid callback, cannot access protected method B1::f()
> ?>
>
>
> 3. is_callable() doesn't know about this visibility rule:
> <?php
> class A {
> static protected function f() {return 'A::f()';}
> }
> class B1 extends A {
> static protected function f() {return 'B1::f()';}
> }
> class B2 extends A {
> static public function test() {
> var_dump(is_callable('B1::f')); // returns false
> B1::f(); // works
> }
> }
> B2::test();
> ?>
>
>
> 4. The rule does not apply to the clone magic method:
> <?php
> class A {
> protected function f() {return 'A::f()';}
> protected function __clone() {}
> }
> class B1 extends A {
> protected function f() {return 'B1::f()';}
> protected function __clone() {}
> }
> class B2 extends A {
> static public function test($obj) {
> echo $obj->f(); // works
> clone $obj; // Fatal error: Call to protected B1::__clone()
> from context 'B2'
> }
> }
> B2::test(new B1);
> ?>
>
>
> 5. The rule does not apply to destructors:
> <?php
> class A {
> protected function __destruct() {}
> }
> class B1 extends A {
> protected function __destruct() {}
> }
> class B2 extends A {
> static public function test() {
> $obj = new B1;
> } // Fatal error: Call to protected B1::__destruct() from context 'B2'
> }
> B2::test();
> ?>
>
> Many thanks,
> Robin
>
--
Regards,
Felipe Pena.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php