Commits

laru...@c90b9560-bf6c-de11-be94-00142212c4b1  committed e7f4d88

Fixed bug #60558 (Invalid read and writes)
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.

  • Participants
  • Parent commits dd6f00f
  • Branches PHP_5_4

Comments (0)

Files changed (3)

   . Fixed bug #60536 (Traits Segfault). (Laruence)
   . Fixed bug #60362 (non-existent sub-sub keys should not have values).
     (Laruence, alan_k, Stas)
+  . Fixed bug #60558 (Invalid read and writes). (Laruence)
 
 - CLI SAPI:
   . Fixed bug #60477 (Segfault after two multipart/form-data POST requests,

File Zend/zend_compile.c

 }
 /* }}} */
 
+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;
 									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;
 				}
 			}
 

File Zend/zend_object_handlers.c

 		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)) {
 				    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) {
 					    (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);
 		}
 	}
 }