]> granicus.if.org Git - php/commitdiff
Fixed zend_update_class_constants() to always resolve all constants.
authorDmitry Stogov <dmitry@zend.com>
Thu, 21 May 2015 01:13:10 +0000 (04:13 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 21 May 2015 01:13:10 +0000 (04:13 +0300)
Call zend_update_class_constants() only when necessary.

Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_object_handlers.c

index 7f8587ab4f3709fd259553d09ae9af81839ed8d7..757becf74646dce18ec71c7506be35fdececc38e 100644 (file)
@@ -1118,104 +1118,84 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
 }
 /* }}} */
 
-static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset) /* {{{ */
-{
-       ZVAL_DEREF(pp);
-       if (Z_CONSTANT_P(pp)) {
-               zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
-
-               if ((*scope)->parent) {
-                       zend_class_entry *ce = *scope;
-                       zend_property_info *prop_info;
-
-                       do {
-                               ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
-                                       if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
-                                           offset == prop_info->offset) {
-                                               int ret;
-                                               zend_class_entry *old_scope = *scope;
-                                               *scope = prop_info->ce;
-                                               ret = zval_update_constant_ex(pp, 1, NULL);
-                                               *scope = old_scope;
-                                               return ret;
-                                       }
-                               } ZEND_HASH_FOREACH_END();
-                               ce = ce->parent;
-                       } while (ce);
-
-               }
-               return zval_update_constant_ex(pp, 1, NULL);
-       }
-       return SUCCESS;
-}
-/* }}} */
-
 ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
 {
-       int i;
-
-       /* initialize static members of internal class */
-       if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
-               zval *p;
+       if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
+               class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
 
                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);
+                       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);
+                       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_ISREF_P(p) &&
-                               class_type->parent &&
-                               i < class_type->parent->default_static_members_count &&
-                               p == &class_type->parent->default_static_members_table[i] &&
-                               Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
-                       ) {
-                               zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
-
-                               ZVAL_NEW_REF(q, q);
-                               ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
-                               Z_ADDREF_P(q);
-                       } else {
-                               ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
-                       }
-               }
-       }
-
-       if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0) {
-               zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
-               zend_class_entry *old_scope = *scope;
-               zval *val;
-
-               *scope = class_type;
-
-               ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
-                       if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
-                               return FAILURE;
+                       for (i = 0; i < class_type->default_static_members_count; i++) {
+                               p = &class_type->default_static_members_table[i];
+                               if (Z_ISREF_P(p) &&
+                                       class_type->parent &&
+                                       i < class_type->parent->default_static_members_count &&
+                                       p == &class_type->parent->default_static_members_table[i] &&
+                                       Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
+                               ) {
+                                       zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
+
+                                       ZVAL_NEW_REF(q, q);
+                                       ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
+                                       Z_ADDREF_P(q);
+                               } else {
+                                       ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+                               }
                        }
-               } ZEND_HASH_FOREACH_END();
+               } else {
+                       zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
+                       zend_class_entry *old_scope = *scope;
+                       zend_class_entry *ce;
+                       zval *val;
+                       zend_property_info *prop_info;
 
-               for (i = 0; i < class_type->default_properties_count; i++) {
-                       if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) {
-                               if (UNEXPECTED(zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i)) != SUCCESS)) {
-                                       return FAILURE;
+                       *scope = class_type;
+                       ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
+                               ZVAL_DEREF(val);
+                               if (Z_CONSTANT_P(val)) {
+                                       if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
+                                               return FAILURE;
+                                       }
                                }
-                       }
-               }
+                       } ZEND_HASH_FOREACH_END();
 
-               for (i = 0; i < class_type->default_static_members_count; i++) {
-                       if (UNEXPECTED(zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i) != 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_CONSTANT_P(val)) {
+                                                       *scope = ce;
+                                                       if (UNEXPECTED(zval_update_constant_ex(val, 1, NULL) != SUCCESS)) {
+                                                               return FAILURE;
+                                                       }
+                                               }
+                                       }
+                               } ZEND_HASH_FOREACH_END();
+                               ce = ce->parent;
                        }
-               }
 
-               *scope = old_scope;
-               class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
+                       *scope = old_scope;
+               }
        }
        return SUCCESS;
 }
@@ -1313,10 +1293,12 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
                return FAILURE;
        }
 
-       if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
-               ZVAL_NULL(arg);
-               Z_OBJ_P(arg) = NULL;
-               return FAILURE;
+       if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+               if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
+                       ZVAL_NULL(arg);
+                       Z_OBJ_P(arg) = NULL;
+                       return FAILURE;
+               }
        }
 
        if (class_type->create_object == NULL) {
@@ -3632,13 +3614,16 @@ 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_CONSTANT_P(property)) {
+                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+               }
        } else {
                property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
+               if (Z_CONSTANT_P(property)) {
+                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+               }
        }
 
-       if (Z_CONSTANT_P(property)) {
-               ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
-       }
        if (!(access_type & ZEND_ACC_PPP_MASK)) {
                access_type |= ZEND_ACC_PUBLIC;
        }
index 7313b3206584461cc7a7d0b8c9e94842a8615c00..6b65bdd33034339fb22035c058c0caa735ba9302 100644 (file)
@@ -1105,8 +1105,10 @@ ZEND_FUNCTION(get_class_vars)
                RETURN_FALSE;
        } else {
                array_init(return_value);
-               if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
-                       return;
+               if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+                       if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
+                               return;
+                       }
                }
                add_class_vars(ce, 0, return_value);
                add_class_vars(ce, 1, return_value);
index 363ea139d6ecaa2d7ba7e5f54e06ecda1de1674b..0127a9cf04ed0ec4b224e8f445f27ad8d231f227 100644 (file)
@@ -1256,8 +1256,10 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
                goto undeclared_property;
        }
 
-       if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) {
-               return NULL;
+       if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+               if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) {
+                       return NULL;
+               }
        }
        ret = CE_STATIC_MEMBERS(ce) + property_info->offset;