summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--ext/standard/array.c15
-rw-r--r--ext/standard/tests/array/bug72369.phpt16
3 files changed, 27 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index e2c3b94c1e..fdb232695f 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,7 @@ PHP NEWS
. Fixed bug #72197 (pg_lo_create arbitrary read). (Anatol)
- Standard:
+ . Fixed bug #72369 (array_merge() produces references in PHP7). (Dmitry)
. Fixed bug #72300 (ignore_user_abort(false) has no effect). (Laruence)
. Fixed bug #72229 (Wrong reference when serialize/unserialize an object).
(Laruence)
diff --git a/ext/standard/array.c b/ext/standard/array.c
index d07daf819a..6c58e3aa74 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -3095,15 +3095,20 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src) /* {{{ */
zend_string *string_key;
ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
- if (string_key) {
- if (Z_REFCOUNTED_P(src_entry)) {
+ if (Z_REFCOUNTED_P(src_entry)) {
+ if (UNEXPECTED(Z_ISREF_P(src_entry))
+ && UNEXPECTED(Z_REFCOUNT_P(src_entry) == 1)) {
+ ZVAL_UNREF(src_entry);
+ if (Z_REFCOUNTED_P(src_entry)) {
+ Z_ADDREF_P(src_entry);
+ }
+ } else {
Z_ADDREF_P(src_entry);
}
+ }
+ if (string_key) {
zend_hash_update(dest, string_key, src_entry);
} else {
- if (Z_REFCOUNTED_P(src_entry)) {
- Z_ADDREF_P(src_entry);
- }
zend_hash_next_index_insert_new(dest, src_entry);
}
} ZEND_HASH_FOREACH_END();
diff --git a/ext/standard/tests/array/bug72369.phpt b/ext/standard/tests/array/bug72369.phpt
new file mode 100644
index 0000000000..63bb5625de
--- /dev/null
+++ b/ext/standard/tests/array/bug72369.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #72369 (array_merge() produces references in PHP7)
+--FILE--
+<?php
+$x = 'xxx';
+$d = ['test' => &$x];
+unset($x);
+$a = ['test' => 'yyy'];
+$a = array_merge($a, $d);
+debug_zval_dump($a);
+?>
+--EXPECTF--
+array(1) refcount(%d){
+ ["test"]=>
+ string(3) "xxx" refcount(%d)
+}