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

Reply via email to