php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

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)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 08:01:29 2024 UTC