- Fixed bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables)
- Added some tests
This commit is contained in:
Felipe Pena 2008-08-22 00:59:39 +00:00
parent a7d2377ce4
commit 317b48f3af
9 changed files with 384 additions and 11 deletions

43
Zend/tests/bug45862.phpt Normal file
View File

@ -0,0 +1,43 @@
--TEST--
Bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables)
--FILE--
<?php
class Ancestor {
function test() {
var_dump(get_class_vars("Tester"));
var_dump(Tester::$prot);
}
}
class Tester extends Ancestor {
static protected $prot = "protected var";
static private $priv = "private var";
}
class Child extends Tester {
function test() { var_dump(get_class_vars("Tester")); }
}
echo "\n From parent scope\n";
$parent = new Ancestor();
$parent->test();
echo "\n From child scope\n";
$child = new Child();
$child->test();
?>
--EXPECT--
From parent scope
array(1) {
["prot"]=>
string(13) "protected var"
}
string(13) "protected var"
From child scope
array(1) {
["prot"]=>
string(13) "protected var"
}

View File

@ -0,0 +1,33 @@
--TEST--
get_class_vars(): Simple test
--FILE--
<?php
class A {
public $a = 1;
private $b = 2;
private $c = 3;
}
class B extends A {
static public $aa = 4;
static private $bb = 5;
static protected $cc = 6;
}
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
?>
--EXPECT--
array(1) {
["a"]=>
int(1)
}
array(2) {
["a"]=>
int(1)
["aa"]=>
int(4)
}

View File

@ -0,0 +1,49 @@
--TEST--
get_class_vars(): Testing the scope
--FILE--
<?php
class A {
public $a = 1;
private $b = 2;
private $c = 3;
}
class B extends A {
static public $aa = 4;
static private $bb = 5;
static protected $cc = 6;
}
class C extends B {
public function __construct() {
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
var_dump($this->a, $this->b, $this->c);
}
}
new C;
?>
--EXPECTF--
array(1) {
["a"]=>
int(1)
}
array(3) {
["a"]=>
int(1)
["aa"]=>
int(4)
["cc"]=>
int(6)
}
Notice: Undefined property: C::$b in %s on line %d
Notice: Undefined property: C::$c in %s on line %d
int(1)
NULL
NULL

View File

@ -0,0 +1,47 @@
--TEST--
get_class_vars(): Testing the scope
--FILE--
<?php
class A {
public $a = 1;
private $b = 2;
private $c = 3;
}
class B extends A {
static public $aa = 4;
static private $bb = 5;
static protected $cc = 6;
protected function __construct() {
var_dump(get_class_vars('C'));
}
}
class C extends B {
public $aaa = 7;
private $bbb = 8;
protected $ccc = 9;
public function __construct() {
parent::__construct();
}
}
new C;
?>
--EXPECT--
array(5) {
["aaa"]=>
int(7)
["ccc"]=>
int(9)
["a"]=>
int(1)
["aa"]=>
int(4)
["cc"]=>
int(6)
}

View File

@ -0,0 +1,67 @@
--TEST--
get_class_vars(): Testing the scope
--FILE--
<?php
class A {
public $a = 1;
static public $A = 2;
private $b = 3;
static private $B = 4;
protected $c = 5;
static protected $C = 6;
public function __construct() {
var_dump(get_class_vars('A'));
}
static public function test() {
var_dump(get_class_vars('A'));
}
}
var_dump(get_class_vars('A'));
new A;
var_dump(A::test());
?>
--EXPECT--
array(2) {
["a"]=>
int(1)
["A"]=>
int(2)
}
array(6) {
["a"]=>
int(1)
["b"]=>
int(3)
["c"]=>
int(5)
["A"]=>
int(2)
["B"]=>
int(4)
["C"]=>
int(6)
}
array(6) {
["a"]=>
int(1)
["b"]=>
int(3)
["c"]=>
int(5)
["A"]=>
int(2)
["B"]=>
int(4)
["C"]=>
int(6)
}
NULL

View File

@ -0,0 +1,39 @@
--TEST--
get_class_vars(): Testing visibility
--FILE--
<?php
class A {
protected $a = 1;
private $b = 2;
}
class B extends A {
private $c = 3;
public function __construct() {
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
}
}
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
new B;
?>
--EXPECT--
array(0) {
}
array(0) {
}
array(1) {
["a"]=>
int(1)
}
array(2) {
["c"]=>
int(3)
["a"]=>
int(1)
}

View File

@ -0,0 +1,48 @@
--TEST--
get_class_vars(): Testing visibility
--FILE--
<?php
class A {
protected $a = 1;
}
class B extends A { }
class C extends B { }
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
var_dump(get_class_vars('C'));
print "---\n";
class D extends B {
public function __construct() {
var_dump(get_class_vars('A'));
var_dump(get_class_vars('B'));
var_dump(get_class_vars('C'));
}
}
new D;
?>
--EXPECT--
array(0) {
}
array(0) {
}
array(0) {
}
---
array(1) {
["a"]=>
int(1)
}
array(1) {
["a"]=>
int(1)
}
array(0) {
}

View File

@ -0,0 +1,41 @@
--TEST--
get_class_vars(): Testing with static properties
--FILE--
<?php
class A {
static public $a, $aa;
static private $b, $bb;
static protected $c, $cc;
static public function test() {
var_dump(get_class_vars(__CLASS__));
}
}
var_dump(get_class_vars('A'));
var_dump(A::test());
?>
--EXPECT--
array(2) {
["a"]=>
NULL
["aa"]=>
NULL
}
array(6) {
["a"]=>
NULL
["aa"]=>
NULL
["b"]=>
NULL
["bb"]=>
NULL
["c"]=>
NULL
["cc"]=>
NULL
}
NULL

View File

@ -977,8 +977,6 @@ ZEND_FUNCTION(is_a)
/* {{{ add_class_vars */
static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC)
{
int instanceof = EG(scope) && instanceof_function(EG(scope), ce TSRMLS_CC);
if (zend_hash_num_elements(properties) > 0) {
HashPosition pos;
zval **prop;
@ -987,20 +985,28 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
char *key, *class_name, *prop_name;
uint key_len;
ulong num_index;
ulong num_index, h;
int prop_name_len = 0;
zval *prop_copy;
zend_property_info *property_info;
zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(properties, &pos);
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
if (class_name) {
if (class_name[0] != '*' && strcmp(class_name, ce->name)) {
/* filter privates from base classes */
continue;
} else if (!instanceof) {
/* filter protected if not inside class */
continue;
}
prop_name_len = strlen(prop_name);
h = zend_get_hash_value(prop_name, prop_name_len+1);
if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_len+1, h, (void **) &property_info) == FAILURE) {
continue;
}
if (property_info->flags & ZEND_ACC_SHADOW) {
continue;
} else if ((property_info->flags & ZEND_ACC_PRIVATE) && EG(scope) != ce) {
continue;
} else if ((property_info->flags & ZEND_ACC_PROTECTED) && zend_check_protected(ce, EG(scope)) == 0) {
continue;
}
/* copy: enforce read only access */