]> granicus.if.org Git - php/commitdiff
MFB: Fixed bug #43495 (array_merge_recursive() crashes with recursive
authorIlia Alshanetsky <iliaa@php.net>
Wed, 5 Dec 2007 20:04:13 +0000 (20:04 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Wed, 5 Dec 2007 20:04:13 +0000 (20:04 +0000)
arrays)

NEWS
ext/standard/array.c
ext/standard/tests/array/bug43495.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 15b37ad6741665ecef75f7c2803a69b4fda0d631..a9b9530cf0900cef0bd29b47b56c6a3188f98056 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP                                                                        NEWS
 ?? ??? 2008, PHP 5.2.6
 - Fixed weired behavior in CGI parameter parsing. (Dmitry, Hannes Magnusson)
 
+- Fixed bug #43495 (array_merge_recursive() crashes with recursive arrays).
+  (Ilia)
 - Fixed bug #43493 (pdo_pgsql does not send username on connect when password
   is not available). (Ilia)
 - Fixed bug #43482 (array_pad() does not warn on very small pad numbers).
index adaefeb0ca1e322d9c4ef527d182ceb6c8fe747f..e92eda233061b5502992f0360568bde2351b5647 100644 (file)
@@ -2314,9 +2314,10 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS
        while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
                switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
                        case HASH_KEY_IS_STRING:
-                               if (recursive &&
-                                       zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) {
-                                       if (*src_entry == *dest_entry && ((*dest_entry)->refcount % 2)) {
+                               if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) {
+                                       HashTable *thash = HASH_OF(*dest_entry);
+
+                                       if ((thash && thash->nApplyCount > 1) || (*src_entry == *dest_entry && ((*dest_entry)->refcount % 2))) {
                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
                                                return 0;
                                        }
@@ -2325,9 +2326,18 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS
                                        
                                        convert_to_array_ex(dest_entry);
                                        convert_to_array_ex(src_entry);
-                                       if (!php_array_merge(Z_ARRVAL_PP(dest_entry),
-                                                                       Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC))
+                                       if (thash) {
+                                               thash->nApplyCount++;
+                                       }
+                                       if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) {
+                                               if (thash) {
+                                                       thash->nApplyCount--;
+                                               }
                                                return 0;
+                                       }
+                                       if (thash) {
+                                               thash->nApplyCount--;
+                                       }
                                } else {
                                        (*src_entry)->refcount++;
 
diff --git a/ext/standard/tests/array/bug43495.phpt b/ext/standard/tests/array/bug43495.phpt
new file mode 100644 (file)
index 0000000..2bdbf96
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #43495 (array_merge_recursive() crashes with recursive arrays)
+--FILE--
+<?php
+$a=array("key1"=>array("key2"=>array()));
+$a["key1"]["key2"]["key3"]=&$a;
+
+$b=array("key1"=>array("key2"=>array()));
+$b["key1"]["key2"]["key3"]=&$b;
+
+array_merge_recursive($a,$b); 
+
+echo "Done.\n";
+?>
+--EXPECTF--
+Warning: array_merge_recursive(): recursion detected in %s/bug43495.php on line %d
+Done.