]> granicus.if.org Git - php/commitdiff
MF50: fix #29689 and more private property problems
authorStanislav Malyshev <stas@php.net>
Thu, 9 Jun 2005 17:20:44 +0000 (17:20 +0000)
committerStanislav Malyshev <stas@php.net>
Thu, 9 Jun 2005 17:20:44 +0000 (17:20 +0000)
Zend/tests/bug29689.phpt
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_object_handlers.c
Zend/zend_reflection_api.c
ext/reflection/php_reflection.c

index 003499f378ead2d7aec1f8f7b43e48cbd3eb3969..e0a037a1b6e2342cdc68b911d7259c22ee246269 100644 (file)
@@ -4,10 +4,11 @@ Bug #29689 (default value of protected member overrides default value of private
 <?php
 class foo {
     private $foo = 'foo';
+    private $foo2 = 'foo2';
 
     function printFoo()
     {
-        echo __CLASS__, ': ', $this->foo, "\n";
+        echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n";
     }
 }
 
@@ -17,41 +18,45 @@ class bar extends foo {
     function printFoo()
     {
         parent::printFoo();
-        echo __CLASS__, ': ', $this->foo, "\n";
+        echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n";
     }
 }
 
 class baz extends bar {
     protected $foo = 'baz';
+    protected $foo2 = 'baz2';
 }
 
 class bar2 extends foo {
     function printFoo()
     {
         parent::printFoo();
-        echo __CLASS__, ': ', $this->foo, "\n";
+        echo __CLASS__, ': ', $this->foo, " ", $this->foo2, "\n";
     }
 }
 
 class baz2 extends bar2 {
     protected $foo = 'baz2';
+    protected $foo2 = 'baz22';
 }
 
 $bar = new bar;
 $bar->printFoo();
-echo "---\n";
+echo "---baz--\n";
 $baz = new baz();
 $baz->printFoo();
-echo "---\n";
+echo "---baz2--\n";
 $baz = new baz2();
 $baz->printFoo();
 ?>
---EXPECT--
-foo: foo
+--EXPECTF--
+foo: foo foo2
 bar: bar
----
-foo: foo
-bar: baz
----
-foo: foo
-bar2: baz2
+Notice: Undefined property:  bar::$foo2 in %s on line %d
+
+---baz--
+foo: foo foo2
+bar: baz baz2
+---baz2--
+foo: foo foo2
+bar2: baz2 baz22
index 7e95d0fcdb7d96d0ac0358f1bfb972ddf05c798a..67043fa4481034c019e11929979f7faa0fee91a0 100644 (file)
@@ -1982,9 +1982,18 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
        zend_property_info *child_info;
        zend_class_entry *parent_ce = ce->parent;
 
-       if (parent_info->flags & ZEND_ACC_PRIVATE) {
+       if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
                if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
                        child_info->flags |= ZEND_ACC_CHANGED;
+               } else {
+                       zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
+                       if(ce->type & ZEND_INTERNAL_CLASS) {
+                               zend_duplicate_property_info_internal(child_info);
+                       } else {
+                               zend_duplicate_property_info(child_info);
+                       }
+                       child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
+                       child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
                }
                return 0; /* don't copy access information to child */
        }
@@ -1996,6 +2005,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
                                (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
                                
                }
+               
+               if(parent_info->flags & ZEND_ACC_CHANGED) {
+                       child_info->flags |= ZEND_ACC_CHANGED;
+               }
+               
                if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
                        zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
                } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
index 205da3281130252c2625f6882f1104d10f5bc275..f6a3a8bc388e14390027261753e2b0e8f83e5ba4 100644 (file)
@@ -133,6 +133,9 @@ typedef struct _zend_try_catch_element {
 /* method flag (bc only), any method that has this flag can be used statically and non statically. */
 #define ZEND_ACC_ALLOW_STATIC  0x10000
 
+/* shadow of parent's private method/property */
+#define ZEND_ACC_SHADOW 0x20000
+
 char *zend_visibility_string(zend_uint fn_flags);
 
 
index a0348a1ac454ccbc8a189d0fa75fe672d0fd8e7c..dd86080e6d17c3315e2d7d175537d2f4b50fde3e 100644 (file)
@@ -160,22 +160,27 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
        }
        h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
        if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
-               if (zend_verify_property_access(property_info, ce TSRMLS_CC)) {
-                       if (property_info->flags & ZEND_ACC_CHANGED
-                               && !(property_info->flags & ZEND_ACC_PRIVATE)) {
-                               /* We still need to make sure that we're not in a context
-                                * where the right property is a different 'statically linked' private
-                                * continue checking below...
-                                */
-                       } else {
-                               if (!silent && (property_info->flags & ZEND_ACC_STATIC)) {
-                                       zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
+               if(property_info->flags & ZEND_ACC_SHADOW) {
+                       /* if it's a shadow - go to access it's private */
+                       property_info = NULL;
+               } else {
+                       if (zend_verify_property_access(property_info, ce TSRMLS_CC)) {
+                               if (property_info->flags & ZEND_ACC_CHANGED
+                                       && !(property_info->flags & ZEND_ACC_PRIVATE)) {
+                                       /* We still need to make sure that we're not in a context
+                                        * where the right property is a different 'statically linked' private
+                                        * continue checking below...
+                                        */
+                               } else {
+                                       if (!silent && (property_info->flags & ZEND_ACC_STATIC)) {
+                                               zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
+                                       }
+                                       return property_info;
                                }
-                               return property_info;
+                       } else {
+                               /* Try to look in the scope instead */
+                               denied_access = 1;
                        }
-               } else {
-                       /* Try to look in the scope instead */
-                       denied_access = 1;
                }
        }
        if (EG(scope) != ce
@@ -740,7 +745,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
        zend_property_info *property_info;
        zend_property_info std_property_info;
 
-       if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
+       if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
                std_property_info.flags = ZEND_ACC_PUBLIC;
                std_property_info.name = property_name;
                std_property_info.name_length = property_name_len;
index 133aa80fdd91adf0935c0edd2c443c070bf1414d..ae7a6d3b75dab762ec69b6774d613537c21b818d 100644 (file)
@@ -257,7 +257,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
 /* {{{ _class_string */
 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
 {
-       int count, count_static_props = 0, count_static_funcs = 0;
+       int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
        string sub_indent;
        
        string_init(&sub_indent);
@@ -349,7 +349,9 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (prop->flags & ZEND_ACC_STATIC) {
+                               if(prop->flags & ZEND_ACC_SHADOW) {
+                                       count_shadow_props++;
+                               } else if (prop->flags & ZEND_ACC_STATIC) {
                                        count_static_props++;
                                }
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
@@ -365,9 +367,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (prop->flags & ZEND_ACC_STATIC) {
+                               if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
                                        _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
                                }
+
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
                        }
                }
@@ -415,7 +418,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
 
        /* Default/Implicit properties */
        if (&ce->properties_info) {
-               count = zend_hash_num_elements(&ce->properties_info) - count_static_props;
+               count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
                string_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
                if (count > 0) {
                        HashPosition pos;
@@ -424,7 +427,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (!(prop->flags & ZEND_ACC_STATIC)) {
+                               if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
                                        _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
                                }
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
@@ -2724,7 +2727,7 @@ ZEND_METHOD(reflection_class, getProperty)
        }
 
        GET_REFLECTION_OBJECT_PTR(ce);
-       if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) {
+       if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
                reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
        } else {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
@@ -2742,6 +2745,10 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze
        zval *retval = va_arg(args, zval*);
        long filter = va_arg(args, long);
 
+       if (pptr->flags & ZEND_ACC_SHADOW) {
+               return 0;
+       }
+       
        if (pptr->flags & filter) {
                TSRMLS_FETCH();
                ALLOC_ZVAL(property);
@@ -3248,7 +3255,7 @@ ZEND_METHOD(reflection_property, __construct)
                        /* returns out of this function */
        }
 
-       if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE) {
+       if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags | ZEND_ACC_SHADOW)) {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
                        "Property %s::$%s does not exist", ce->name, name_str);
                return;
index 133aa80fdd91adf0935c0edd2c443c070bf1414d..ae7a6d3b75dab762ec69b6774d613537c21b818d 100644 (file)
@@ -257,7 +257,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
 /* {{{ _class_string */
 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
 {
-       int count, count_static_props = 0, count_static_funcs = 0;
+       int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
        string sub_indent;
        
        string_init(&sub_indent);
@@ -349,7 +349,9 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (prop->flags & ZEND_ACC_STATIC) {
+                               if(prop->flags & ZEND_ACC_SHADOW) {
+                                       count_shadow_props++;
+                               } else if (prop->flags & ZEND_ACC_STATIC) {
                                        count_static_props++;
                                }
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
@@ -365,9 +367,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (prop->flags & ZEND_ACC_STATIC) {
+                               if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
                                        _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
                                }
+
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
                        }
                }
@@ -415,7 +418,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
 
        /* Default/Implicit properties */
        if (&ce->properties_info) {
-               count = zend_hash_num_elements(&ce->properties_info) - count_static_props;
+               count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
                string_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
                if (count > 0) {
                        HashPosition pos;
@@ -424,7 +427,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                        zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
 
                        while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
-                               if (!(prop->flags & ZEND_ACC_STATIC)) {
+                               if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
                                        _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
                                }
                                zend_hash_move_forward_ex(&ce->properties_info, &pos);
@@ -2724,7 +2727,7 @@ ZEND_METHOD(reflection_class, getProperty)
        }
 
        GET_REFLECTION_OBJECT_PTR(ce);
-       if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) {
+       if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
                reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
        } else {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
@@ -2742,6 +2745,10 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze
        zval *retval = va_arg(args, zval*);
        long filter = va_arg(args, long);
 
+       if (pptr->flags & ZEND_ACC_SHADOW) {
+               return 0;
+       }
+       
        if (pptr->flags & filter) {
                TSRMLS_FETCH();
                ALLOC_ZVAL(property);
@@ -3248,7 +3255,7 @@ ZEND_METHOD(reflection_property, __construct)
                        /* returns out of this function */
        }
 
-       if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE) {
+       if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags | ZEND_ACC_SHADOW)) {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
                        "Property %s::$%s does not exist", ce->name, name_str);
                return;