From: Ilia Alshanetsky Date: Wed, 5 Dec 2007 20:04:13 +0000 (+0000) Subject: MFB: Fixed bug #43495 (array_merge_recursive() crashes with recursive X-Git-Tag: php-5.2.6RC1~263 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6829cf90f5d9d8c131b39aaac0bd51e0e84a4cd;p=php MFB: Fixed bug #43495 (array_merge_recursive() crashes with recursive arrays) --- diff --git a/NEWS b/NEWS index 15b37ad674..a9b9530cf0 100644 --- 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). diff --git a/ext/standard/array.c b/ext/standard/array.c index adaefeb0ca..e92eda2330 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -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 index 0000000000..2bdbf96d75 --- /dev/null +++ b/ext/standard/tests/array/bug43495.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #43495 (array_merge_recursive() crashes with recursive arrays) +--FILE-- +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.