summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-05-26 14:44:09 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-05-26 14:44:09 +0200
commit2daa89b1e621604721bfa18278b613dab6764aba (patch)
tree3883eff89968a2a6d626e0252e37a2ddaec60f96 /Zend/zend_execute.c
parent59e69eb1c9f0f4fd28f2107fddcac5bdb063a8ae (diff)
parent314ab47e55845862be62683e331aa247025d073d (diff)
downloadphp-git-2daa89b1e621604721bfa18278b613dab6764aba.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: Fix zend_assign_to_typed_ref() implementation
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index f302363621..0a18ab62fa 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -3102,45 +3102,41 @@ conflicting_coercion_error:
return 1;
}
-ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, zend_bool strict, zend_refcounted *ref)
-{
- zend_bool need_copy = ZEND_CONST_COND(value_type & (IS_CONST|IS_CV), 1) ||
- ((value_type & IS_VAR) && UNEXPECTED(ref) && GC_REFCOUNT(ref) > 1);
- zend_bool ret;
- zval tmp;
-
- if (need_copy) {
- ZVAL_COPY(&tmp, value);
- value = &tmp;
- }
- ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), value, strict);
- if (need_copy) {
- Z_TRY_DELREF_P(value);
- }
- if (!ret) {
- if (value_type & (IS_VAR|IS_TMP_VAR)) {
- zval_ptr_dtor(value);
+static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
+ if (Z_REFCOUNTED_P(zval_ptr)) {
+ zend_refcounted *ref = Z_COUNTED_P(zval_ptr);
+ ZEND_ASSERT(Z_TYPE_P(zval_ptr) != IS_REFERENCE);
+ if (!GC_DELREF(ref)) {
+ rc_dtor_func(ref);
+ } else if (UNEXPECTED(GC_MAY_LEAK(ref))) {
+ gc_possible_root(ref);
}
- return Z_REFVAL_P(variable_ptr);
}
+}
+ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, zend_bool strict, zend_refcounted *ref)
+{
+ zend_bool ret;
+ zval value;
+ ZVAL_COPY(&value, orig_value);
+ ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict);
variable_ptr = Z_REFVAL_P(variable_ptr);
- if (EXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
- zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
-
- zend_copy_to_variable(variable_ptr, value, value_type, ref);
- if (GC_DELREF(garbage) == 0) {
- rc_dtor_func(garbage);
- } else { /* we need to split */
- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
- if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
- gc_possible_root(garbage);
+ if (EXPECTED(ret)) {
+ i_zval_ptr_dtor_noref(variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, &value);
+ } else {
+ zval_ptr_dtor_nogc(&value);
+ }
+ if (value_type & (IS_VAR|IS_TMP_VAR)) {
+ if (UNEXPECTED(ref)) {
+ if (UNEXPECTED(GC_DELREF(ref) == 0)) {
+ zval_ptr_dtor(orig_value);
+ efree_size(ref, sizeof(zend_reference));
}
+ } else {
+ i_zval_ptr_dtor_noref(orig_value);
}
- return variable_ptr;
}
-
- zend_copy_to_variable(variable_ptr, value, value_type, ref);
return variable_ptr;
}