]> granicus.if.org Git - php/commitdiff
fix #29689 and more private property problems
authorStanislav Malyshev <stas@php.net>
Thu, 9 Jun 2005 16:59:57 +0000 (16:59 +0000)
committerStanislav Malyshev <stas@php.net>
Thu, 9 Jun 2005 16:59:57 +0000 (16:59 +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..74dabc159041dec188fd378486ffa679f1d07094 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
-bar: bar
----
-foo: foo
-bar: baz
----
-foo: foo
-bar2: baz2
+--EXPECTF--
+foo: foo foo2
+bar: bar 
+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 4cd638513872fee18e94372c36117ef8a85ffa0c..2d0d59ea96f415671271501597f0bf5d4d9419be 100644 (file)
@@ -1860,9 +1860,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 */
        }
@@ -1874,6 +1883,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 e5d2faa919c395bc191c24fc36ae0b4e4fdac973..7b00196e013836d7c23c2722bb640bed9be7baac 100644 (file)
@@ -134,6 +134,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 43afc6ec2b53628debfee5c91b342670955dcf16..5404e99c769a0411339ae9bc6dc61cdfb01a8126 100644 (file)
@@ -206,22 +206,27 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval
        }
        h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
        if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
-               if (zend_verify_property_access(property_info, zobj->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", zobj->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, zobj->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", zobj->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) != zobj->ce
@@ -229,6 +234,9 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval
                && EG(scope)
                && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
                && scope_property_info->flags & ZEND_ACC_PRIVATE) {
+               if (!silent && (scope_property_info->flags & ZEND_ACC_STATIC)) {
+                       zend_error(E_STRICT, "Accessing static property %s::$%s as non static", EG(scope)->name, Z_STRVAL_P(member));
+               }
                return scope_property_info;
        } else if (property_info) {
                if (denied_access) {
@@ -809,7 +817,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;
@@ -817,7 +825,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
                property_info = &std_property_info;
        }
 
-#if 1&&DEBUG_OBJECT_HANDLERS
+#if DEBUG_OBJECT_HANDLERS
        zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
 #endif
 
index b328e998cfd76d5007c363b05556b0ba5cc2b3b9..b010a6ed2831862c8041f4dae4243a3cfef6e87e 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);
@@ -2403,7 +2406,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, 
@@ -2421,6 +2424,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);
@@ -2904,7 +2911,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 b328e998cfd76d5007c363b05556b0ba5cc2b3b9..b010a6ed2831862c8041f4dae4243a3cfef6e87e 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);
@@ -2403,7 +2406,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, 
@@ -2421,6 +2424,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);
@@ -2904,7 +2911,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;