diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ff8d99addc34e..6f0dc7811ee76 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -593,10 +593,24 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */ /* To check: can't *variable_ptr be some system variable like error_zval here? */ - ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value); - if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) { - zval_copy_ctor(Z_REFVAL_P(variable_ptr)); + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + if (EXPECTED(!Z_ISREF_P(value))) { + Z_ADDREF_P(value); + } else { + if (Z_REFCOUNT_P(value) == 1) { + ZVAL_UNREF(value); + } else { + value = Z_REFVAL_P(value); + } + if (Z_REFCOUNTED_P(value)) { + if (UNEXPECTED(Z_REFVAL_P(variable_ptr) == value)) { + goto exit; + } + Z_ADDREF_P(value); + } + } } + ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value); zval_ptr_dtor(&garbage); } else { zval garbage;