]> granicus.if.org Git - php/commitdiff
Fixed ZTS race condition (zend_class_entry->ce_flags of internal classes must not...
authorDmitry Stogov <dmitry@zend.com>
Wed, 27 Jun 2018 09:33:20 +0000 (12:33 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 27 Jun 2018 09:33:20 +0000 (12:33 +0300)
Zend/zend_API.c
Zend/zend_inheritance.c
Zend/zend_object_handlers.c
Zend/zend_opcode.c

index 777361d41b7b0921f697ccc2ef1545c1b49f9b59..b05c5a96d4757a43dfc399570620ea8d61640043 100644 (file)
@@ -1146,67 +1146,46 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
 ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
 {
        if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
+               zend_class_entry *ce;
+               zend_class_constant *c;
+               zval *val;
+               zend_property_info *prop_info;
+
                if (class_type->parent) {
                        if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
                                return FAILURE;
                        }
                }
 
-               if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
-                       /* initialize static members of internal class */
-                       int i;
-                       zval *p;
-
-#if ZTS
-                       CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
-#else
-                       class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
-#endif
-                       for (i = 0; i < class_type->default_static_members_count; i++) {
-                               p = &class_type->default_static_members_table[i];
-                               if (Z_TYPE_P(p) == IS_INDIRECT) {
-                                       zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
-                                       ZVAL_DEINDIRECT(q);
-                                       ZVAL_INDIRECT(&CE_STATIC_MEMBERS(class_type)[i], q);
-                               } else {
-                                       ZVAL_COPY_OR_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+               ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
+                       val = &c->value;
+                       if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
+                               if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
+                                       return FAILURE;
                                }
                        }
-               } else {
-                       zend_class_entry *ce;
-                       zend_class_constant *c;
-                       zval *val;
-                       zend_property_info *prop_info;
-
-                       ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
-                               val = &c->value;
-                               if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
-                                       if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
-                                               return FAILURE;
-                                       }
-                               }
-                       } ZEND_HASH_FOREACH_END();
+               } ZEND_HASH_FOREACH_END();
 
-                       ce = class_type;
-                       while (ce) {
-                               ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
-                                       if (prop_info->ce == ce) {
-                                               if (prop_info->flags & ZEND_ACC_STATIC) {
-                                                       val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
-                                               } else {
-                                                       val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
-                                               }
-                                               ZVAL_DEREF(val);
-                                               if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
-                                                       if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
-                                                               return FAILURE;
-                                                       }
+               ce = class_type;
+               while (ce) {
+                       ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
+                               if (prop_info->ce == ce) {
+                                       if (prop_info->flags & ZEND_ACC_STATIC) {
+                                               val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
+                                       } else {
+                                               val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
+                                       }
+                                       ZVAL_DEREF(val);
+                                       if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
+                                               if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
+                                                       return FAILURE;
                                                }
                                        }
-                               } ZEND_HASH_FOREACH_END();
-                               ce = ce->parent;
-                       }
+                               }
+                       } ZEND_HASH_FOREACH_END();
+                       ce = ce->parent;
                }
+
                class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
        }
 
@@ -3705,9 +3684,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
 
        if (ce->type == ZEND_INTERNAL_CLASS) {
                property_info = pemalloc(sizeof(zend_property_info), 1);
-               if ((access_type & ZEND_ACC_STATIC) || Z_TYPE_P(property) == IS_CONSTANT_AST) {
-                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
-               }
        } else {
                property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
                if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
index 67e2b97d3eb658537877a7ff14107546f75ec049..be605a49de6c22c07c87ecfc31c9fff8eaf1e2b6 100644 (file)
@@ -925,8 +925,6 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
                ce->default_static_members_count += parent_ce->default_static_members_count;
                if (ce->type == ZEND_USER_CLASS) {
                        ce->static_members_table = ce->default_static_members_table;
-               } else {
-                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                }
        }
 
index 86029ee4b9fadc2bd2a9ced365f05c152d02effd..fda969cd3008ea74c7a03dd7b33be8b1019a919e 100644 (file)
@@ -1420,6 +1420,34 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
 }
 /* }}} */
 
+static void zend_intenal_class_init_statics(zend_class_entry *class_type) /* {{{ */
+{
+       int i;
+       zval *p;
+
+       if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
+               if (class_type->parent) {
+                       zend_intenal_class_init_statics(class_type->parent);
+               }
+
+#if ZTS
+               CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
+#else
+               class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
+#endif
+               for (i = 0; i < class_type->default_static_members_count; i++) {
+                       p = &class_type->default_static_members_table[i];
+                       if (Z_TYPE_P(p) == IS_INDIRECT) {
+                               zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
+                               ZVAL_DEINDIRECT(q);
+                               ZVAL_INDIRECT(&CE_STATIC_MEMBERS(class_type)[i], q);
+                       } else {
+                               ZVAL_COPY_OR_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+                       }
+               }
+       }
+} /* }}} */
+
 ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent) /* {{{ */
 {
        zend_property_info *property_info = zend_hash_find_ptr(&ce->properties_info, property_name);
@@ -1448,11 +1476,15 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
 
        /* check if static properties were destoyed */
        if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+               if (ce->type == ZEND_INTERNAL_CLASS) {
+                       zend_intenal_class_init_statics(ce);
+               } else {
 undeclared_property:
-               if (!silent) {
-                       zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(property_name));
+                       if (!silent) {
+                               zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(property_name));
+                       }
+                       return NULL;
                }
-               return NULL;
        }
 
        ret = CE_STATIC_MEMBERS(ce) + property_info->offset;
index ddb78c79244d16227c2140ce46cdad8be89c2a88..645f942818a1e82b81c779efe982b83b06ca9165 100644 (file)
@@ -172,7 +172,6 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
 #else
                ce->static_members_table = NULL;
 #endif
-               ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                while (p != end) {
                        i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
                        p++;