]> granicus.if.org Git - php/commitdiff
Fixed bug #60558 (Invalid read and writes)
authorXinchen Hui <laruence@php.net>
Mon, 19 Dec 2011 16:48:18 +0000 (16:48 +0000)
committerXinchen Hui <laruence@php.net>
Mon, 19 Dec 2011 16:48:18 +0000 (16:48 +0000)
Re-Fixed bug #60536 (Traits Segfault)
#Thanks to tony2001, I found the previous fix -r321089 is actually not a correct one.
#The key problem there is because the traits didn't correct set the property_info.offset
#for private properties. so here come the new fix.

Zend/zend_compile.c
Zend/zend_object_handlers.c

index d65c14dc153ba191d613bb91f2ecd0336aee2d04..cfd1ce8315856f250cea785fb2c0eaf304b8f244 100644 (file)
@@ -4208,6 +4208,50 @@ static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t curr
 }
 /* }}} */
 
+static void zend_traits_register_private_property(zend_class_entry *ce, const char *name, int name_len, zend_property_info *old_info, zval *property TSRMLS_DC) /* {{{ */
+{
+       char *priv_name;
+       int priv_name_length;
+       const char *interned_name;
+       zend_property_info property_info;
+       ulong h = zend_get_hash_value(name, name_len+1);
+       property_info = *old_info;
+
+       if (old_info->flags & ZEND_ACC_STATIC) {
+               property_info.offset = ce->default_static_members_count++;
+               ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
+               ce->default_static_members_table[property_info.offset] = property;
+               if (ce->type == ZEND_USER_CLASS) {
+                       ce->static_members_table = ce->default_static_members_table;
+               }
+       } else {
+               property_info.offset = ce->default_properties_count++;
+               ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
+               ce->default_properties_table[property_info.offset] = property;
+       }
+
+       zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_len, ce->type & ZEND_INTERNAL_CLASS);
+       property_info.name = priv_name;
+       property_info.name_length = priv_name_length;
+
+       interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
+       if (interned_name != property_info.name) {
+               if (ce->type == ZEND_USER_CLASS) {
+                       efree((char*)property_info.name);
+               } else {
+                       free((char*)property_info.name);
+               }
+               property_info.name = interned_name;
+       }
+
+       property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+
+       property_info.ce = ce;
+
+       zend_hash_quick_update(&ce->properties_info, name, name_len+1, h, &property_info, sizeof(zend_property_info), NULL);
+}
+/* }}} */
+
 static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
 {
        size_t i;
@@ -4295,6 +4339,17 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
                                                                        prop_name,
                                                                        ce->name);
                                        }
+                               } else {
+                                       /* private property, make the property_info.offset indenpended */
+                                       if (property_info->flags & ZEND_ACC_STATIC) {
+                                               prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
+                                       } else {
+                                               prop_value = ce->traits[i]->default_properties_table[property_info->offset];
+                                       }
+                                       Z_ADDREF_P(prop_value);
+
+                                       zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
+                                       return;
                                }
                        }
 
index d524c23faa337f8edf300d34daf3a7f0aef4da13..b14c15795bf7fbfa774b93f0af262789b52f5a4f 100644 (file)
@@ -62,7 +62,6 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
                ALLOC_HASHTABLE(zobj->properties);
                zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
                if (ce->default_properties_count) {
-                       char *flags = ecalloc(ce->default_properties_count, sizeof(char));
                        for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
                             zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
                             zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
@@ -71,7 +70,6 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
                                    prop_info->offset >= 0 &&
                                    zobj->properties_table[prop_info->offset]) {
                                        zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
-                                       flags[prop_info->offset] = 1;
                                }                               
                        }
                        while (ce->parent && ce->parent->default_properties_count) {
@@ -84,15 +82,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
                                            (prop_info->flags & ZEND_ACC_PRIVATE) != 0 && 
                                            prop_info->offset >= 0 &&
                                                zobj->properties_table[prop_info->offset]) {
-                                               if (UNEXPECTED(flags[prop_info->offset])) {
-                                                       zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
-                                               } else {
-                                                       zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
-                                               }
+                                               zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
                                        }                               
                                }
                        }
-                       efree(flags);
                }
        }
 }