Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:35184 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 34778 invoked by uid 1010); 5 Feb 2008 13:23:47 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 34763 invoked from network); 5 Feb 2008 13:23:47 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 5 Feb 2008 13:23:47 -0000 Authentication-Results: pb1.pair.com smtp.mail=felipensp@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=felipensp@gmail.com; sender-id=pass; domainkeys=bad Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.132.246 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: felipensp@gmail.com X-Host-Fingerprint: 209.85.132.246 an-out-0708.google.com Received: from [209.85.132.246] ([209.85.132.246:16896] helo=an-out-0708.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 75/AC-14268-26368A74 for ; Tue, 05 Feb 2008 08:23:46 -0500 Received: by an-out-0708.google.com with SMTP id c18so524838anc.1 for ; Tue, 05 Feb 2008 05:23:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:subject:from:to:cc:in-reply-to:references:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; bh=xShY99vwyrCobw7j9cUO5Xk4APJ2EVKau4wXCh9NsYc=; b=HiYbcN/fdRqBnIVTrtPawnzCha3qZMx+xm4v2Q7t+S1FavbyU5gQdNso3Q5oPuPggtjP03qxaEEHgGrQTOHsYyy1i024dU5YnjXWNr8UJZELKnBzd53VLAU6hW5t6t8+VYyHHYYwpQ4WSszc7kGzzXVR+3KAk/2OrfnnEXwFHaw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:cc:in-reply-to:references:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; b=dVuBqWiypgeI6xhJNvhaEpdZKLZipOlY4g3XyAy0U9m5aMxeK+tmuSHbwOVIXCT8ucPyiLRXARJJ2CvQgUq25n8zuVB8V7GemdgzF1x1YIkNPPEY8A681XnjpZKKahP8MN09k6iO/9slvMrfOed0v432h8vbIl8Yhm+RsZW/Kv0= Received: by 10.100.44.4 with SMTP id r4mr763006anr.0.1202217823439; Tue, 05 Feb 2008 05:23:43 -0800 (PST) Received: from ?189.24.55.9? ( [189.24.55.9]) by mx.google.com with ESMTPS id t26sm18106098ele.4.2008.02.05.05.23.39 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 05 Feb 2008 05:23:40 -0800 (PST) To: Robin Fernandes Cc: internals@lists.php.net In-Reply-To: <5a8807d10802050343r43742844we89366ec47b57f4b@mail.gmail.com> References: <5a8807d10802050343r43742844we89366ec47b57f4b@mail.gmail.com> Content-Type: text/plain; charset=utf-8 Date: Tue, 05 Feb 2008 11:22:51 -0200 Message-ID: <1202217771.6178.8.camel@pena> Mime-Version: 1.0 X-Mailer: Evolution 2.10.1 Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] Inconsistencies when accessing protected members From: felipensp@gmail.com (Felipe Pena) 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. > > 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): > 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: > 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: > 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: > 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: > 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.