php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37964 Reflection shows private methods of parent class
Submitted: 2006-06-29 20:06 UTC Modified: 2008-01-16 14:21 UTC
From: lavin dot peter at gmail dot com Assigned: helly (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.2.* OS: Windows XP
Private report: No CVE-ID: None
 [2006-06-29 20:06 UTC] lavin dot peter at gmail dot com
Description:
------------
When using the export method of ReflectionClass the private methods of of a parent class are displayed.

Reproduce code:
---------------
class Base{
  private $basevar;
  private function baseFunction(){}
}
class Derived extends Base{}
$d = new Derived;
Reflection::export(new ReflectionClass($d));



Expected result:
----------------
Since properties and methods defined as private are not inherited, the exported Base class should have no properties or methods but in fact the private method of the Parent class shows up.

Actual result:
--------------
Class [ class Derived extends Base ] { @@ C:\Program Files\Apache Group\Apache2\htdocs\newstuff\captcha\refbug.php 6-6 - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [0] { } - Methods [1] { Method [ private method baseFunction ] { @@ C:\Program Files\Apache Group\Apache2\htdocs\newstuff\captcha\refbug.php 4 - 4 } } } 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-07-04 14:13 UTC] lavin dot peter at gmail dot com
The "getMethods" method of ReflectionClass also returns the private methods of the parent class.
 [2006-08-20 09:31 UTC] ruslan dot kyrychuk at gmail dot com
I'd say it is not correct. Properties and methods defined as private are inherited but you have no access to this properties in child class.
If for example during serializing if you ommit private properties of base class - you'll get wrong object.

class Base{
  private $basevar;
  public function baseFunction(){return $this->basevar;}
}
class Derived extends Base{}

if private properties are not inherited - than calling baseFunction will cause null result and this is not correct in class inheritance.
 [2006-08-20 11:07 UTC] helly@php.net
That is why we have a new serializing interface which allows you to call a serializing function in the base class which then can deal with the private properties in that base class.
 [2006-08-20 12:39 UTC] ruslan dot kyrychuk at gmail dot com
With this serializing interface (if you mean __sleep and __wakeup method) and with reflection can not work with private variables, I can not write serialization method that can be used in all child classes .In every child class Reflection will have child instance and will not have access for private variables of parent. 

Reproduce code:
---------------
class A
{
	public function __sleep() 
	{
		$refl = new ReflectionObject($this);
		$props = $refl->getProperties();
		$result = array();
		foreach($props as $prop)
			$result[] = $prop->getName();
		return $result ;
	}
	private $privateVar = 'Test Private';
	public $publicVar = 'Test Public';
	
	public function setPublic($value)
	{
		$this->publicVar = $value;
	}
	public function setPrivate($value)
	{
		$this->privateVar = $value;
	}
}

class B extends A{}

$instance = new B();
$instance->setPrivate('Set Test Private');
$instance->setPublic('Set Test Private');

var_dump($instance);
var_dump(unserialize(serialize($instance)));

Expected result:
----------------
Object before serializing and after is same.

Actual result:
--------------
object(B)#1 (2) {
  ["privateVar:private"]=>
  string(16) "Set Test Private"
  ["publicVar"]=>
  string(16) "Set Test Private"
}
object(B)#3 (2) {
  ["privateVar:private"]=>
  string(12) "Test Private"
  ["publicVar"]=>
  string(16) "Set Test Private"
}


--------------
When writing 
public function __sleep(){return array('privateVar', 'publicVar');} In B class
Than you'll get 

Notice: serialize() [function.serialize]: "privateVar" returned as member variable from __sleep() but does not exist.

So you can't write custom serializing for child object when private properties exists in parent class.
 [2006-08-20 13:36 UTC] ruslan dot kyrychuk at gmail dot com
Maybe it is not valid to have private variables of parent class in Reflection. Then it is only my own custom serialization problem.
 [2008-01-16 02:18 UTC] felipe@php.net
Simple fix:

Index: php_reflection.c
===================================================================
RCS file: /repository/php-src/ext/reflection/php_reflection.c,v
retrieving revision 1.164.2.33.2.45.2.6
diff -u -r1.164.2.33.2.45.2.6 php_reflection.c
--- php_reflection.c    31 Dec 2007 07:17:13 -0000      1.164.2.33.2.45.2.6
+++ php_reflection.c    16 Jan 2008 02:14:41 -0000
@@ -519,7 +519,8 @@
                        zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
-                               if (!(mptr->common.fn_flags & ZEND_ACC_STATIC)) {
+                               if (!((mptr->common.fn_flags & ZEND_ACC_STATIC) || 
+                                       ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && mptr->common.scope != ce))) {
                                        char *key;
                                        uint key_len;
                                        ulong num_index;

 [2008-01-16 10:34 UTC] tony2001@php.net
Assigned to the Reflection maintainer.
 [2008-01-16 14:21 UTC] helly@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 09:01:26 2024 UTC