summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Pena <felipe@php.net>2008-08-22 00:54:00 +0000
committerFelipe Pena <felipe@php.net>2008-08-22 00:54:00 +0000
commit65cc4f2e86ba3bf38cf67b807daef1ad6e3989d5 (patch)
tree3bbb1c30f8e54b490c46ae3e6e6a3e28365a83f2
parentadfa214688b0baa9141422770dd2eb91b491335d (diff)
downloadphp-git-65cc4f2e86ba3bf38cf67b807daef1ad6e3989d5.tar.gz
- Fixed bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables)
- Added some tests
-rw-r--r--Zend/tests/bug45862.phpt43
-rw-r--r--Zend/tests/get_class_vars_001.phpt33
-rw-r--r--Zend/tests/get_class_vars_002.phpt49
-rw-r--r--Zend/tests/get_class_vars_003.phpt47
-rw-r--r--Zend/tests/get_class_vars_004.phpt67
-rw-r--r--Zend/tests/get_class_vars_005.phpt39
-rw-r--r--Zend/tests/get_class_vars_006.phpt48
-rw-r--r--Zend/tests/get_class_vars_007.phpt41
-rw-r--r--Zend/zend_builtin_functions.c28
9 files changed, 384 insertions, 11 deletions
diff --git a/Zend/tests/bug45862.phpt b/Zend/tests/bug45862.phpt
new file mode 100644
index 0000000000..4f4dfe46d6
--- /dev/null
+++ b/Zend/tests/bug45862.phpt
@@ -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) {
+ [u"prot"]=>
+ unicode(13) "protected var"
+}
+unicode(13) "protected var"
+
+ From child scope
+array(1) {
+ [u"prot"]=>
+ unicode(13) "protected var"
+}
diff --git a/Zend/tests/get_class_vars_001.phpt b/Zend/tests/get_class_vars_001.phpt
new file mode 100644
index 0000000000..3066f8eba5
--- /dev/null
+++ b/Zend/tests/get_class_vars_001.phpt
@@ -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) {
+ [u"a"]=>
+ int(1)
+}
+array(2) {
+ [u"a"]=>
+ int(1)
+ [u"aa"]=>
+ int(4)
+}
diff --git a/Zend/tests/get_class_vars_002.phpt b/Zend/tests/get_class_vars_002.phpt
new file mode 100644
index 0000000000..7fe1b7606f
--- /dev/null
+++ b/Zend/tests/get_class_vars_002.phpt
@@ -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) {
+ [u"a"]=>
+ int(1)
+}
+array(3) {
+ [u"a"]=>
+ int(1)
+ [u"aa"]=>
+ int(4)
+ [u"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
diff --git a/Zend/tests/get_class_vars_003.phpt b/Zend/tests/get_class_vars_003.phpt
new file mode 100644
index 0000000000..9ffe9bf530
--- /dev/null
+++ b/Zend/tests/get_class_vars_003.phpt
@@ -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) {
+ [u"aaa"]=>
+ int(7)
+ [u"ccc"]=>
+ int(9)
+ [u"a"]=>
+ int(1)
+ [u"aa"]=>
+ int(4)
+ [u"cc"]=>
+ int(6)
+}
diff --git a/Zend/tests/get_class_vars_004.phpt b/Zend/tests/get_class_vars_004.phpt
new file mode 100644
index 0000000000..258984c132
--- /dev/null
+++ b/Zend/tests/get_class_vars_004.phpt
@@ -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) {
+ [u"a"]=>
+ int(1)
+ [u"A"]=>
+ int(2)
+}
+array(6) {
+ [u"a"]=>
+ int(1)
+ [u"b"]=>
+ int(3)
+ [u"c"]=>
+ int(5)
+ [u"A"]=>
+ int(2)
+ [u"B"]=>
+ int(4)
+ [u"C"]=>
+ int(6)
+}
+array(6) {
+ [u"a"]=>
+ int(1)
+ [u"b"]=>
+ int(3)
+ [u"c"]=>
+ int(5)
+ [u"A"]=>
+ int(2)
+ [u"B"]=>
+ int(4)
+ [u"C"]=>
+ int(6)
+}
+NULL
diff --git a/Zend/tests/get_class_vars_005.phpt b/Zend/tests/get_class_vars_005.phpt
new file mode 100644
index 0000000000..b3acf943c7
--- /dev/null
+++ b/Zend/tests/get_class_vars_005.phpt
@@ -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) {
+ [u"a"]=>
+ int(1)
+}
+array(2) {
+ [u"c"]=>
+ int(3)
+ [u"a"]=>
+ int(1)
+}
diff --git a/Zend/tests/get_class_vars_006.phpt b/Zend/tests/get_class_vars_006.phpt
new file mode 100644
index 0000000000..8948399c27
--- /dev/null
+++ b/Zend/tests/get_class_vars_006.phpt
@@ -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) {
+ [u"a"]=>
+ int(1)
+}
+array(1) {
+ [u"a"]=>
+ int(1)
+}
+array(0) {
+}
diff --git a/Zend/tests/get_class_vars_007.phpt b/Zend/tests/get_class_vars_007.phpt
new file mode 100644
index 0000000000..97d9230489
--- /dev/null
+++ b/Zend/tests/get_class_vars_007.phpt
@@ -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) {
+ [u"a"]=>
+ NULL
+ [u"aa"]=>
+ NULL
+}
+array(6) {
+ [u"a"]=>
+ NULL
+ [u"aa"]=>
+ NULL
+ [u"b"]=>
+ NULL
+ [u"bb"]=>
+ NULL
+ [u"c"]=>
+ NULL
+ [u"cc"]=>
+ NULL
+}
+NULL
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index b2daf3c489..3857afdddc 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -972,8 +972,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;
@@ -982,21 +980,29 @@ 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) {
zstr key, class_name, prop_name;
uint key_len;
- ulong num_index;
+ ulong num_index, h;
+ int prop_name_len = 0;
zval *prop_copy;
zend_uchar key_type;
+ zend_property_info *property_info;
key_type = zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(properties, &pos);
+
zend_u_unmangle_property_name(key_type, key, key_len-1, &class_name, &prop_name);
- if (class_name.v) {
- if (class_name.s[0] != '*' && strcmp(class_name.s, ce->name.s)) {
- /* filter privates from base classes */
- continue;
- } else if (!instanceof) {
- /* filter protected if not inside class */
- continue;
- }
+ prop_name_len = ZSTR_LEN(key_type, prop_name);
+
+ h = zend_u_get_hash_value(key_type, prop_name, prop_name_len+1);
+ if (zend_u_hash_quick_find(&ce->properties_info, key_type, 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 */