]> granicus.if.org Git - php/commitdiff
MFH:
authorFelipe Pena <felipe@php.net>
Fri, 22 Aug 2008 00:59:39 +0000 (00:59 +0000)
committerFelipe Pena <felipe@php.net>
Fri, 22 Aug 2008 00:59:39 +0000 (00:59 +0000)
- Fixed bug #45862 (get_class_vars is inconsistent with 'protected' and 'private' variables)
- Added some tests

Zend/tests/bug45862.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_001.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_002.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_003.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_004.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_005.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_006.phpt [new file with mode: 0644]
Zend/tests/get_class_vars_007.phpt [new file with mode: 0644]
Zend/zend_builtin_functions.c

diff --git a/Zend/tests/bug45862.phpt b/Zend/tests/bug45862.phpt
new file mode 100644 (file)
index 0000000..f70c142
--- /dev/null
@@ -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"
+}
diff --git a/Zend/tests/get_class_vars_001.phpt b/Zend/tests/get_class_vars_001.phpt
new file mode 100644 (file)
index 0000000..ada0be6
--- /dev/null
@@ -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)
+}
diff --git a/Zend/tests/get_class_vars_002.phpt b/Zend/tests/get_class_vars_002.phpt
new file mode 100644 (file)
index 0000000..721ebe6
--- /dev/null
@@ -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
diff --git a/Zend/tests/get_class_vars_003.phpt b/Zend/tests/get_class_vars_003.phpt
new file mode 100644 (file)
index 0000000..f9dab77
--- /dev/null
@@ -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)
+}
diff --git a/Zend/tests/get_class_vars_004.phpt b/Zend/tests/get_class_vars_004.phpt
new file mode 100644 (file)
index 0000000..26cd461
--- /dev/null
@@ -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
diff --git a/Zend/tests/get_class_vars_005.phpt b/Zend/tests/get_class_vars_005.phpt
new file mode 100644 (file)
index 0000000..51f5490
--- /dev/null
@@ -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)
+}
diff --git a/Zend/tests/get_class_vars_006.phpt b/Zend/tests/get_class_vars_006.phpt
new file mode 100644 (file)
index 0000000..73de66b
--- /dev/null
@@ -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) {
+}
diff --git a/Zend/tests/get_class_vars_007.phpt b/Zend/tests/get_class_vars_007.phpt
new file mode 100644 (file)
index 0000000..6aea0e2
--- /dev/null
@@ -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
index d7392fbe858aa13380a0c188d1578aca64da6d3b..0e3dba84188a51c45630f8a3d95ddce025576fc6 100644 (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 */