diff --git a/Zend/tests/gh10085_1.phpt b/Zend/tests/gh10085_1.phpt new file mode 100644 index 0000000000000..cc11c96a09d32 --- /dev/null +++ b/Zend/tests/gh10085_1.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10085: Assertion in add_function_array() +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + array(2) { + [0]=> + array(0) { + } + [1]=> + int(0) + } + [1]=> + int(0) +} diff --git a/Zend/tests/gh10085_2.phpt b/Zend/tests/gh10085_2.phpt new file mode 100644 index 0000000000000..7895999f2cd05 --- /dev/null +++ b/Zend/tests/gh10085_2.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-10085: Assertion in add_function_array() +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + array(2) { + [0]=> + array(0) { + } + [1]=> + int(0) + } + [1]=> + int(0) +} diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index ef5c50c4336d2..ad206f8dfe462 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -969,12 +969,15 @@ static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zva /* $a += $a */ return; } - if (result != op1) { - ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1))); - } else { - SEPARATE_ARRAY(result); + zval tmp; + ZVAL_ARR(&tmp, zend_array_dup(Z_ARR_P(op1))); + zend_hash_merge(Z_ARRVAL_P(&tmp), Z_ARRVAL_P(op2), zval_add_ref, 0); + if (result == op1) { + /* When result == op1 the caller is assuming that reused when rc == 1. + * Since we're not doing that (GH-10085) we need to release it. */ + zval_ptr_dtor(result); } - zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0); + ZVAL_COPY_VALUE(result, &tmp); } /* }}} */