Patch fix_array_replace_recursive_ref_mut for Variables related Bug #71241
Patch version 2015-12-30 00:03 UTC
Return to Bug #71241 |
Download this patch
Patch Revisions:
Developer: as@php.net
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 79c9ab6..d72412c 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -2940,6 +2940,25 @@ PHP_FUNCTION(array_slice)
}
/* }}} */
+static zend_always_inline zval * zval_dup_ref_or_separate(zval *zv) /* {{{ */
+{
+ zval *tmp = zv;
+ ZVAL_DEREF(tmp);
+ if (Z_ISREF_P(zv)) {
+ if (Z_REFCOUNT_P(zv) == 1) {
+ ZVAL_UNREF(zv);
+ } else {
+ Z_DELREF_P(zv);
+ ZVAL_DUP(zv, tmp);
+ }
+ tmp = zv;
+ } else {
+ SEPARATE_ZVAL(tmp);
+ }
+ return tmp;
+}
+/* }}} */
+
PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
{
zval *src_entry, *dest_entry;
@@ -2962,17 +2981,8 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
return 0;
}
- if (Z_ISREF_P(dest_entry)) {
- if (Z_REFCOUNT_P(dest_entry) == 1) {
- ZVAL_UNREF(dest_entry);
- } else {
- Z_DELREF_P(dest_entry);
- ZVAL_DUP(dest_entry, dest_zval);
- }
- dest_zval = dest_entry;
- } else {
- SEPARATE_ZVAL(dest_zval);
- }
+ dest_zval = zval_dup_ref_or_separate(dest_entry);
+
if (Z_TYPE_P(dest_zval) == IS_NULL) {
convert_to_array_ex(dest_zval);
add_next_index_null(dest_zval);
@@ -3092,7 +3102,8 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ *
php_error_docref(NULL, E_WARNING, "recursion detected");
return 0;
}
- SEPARATE_ZVAL(dest_zval);
+
+ dest_zval = zval_dup_ref_or_separate(dest_entry);
if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(dest_zval))) {
Z_ARRVAL_P(dest_zval)->u.v.nApplyCount++;
diff --git a/ext/standard/tests/array/array_replace_recursive_ref.phpt b/ext/standard/tests/array/array_replace_recursive_ref.phpt
new file mode 100644
index 0000000..daf7171
--- /dev/null
+++ b/ext/standard/tests/array/array_replace_recursive_ref.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test array_replace_recursive with references
+--FILE--
+<?php
+
+$one = [1];
+$two = [42];
+
+$arr1 = ['k' => &$one];
+$arr2 = ['k' => &$two];
+var_dump(current($one), current($two));
+array_replace_recursive($arr1, $arr2);
+var_dump(current($one), current($two));
+?>
+--EXPECT--
+int(1)
+int(42)
+int(1)
+int(42)
|