]> granicus.if.org Git - php/commitdiff
Fixed interface constants inheritance.
authorDmitry Stogov <dmitry@zend.com>
Mon, 14 Apr 2014 09:24:43 +0000 (13:24 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 14 Apr 2014 09:24:43 +0000 (13:24 +0400)
Now we use IS_REFERENCE for inhereted class constants.
I might miss some edje cases.

Zend/zend_compile.c
Zend/zend_constants.c
Zend/zend_objects.c
Zend/zend_types.h
Zend/zend_variables.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/pass1_5.c
ext/opcache/zend_accelerator_util_funcs.c
ext/reflection/php_reflection.c

index 818ecf3632e996714e82ac510af41d24c6330f19..d54e705a81737656743d73a039c49ac4ad26b93f 100644 (file)
@@ -3089,7 +3089,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
 
                        ALLOC_HASHTABLE(op_array->static_variables);
                        zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
-                       zend_hash_copy(op_array->static_variables, static_variables, zval_add_ref_unref);
+                       zend_hash_copy(op_array->static_variables, static_variables, zval_add_ref);
                }
                op_array->run_time_cache = NULL;
        } else if (function->type == ZEND_INTERNAL_FUNCTION) {
@@ -3743,6 +3743,27 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
        zval_add_ref
 #endif
 
+static int do_inherit_class_constant(zval *zv TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
+{
+       zend_class_entry *ce = va_arg(args, zend_class_entry *);
+       zend_class_entry *parent_ce = va_arg(args, zend_class_entry *);
+
+       if (hash_key->key) {
+               if (!Z_ISREF_P(zv)) {
+                       if (parent_ce->type == ZEND_INTERNAL_CLASS) {
+                               ZVAL_NEW_PERSISTENT_REF(zv, zv);
+                       } else {
+                               ZVAL_NEW_REF(zv, zv);
+                       }
+               }
+               if (zend_hash_add(&ce->constants_table, hash_key->key, zv)) {
+                       Z_ADDREF_P(zv);
+               }
+       }
+       return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
 {
        zend_property_info *property_info;
@@ -3846,7 +3867,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
 
        zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal_zval : zend_duplicate_property_info_zval), (merge_checker_func_t) do_inherit_property_access_check, ce);
 
-       zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), 0);
+       zend_hash_apply_with_arguments(&parent_ce->constants_table TSRMLS_CC, (apply_func_args_t)do_inherit_class_constant, 2, ce, parent_ce);
        zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, do_inherit_method, (merge_checker_func_t) do_inherit_method_check, ce);
        do_inherit_parent_constructor(ce);
 
@@ -3865,14 +3886,9 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, con
        zval *old_constant;
 
        if ((old_constant = zend_hash_find(child_constants_table, hash_key->key)) != NULL) {
-//???  if (old_constant != parent_constant) {
-//??? see Zend/tests/errmsg_025.phpt
-               if ((Z_TYPE_P(old_constant) != Z_TYPE_P(parent_constant)) ||
-                   (Z_TYPE_P(old_constant) == IS_LONG && Z_LVAL_P(old_constant) != Z_LVAL_P(parent_constant)) ||
-                   (Z_TYPE_P(old_constant) == IS_BOOL && Z_LVAL_P(old_constant) != Z_LVAL_P(parent_constant)) ||
-                   (Z_TYPE_P(old_constant) == IS_DOUBLE && Z_DVAL_P(old_constant) != Z_DVAL_P(parent_constant)) ||
-                   (Z_TYPE_P(old_constant) == IS_STRING && Z_STR_P(old_constant) != Z_STR_P(parent_constant)) ||
-                   (Z_REFCOUNTED_P(old_constant) && Z_COUNTED_P(old_constant) != Z_COUNTED_P(parent_constant))) {
+               if (!Z_ISREF_P(old_constant) ||
+                   !Z_ISREF_P(parent_constant) ||
+                   Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
                        zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->key->val, iface->name->val);
                }
                return 0;
@@ -3891,6 +3907,22 @@ static int do_interface_constant_check(zval *val TSRMLS_DC, int num_args, va_lis
 }
 /* }}} */
 
+static int do_inherit_iface_constant(zval *zv TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
+{
+       zend_class_entry *ce = va_arg(args, zend_class_entry *);
+       zend_class_entry *iface = va_arg(args, zend_class_entry *);
+
+       if (hash_key->key && do_inherit_constant_check(&ce->constants_table, zv, hash_key, iface)) {
+               if (!Z_ISREF_P(zv)) {
+                       ZVAL_NEW_REF(zv, zv);
+               }
+               Z_ADDREF_P(zv);
+               zend_hash_update(&ce->constants_table, hash_key->key, zv);
+       }
+       return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
 {
        zend_uint i, ignore = 0;
@@ -3922,7 +3954,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
                }
                ce->interfaces[ce->num_interfaces++] = iface;
 
-               zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, (merge_checker_func_t) do_inherit_constant_check, iface);
+               zend_hash_apply_with_arguments(&iface->constants_table TSRMLS_CC, (apply_func_args_t)do_inherit_iface_constant, 2, ce, iface);
                zend_hash_merge_ex(&ce->function_table, &iface->function_table, do_inherit_method, (merge_checker_func_t) do_inherit_method_check, ce);
 
                do_implement_interface(ce, iface TSRMLS_CC);
index 8227f185d40c46c53abfd0c33014f91ffbff38f6..964c7f81654e0238dffe91bee9f28b757260c3a8 100644 (file)
@@ -379,6 +379,8 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
                                if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
                                        zend_error(E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val);
                                }
+                       } else if (Z_ISREF_P(ret_constant)) {
+                               ret_constant = Z_REFVAL_P(ret_constant);
                        }
                } else if (!ce) {
                        retval = 0;
index 37423b3dd8fee6760af1a4ec64d0f7e272f5bfab..390d6fc0266f2dd4ee1fd2ee16b45cd4a6e35bef 100644 (file)
@@ -165,7 +165,7 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
                                ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table));
                        } else {
                                ZVAL_COPY_VALUE(&new_prop, prop);
-                               zval_add_ref_unref(&new_prop);
+                               zval_add_ref(&new_prop);
                        }
                        switch (zend_hash_get_current_key_ex(old_object->properties, &key, &num_key, 0, &pos)) {
                                case HASH_KEY_IS_STRING:
index 8baf8643af984a5600c9b4d75c5482422b387f10..4390d992326a9bab672fd8d40c17538777aabaac 100644 (file)
@@ -568,6 +568,15 @@ static inline zend_uchar zval_get_type(const zval* pz) {
                Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;                                             \
        } while (0)
 
+#define ZVAL_NEW_PERSISTENT_REF(z, r) do {                                             \
+               zend_reference *_ref = malloc(sizeof(zend_reference));  \
+               GC_REFCOUNT(_ref) = 1;                                                                  \
+               GC_TYPE_INFO(_ref) = IS_REFERENCE;                                              \
+               ZVAL_COPY_VALUE(&_ref->val, r);                                                 \
+               Z_REF_P(z) = _ref;                                                                              \
+               Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;                                             \
+       } while (0)
+
 #define ZVAL_NEW_AST(z, a) do {                                                                        \
                zval *__z = (z);                                                                                \
                zend_ast_ref *_ast = emalloc(sizeof(zend_ast_ref));             \
index 24e347a15bd36b4a65e571ec296db7b89aff40de..9661af1773ebccd3d815c98ffbb155d5dc4a4051 100644 (file)
@@ -161,6 +161,13 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
                case IS_RESOURCE:
                        zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
                        break;
+               case IS_REFERENCE: {
+                               zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
+
+                               zval_internal_ptr_dtor(&ref->val);
+                               free(ref);
+                               break;
+                       }
                case IS_LONG:
                case IS_DOUBLE:
                case IS_BOOL:
@@ -185,6 +192,13 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
                case IS_RESOURCE:
                        zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
                        break;
+               case IS_REFERENCE: {
+                               zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
+
+                               zval_internal_ptr_dtor(&ref->val);
+                               free(ref);
+                               break;
+                       }
                case IS_LONG:
                case IS_DOUBLE:
                case IS_BOOL:
@@ -210,12 +224,7 @@ ZEND_API void zval_add_ref_unref(zval *p)
 {
        if (Z_REFCOUNTED_P(p)) {
                if (Z_ISREF_P(p)) {
-                       if (Z_REFCOUNT_P(p) == 1) {
-                               zval *q = Z_REFVAL_P(p);
-                               ZVAL_DUP(p, q);
-                       } else {
-                               Z_ADDREF_P(p);
-                       }
+                       ZVAL_DUP(p, Z_REFVAL_P(p));
                } else {
                        Z_ADDREF_P(p);
                }
index 3f714703ba716aa1b0cacc6da8d9c1bcad554077..610b46c58e3a30a88ff867f8813736ceca625a39 100644 (file)
@@ -3693,6 +3693,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                }
 
                if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+                       if (Z_ISREF_P(value)) {
+                               value = Z_REFVAL_P(value);
+                       }
                        if (Z_CONSTANT_P(value)) {
                                zend_class_entry *old_scope = EG(scope);
 
index 427ae46b62854d5ab08e59e5d3bfc687ffab6a26..a6d1be22705d184c48fd97a295804931c38cb3fe 100644 (file)
@@ -3890,6 +3890,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
                }
 
                if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+                       if (Z_ISREF_P(value)) {
+                               value = Z_REFVAL_P(value);
+                       }
                        if (Z_CONSTANT_P(value)) {
                                zend_class_entry *old_scope = EG(scope);
 
@@ -15161,6 +15164,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
                }
 
                if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+                       if (Z_ISREF_P(value)) {
+                               value = Z_REFVAL_P(value);
+                       }
                        if (Z_CONSTANT_P(value)) {
                                zend_class_entry *old_scope = EG(scope);
 
@@ -24594,6 +24600,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
                }
 
                if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
+                       if (Z_ISREF_P(value)) {
+                               value = Z_REFVAL_P(value);
+                       }
                        if (Z_CONSTANT_P(value)) {
                                zend_class_entry *old_scope = EG(scope);
 
index 3bf59be84b4ad00b8ac51195d3186cc708fe6318..9edff53d396e67e5e034f32bcbc4ad63857bea7f 100644 (file)
@@ -294,6 +294,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
 
                                        if ((c = zend_hash_find(&ce->constants_table,
                                                        Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) {
+                                               ZVAL_DEREF(c);
                                                if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) { 
                                                        if (!zend_get_persistent_constant(Z_STR_P(c), &t, 1 TSRMLS_CC) ||
                                                            ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
index 6df81e6ee6d1720b6e76ff4b6bc968d89be2e9b7..61d662a4f884fffa0564eff08da18ee3d775bfb9 100644 (file)
@@ -692,7 +692,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
        zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce, ce TSRMLS_CC);
 
        /* constants table */
-       zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 0);
+       zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
 
        ce->name = STR_DUP(ce->name, 0);
 
index 1ef849f92af9d96fb2e3ae9138226ea03f414e3e..224bec75ba6643e06fa851d8769b12ec8950a1fa 100644 (file)
@@ -4010,7 +4010,7 @@ ZEND_METHOD(reflection_class, getConstants)
        GET_REFLECTION_OBJECT_PTR(ce);
        array_init(return_value);
        zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce TSRMLS_CC);
-       zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref);
+       zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref);
 }
 /* }}} */