]> granicus.if.org Git - php/commitdiff
Prevent reference-counting on persistent zvals (internal constants, default propertie...
authorDmitry Stogov <dmitry@zend.com>
Mon, 30 Oct 2017 20:13:10 +0000 (23:13 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 30 Oct 2017 20:13:10 +0000 (23:13 +0300)
New macro ZVAL_COPY_OR_DUP() is used perform duplication, if necessary.
This should eliminate related race-coditions in ZTS build and prevent reference-counting bugs after unclean shutdown.

13 files changed:
Zend/zend_API.c
Zend/zend_ast.c
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_execute_API.c
Zend/zend_inheritance.c
Zend/zend_opcode.c
Zend/zend_types.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/pass1_5.c
ext/reflection/php_reflection.c
ext/standard/basic_functions.c

index 61b1829f786c3b98c471787595a2417265e1e7bd..4392c4c12e17ba74c4656cadb8e11e61d8b340c3 100644 (file)
@@ -1127,19 +1127,22 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
 #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);
+                               if (Z_ISREF_P(p)) {
+                                       if (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_COPY_OR_DUP(&CE_STATIC_MEMBERS(class_type)[i], Z_REFVAL_P(p));
+                                       }
                                } else {
-                                       ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+                                       ZVAL_COPY_OR_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
                                }
                        }
                } else {
@@ -1191,15 +1194,19 @@ ZEND_API void object_properties_init(zend_object *object, zend_class_entry *clas
                zval *dst = object->properties_table;
                zval *end = src + class_type->default_properties_count;
 
-               do {
-#if ZTS
-                       ZVAL_DUP(dst, src);
-#else
-                       ZVAL_COPY(dst, src);
-#endif
-                       src++;
-                       dst++;
-               } while (src != end);
+               if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
+                       do {
+                               ZVAL_COPY_OR_DUP(dst, src);
+                               src++;
+                               dst++;
+                       } while (src != end);
+               } else {
+                       do {
+                               ZVAL_COPY(dst, src);
+                               src++;
+                               dst++;
+                       } while (src != end);
+               }
                object->properties = NULL;
        }
 }
index 1dcf5e31e1234cac053b7544d4249089db285657..26177c2c726a3b46d1a0c6035936395821d76fb1 100644 (file)
@@ -301,7 +301,7 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc
                                ret = zend_use_undefined_constant(name, ast->attr, result);
                                break;
                        }
-                       ZVAL_DUP(result, zv);
+                       ZVAL_COPY_OR_DUP(result, zv);
                        break;
                }
                case ZEND_AST_CONSTANT_CLASS:
@@ -457,9 +457,9 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc
                                zend_fetch_dimension_const(&tmp, &op1, &op2, (ast->attr == ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
 
                                if (UNEXPECTED(Z_ISREF(tmp))) {
-                                       ZVAL_DUP(result, Z_REFVAL(tmp));
+                                       ZVAL_COPY_OR_DUP(result, Z_REFVAL(tmp));
                                } else {
-                                       ZVAL_DUP(result, &tmp);
+                                       ZVAL_COPY_OR_DUP(result, &tmp);
                                }
                                zval_ptr_dtor(&tmp);
                                zval_dtor(&op1);
index 0d6cc442b6784b5e713c67d65ec1ed71909ac649..37bf4f82e0d297da78a8e984c468b03925ee3a5f 100644 (file)
@@ -1064,12 +1064,8 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st
 
                /* copy: enforce read only access */
                ZVAL_DEREF(prop);
-               if (UNEXPECTED(Z_COPYABLE_P(prop))) {
-                       ZVAL_DUP(&prop_copy, prop);
-                       prop = &prop_copy;
-               } else {
-                       Z_TRY_ADDREF_P(prop);
-               }
+               ZVAL_COPY_OR_DUP(&prop_copy, prop);
+               prop = &prop_copy;
 
                /* this is necessary to make it able to work with default array
                 * properties, returned to user */
@@ -2032,7 +2028,7 @@ static int add_constant_info(zval *item, void *arg) /* {{{ */
                return 0;
        }
 
-       ZVAL_DUP(&const_val, &constant->value);
+       ZVAL_COPY_OR_DUP(&const_val, &constant->value);
        zend_hash_add_new(Z_ARRVAL_P(name_array), constant->name, &const_val);
        return 0;
 }
@@ -2108,7 +2104,7 @@ ZEND_FUNCTION(get_defined_constants)
                                add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
                        }
 
-                       ZVAL_DUP(&const_val, &val->value);
+                       ZVAL_COPY_OR_DUP(&const_val, &val->value);
                        zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
                } ZEND_HASH_FOREACH_END();
 
index 11c56cc60c2d218cfc617b7cab9dda6aaf5975f7..e7657bee7f00b6a4d278daafe351bd8c22655cfa 100644 (file)
@@ -98,12 +98,6 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
 }
 /* }}} */
 
-static void zend_destroy_class_constant_internal(zval *zv) /* {{{ */
-{
-       free(Z_PTR_P(zv));
-}
-/* }}} */
-
 static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ {
        zend_string *interned_str;
 
@@ -1402,7 +1396,7 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
              ((c->flags & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION))
           || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION))
        )) {
-               ZVAL_DUP(zv, &c->value);
+               ZVAL_COPY_OR_DUP(zv, &c->value);
                return 1;
        }
 
@@ -1417,7 +1411,7 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
 
                c = zend_lookup_reserved_const(lookup_name, lookup_len);
                if (c) {
-                       ZVAL_DUP(zv, &c->value);
+                       ZVAL_COPY_OR_DUP(zv, &c->value);
                        return 1;
                }
        }
@@ -1570,7 +1564,7 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name,
 
        /* Substitute case-sensitive (or lowercase) persistent class constants */
        if (Z_TYPE_P(c) < IS_OBJECT) {
-               ZVAL_DUP(zv, c);
+               ZVAL_COPY_OR_DUP(zv, c);
                return 1;
        }
 
@@ -1760,7 +1754,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
        ce->default_properties_table = NULL;
        ce->default_static_members_table = NULL;
        zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0);
-       zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0);
+       zend_hash_init_ex(&ce->constants_table, 8, NULL, NULL, persistent_hashes, 0);
        zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
 
        if (ce->type == ZEND_INTERNAL_CLASS) {
index d159305c96914cecd5b18878b5ca2de112b91300..8ffeaf0b5c3a5cffe7933bc460873438dc9284ed 100644 (file)
@@ -590,7 +590,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */
                                return zend_use_undefined_constant(name, ast->attr, p);
                        }
                        zval_ptr_dtor_nogc(p);
-                       ZVAL_DUP(p, zv);
+                       ZVAL_COPY_OR_DUP(p, zv);
                } else {
                        zval tmp;
 
index 02b1810f2e92d2b3c0fc2e874d32573cb40b4c35..c200573ac850492edcd34bd1b6acae69809259e5 100644 (file)
@@ -775,16 +775,7 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
                if (Z_TYPE(parent_const->value) == IS_CONSTANT_AST) {
                        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                }
-               if (ce->type & ZEND_INTERNAL_CLASS) {
-                       if (Z_REFCOUNTED(parent_const->value)) {
-                               Z_ADDREF(parent_const->value);
-                       }
-                       c = pemalloc(sizeof(zend_class_constant), 1);
-                       memcpy(c, parent_const, sizeof(zend_class_constant));
-               } else {
-                       c = parent_const;
-               }
-               _zend_hash_append_ptr(&ce->constants_table, name, c);
+               _zend_hash_append_ptr(&ce->constants_table, name, parent_const);
        }
 }
 /* }}} */
@@ -842,24 +833,28 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
                        ce->default_properties_table = end;
                }
                src = parent_ce->default_properties_table + parent_ce->default_properties_count;
-               do {
-                       dst--;
-                       src--;
-#ifdef ZTS
-                       if (parent_ce->type != ce->type) {
-                               ZVAL_DUP(dst, src);
+               if (UNEXPECTED(parent_ce->type != ce->type)) {
+                       /* User class extends internal */
+                       do {
+                               dst--;
+                               src--;
+                               ZVAL_COPY_OR_DUP(dst, src);
                                if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
                                        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                                }
                                continue;
-                       }
-#endif
-
-                       ZVAL_COPY(dst, src);
-                       if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
-                               ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
-                       }
-               } while (dst != end);
+                       } while (dst != end);
+               } else {
+                       do {
+                               dst--;
+                               src--;
+                               ZVAL_COPY(dst, src);
+                               if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
+                                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+                               }
+                               continue;
+                       } while (dst != end);
+               }
                ce->default_properties_count += parent_ce->default_properties_count;
        }
 
@@ -884,23 +879,43 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
                        dst = end + parent_ce->default_static_members_count;
                        ce->default_static_members_table = end;
                }
-               src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
-               do {
-                       dst--;
-                       src--;
-                       if (parent_ce->type == ZEND_INTERNAL_CLASS) {
+               if (UNEXPECTED(parent_ce->type != ce->type)) {
+                       /* User class extends internal */
+                       if (UNEXPECTED(zend_update_class_constants(parent_ce) != SUCCESS)) {
+                               ZEND_ASSERT(0);
+                       }
+                       src = CE_STATIC_MEMBERS(parent_ce) + parent_ce->default_static_members_count;
+                       do {
+                               dst--;
+                               src--;
+                               ZVAL_MAKE_REF(src);
+                               ZVAL_COPY_VALUE(dst, src);
+                               Z_ADDREF_P(dst);
+                       } while (dst != end);
+               } else if (ce->type == ZEND_USER_CLASS) {
+                       src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
+                       do {
+                               dst--;
+                               src--;
+                               ZVAL_MAKE_REF(src);
+                               ZVAL_COPY_VALUE(dst, src);
+                               Z_ADDREF_P(dst);
+                               if (Z_TYPE_P(Z_REFVAL_P(dst)) == IS_CONSTANT_AST) {
+                                       ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+                               }
+                       } while (dst != end);
+               } else {
+                       src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
+                       do {
+                               dst--;
+                               src--;
                                if (!Z_ISREF_P(src)) {
                                        ZVAL_NEW_PERSISTENT_REF(src, src);
                                }
-                       } else {
-                               ZVAL_MAKE_REF(src);
-                       }
-                       ZVAL_COPY_VALUE(dst, src);
-                       Z_ADDREF_P(dst);
-                       if (Z_TYPE_P(Z_REFVAL_P(dst)) == IS_CONSTANT_AST) {
-                               ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
-                       }
-               } while (dst != end);
+                               ZVAL_COPY_VALUE(dst, src);
+                               Z_ADDREF_P(dst);
+                       } while (dst != end);
+               }
                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;
@@ -988,16 +1003,7 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c,
                if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
                        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
                }
-               if (ce->type & ZEND_INTERNAL_CLASS) {
-                       if (Z_REFCOUNTED(c->value)) {
-                               Z_ADDREF(c->value);
-                       }
-                       ct = pemalloc(sizeof(zend_class_constant), 1);
-                       memcpy(ct, c, sizeof(zend_class_constant));
-               } else {
-                       ct = c;
-               }
-               zend_hash_update_ptr(&ce->constants_table, name, ct);
+               zend_hash_update_ptr(&ce->constants_table, name, c);
        }
 }
 /* }}} */
index 7eafbc05e1f85f951b8da790504c6a343c79319c..2382afbfb93581ef94dc8a838cfb7d95a8b34fdb 100644 (file)
@@ -346,9 +346,12 @@ ZEND_API void destroy_zend_class(zval *zv)
                                zend_class_constant *c;
 
                                ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
-                                       zval_internal_ptr_dtor(&c->value);
-                                       if (c->doc_comment && c->ce == ce) {
-                                               zend_string_release(c->doc_comment);
+                                       if (c->ce == ce) {
+                                               zval_internal_ptr_dtor(&c->value);
+                                               if (c->doc_comment) {
+                                                       zend_string_release(c->doc_comment);
+                                               }
+                                               free(c);
                                        }
                                } ZEND_HASH_FOREACH_END();
                                zend_hash_destroy(&ce->constants_table);
index d96891cb249ea3fad8ca79807011c8e5fc5190c0..341b1fe8c9ef1118d21fd778504239ca4d58fb99 100644 (file)
@@ -993,6 +993,26 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
                }                                                                                               \
        } while (0)
 
+
+/* ZVAL_COPY_OR_DUP() should be used instead of ZVAL_COPY() and ZVAL_DUP()
+ * in all places where the source may be a persistent zval.
+ */
+#define ZVAL_COPY_OR_DUP(z, v)                                                                                 \
+       do {                                                                                                                            \
+               zval *_z1 = (z);                                                                                                \
+               const zval *_z2 = (v);                                                                                  \
+               zend_refcounted *_gc = Z_COUNTED_P(_z2);                                                \
+               uint32_t _t = Z_TYPE_INFO_P(_z2);                                                               \
+               ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t);                                                  \
+               if ((_t & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) {   \
+                       if (EXPECTED(!(GC_FLAGS(_gc) & GC_PERSISTENT))) {                       \
+                               GC_ADDREF(_gc);                                                                                 \
+                       } else {                                                                                                        \
+                               _zval_copy_ctor_func(_z1 ZEND_FILE_LINE_CC);                    \
+                       }                                                                                                                       \
+               }                                                                                                                               \
+       } while (0)
+
 #define ZVAL_DEREF(z) do {                                                             \
                if (UNEXPECTED(Z_ISREF_P(z))) {                                 \
                        (z) = Z_REFVAL_P(z);                                            \
index 54964646916e5cf912963535eaf9c4073699d61c..6449741d127edd55e22f02723d1b1ff522449f0d 100644 (file)
@@ -5055,15 +5055,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST, CONST_FETCH)
                CACHE_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)), c);
        }
 
-#ifdef ZTS
-       if (c->flags & CONST_PERSISTENT) {
-               ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -5081,9 +5073,6 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
                if (OP1_TYPE == IS_CONST) {
                        if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2))))) {
                                value = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)));
-#ifdef ZTS
-                               ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
-#endif
                                break;
                        } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))))) {
                                ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
@@ -5140,15 +5129,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
                }
        } while (0);
 
-#ifdef ZTS
-       if (ce->type == ZEND_INTERNAL_CLASS) {
-               ZVAL_DUP(EX_VAR(opline->result.var), value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
 
        ZEND_VM_NEXT_OPCODE();
 }
index 087610b10f183bd42dd8245e248aea260e778ddd..88adc1c2552ad828fceb7e5a017dd049991f9d1d 100644 (file)
@@ -5764,9 +5764,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS
                if (IS_CONST == IS_CONST) {
                        if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2))))) {
                                value = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)));
-#ifdef ZTS
-                               ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
-#endif
                                break;
                        } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))))) {
                                ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
@@ -5823,15 +5820,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS
                }
        } while (0);
 
-#ifdef ZTS
-       if (ce->type == ZEND_INTERNAL_CLASS) {
-               ZVAL_DUP(EX_VAR(opline->result.var), value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -19813,9 +19802,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_
                if (IS_VAR == IS_CONST) {
                        if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2))))) {
                                value = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)));
-#ifdef ZTS
-                               ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
-#endif
                                break;
                        } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))))) {
                                ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
@@ -19872,15 +19858,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_
                }
        } while (0);
 
-#ifdef ZTS
-       if (ce->type == ZEND_INTERNAL_CLASS) {
-               ZVAL_DUP(EX_VAR(opline->result.var), value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -28698,15 +28676,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
                CACHE_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)), c);
        }
 
-#ifdef ZTS
-       if (c->flags & CONST_PERSISTENT) {
-               ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -28724,9 +28694,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS
                if (IS_UNUSED == IS_CONST) {
                        if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2))))) {
                                value = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op2)));
-#ifdef ZTS
-                               ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
-#endif
                                break;
                        } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))))) {
                                ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)));
@@ -28783,15 +28750,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS
                }
        } while (0);
 
-#ifdef ZTS
-       if (ce->type == ZEND_INTERNAL_CLASS) {
-               ZVAL_DUP(EX_VAR(opline->result.var), value);
-       } else {
-               ZVAL_COPY(EX_VAR(opline->result.var), value);
-       }
-#else
-       ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
+       ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
 
        ZEND_VM_NEXT_OPCODE();
 }
index 9f2801901355e9e57da40f6bb70eddaa6faeaee3..002b6ce80a9a78f677361ae5fe4bbd4ee5ca6936 100644 (file)
@@ -310,8 +310,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                                                break;
                                                        }
                                                } else {
-                                                       ZVAL_COPY_VALUE(&t, c);
-                                                       zval_copy_ctor(&t);
+                                                       ZVAL_COPY_OR_DUP(&t, c);
                                                }
 
                                                if (opline->op1_type == IS_CONST) {
index 9b91a5a1c319d65b6b2af9c283821e2a9c946af4..36af4a193a845f8f8d77d406289560e48fa87877 100644 (file)
@@ -3715,7 +3715,7 @@ ZEND_METHOD(reflection_class_constant, getValue)
        }
        GET_REFLECTION_OBJECT_PTR(ref);
 
-       ZVAL_DUP(return_value, &ref->value);
+       ZVAL_COPY_OR_DUP(return_value, &ref->value);
        if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
                zval_update_constant_ex(return_value, ref->ce);
        }
@@ -3848,7 +3848,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
 
                /* copy: enforce read only access */
                ZVAL_DEREF(prop);
-               ZVAL_DUP(&prop_copy, prop);
+               ZVAL_COPY_OR_DUP(&prop_copy, prop);
 
                /* this is necessary to make it able to work with default array
                * properties, returned to user */
@@ -4504,7 +4504,7 @@ ZEND_METHOD(reflection_class, getConstants)
        zend_class_entry *ce;
        zend_string *key;
        zend_class_constant *c;
-       zval *val;
+       zval val;
 
        if (zend_parse_parameters_none() == FAILURE) {
                return;
@@ -4516,8 +4516,8 @@ ZEND_METHOD(reflection_class, getConstants)
                        zend_array_destroy(Z_ARRVAL_P(return_value));
                        return;
                }
-               val = zend_hash_add_new(Z_ARRVAL_P(return_value), key, &c->value);
-               Z_TRY_ADDREF_P(val);
+               ZVAL_COPY_OR_DUP(&val, &c->value);
+               zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
        } ZEND_HASH_FOREACH_END();
 }
 /* }}} */
@@ -4567,7 +4567,7 @@ ZEND_METHOD(reflection_class, getConstant)
        if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
                RETURN_FALSE;
        }
-       ZVAL_DUP(return_value, &c->value);
+       ZVAL_COPY_OR_DUP(return_value, &c->value);
 }
 /* }}} */
 
@@ -5848,7 +5848,7 @@ static int _addconstant(zval *el, int num_args, va_list args, zend_hash_key *has
        int number = va_arg(args, int);
 
        if (number == constant->module_number) {
-               ZVAL_DUP(&const_val, &constant->value);
+               ZVAL_COPY_OR_DUP(&const_val, &constant->value);
                zend_hash_update(Z_ARRVAL_P(retval), constant->name, &const_val);
        }
        return 0;
index 93d469168b70596e9a839f3298fc9c3794ea0938..071099c7b90f512f4f4b4113ce119dcc0b7848af 100644 (file)
@@ -3879,7 +3879,7 @@ PHP_FUNCTION(constant)
        scope = zend_get_executed_scope();
        c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_SILENT);
        if (c) {
-               ZVAL_DUP(return_value, c);
+               ZVAL_COPY_OR_DUP(return_value, c);
                if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
                        if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) {
                                return;