]> granicus.if.org Git - php/commitdiff
Fixed bug #72369 (array_merge() produces references in PHP7)
authorDmitry Stogov <dmitry@zend.com>
Thu, 9 Jun 2016 12:07:44 +0000 (15:07 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 9 Jun 2016 12:07:44 +0000 (15:07 +0300)
NEWS
ext/standard/array.c
ext/standard/tests/array/bug72369.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index e2c3b94c1ef37765798c351e8e738ec9460e3971..fdb232695fb109904f22e4b5527e5d9f9ada00ad 100644 (file)
--- 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)
index d07daf819aa3463db9915ccb80ab201755447be5..6c58e3aa74735c80a89b36cb7d90cc0fd74c17d2 100644 (file)
@@ -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 (file)
index 0000000..63bb562
--- /dev/null
@@ -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)
+}