diff options
author | Christopher Jones <sixd@php.net> | 2013-07-25 08:53:29 -0700 |
---|---|---|
committer | Christopher Jones <sixd@php.net> | 2013-07-25 08:53:29 -0700 |
commit | 42e8f3ca288cd40ffb72a5d37d13754263348dd7 (patch) | |
tree | 4c0b8098dd0d0a11119c4dfafacf1da3d0ff6479 | |
parent | 024972e3b957270f7e233794376b36c1e5081c78 (diff) | |
parent | 9776504c5bfa036608fc3fd1ae308c99615972b1 (diff) | |
download | php-git-42e8f3ca288cd40ffb72a5d37d13754263348dd7.tar.gz |
Merge branch 'PHP-5.5' of https://git.php.net/repository/php-src into PHP-5.5
# By Johannes Schlüter (3) and others
# Via Xinchen Hui (3) and others
* 'PHP-5.5' of https://git.php.net/repository/php-src:
Upper section name
Update NEWs
Fixed bug #65328 (Segfault when getting SplStack object Value)
Expand the ZEND_STRL macro to handle platforms where strncmp() is a macro.
fix missing include
Fix bug 65299
Fix compiler warning on redefined constant
Fix comment
fixed bug #65311 testsuite failure due to incomplete fix to bug28985.phpt
fix bug #65028 Phar::buildFromDirectory creates corrupt archives for some specific contents
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | Zend/zend_hash.h | 2 | ||||
-rw-r--r-- | ext/openssl/openssl.c | 3 | ||||
-rw-r--r-- | ext/pdo_mysql/mysql_driver.c | 8 | ||||
-rw-r--r-- | ext/pdo_mysql/pdo_mysql.c | 2 | ||||
-rw-r--r-- | ext/pdo_mysql/php_pdo_mysql_int.h | 2 | ||||
-rw-r--r-- | ext/phar/phar.c | 23 | ||||
-rw-r--r-- | ext/phar/tests/bug65028.phpt | 156 | ||||
-rw-r--r-- | ext/soap/tests/bugs/bug28985.phpt | 4 | ||||
-rw-r--r-- | ext/spl/php_spl.c | 2 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 2 | ||||
-rw-r--r-- | ext/spl/tests/bug65328.phpt | 348 |
12 files changed, 549 insertions, 11 deletions
@@ -10,7 +10,15 @@ PHP NEWS . Fixed bug #65291 (get_defined_constants() causes PHP to crash in a very limited case). (Arpad) +- PDO_mysql: + . Fixed bug #65299 (pdo mysql parsing errors). (Johannes) + +- Phar: + . Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for + some specific contents). (Stas) + - SPL: + . Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence) . Added RecursiveTreeIterator setPostfix and getPostifx methods. (Joshua Thijssen) . Fixed bug #61697 (spl_autoload_functions returns lambda functions diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index bf3577124d..69732cd597 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -28,7 +28,7 @@ #define HASH_KEY_IS_STRING 1 #define HASH_KEY_IS_LONG 2 #define HASH_KEY_NON_EXISTENT 3 -#define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT // Keeping old define (with typo) for backward compatibility +#define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT /* Keeping old define (with typo) for backward compatibility */ #define HASH_UPDATE (1<<0) #define HASH_ADD (1<<1) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index c939c01b2b..655980e20c 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -35,6 +35,9 @@ #include "ext/standard/php_fopen_wrappers.h" #include "ext/standard/md5.h" #include "ext/standard/base64.h" +#ifdef PHP_WIN32 +# include "win32/winutil.h" +#endif /* OpenSSL includes */ #include <openssl/evp.h> diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 54c2e8dd84..cd86503dd7 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -527,9 +527,9 @@ static struct pdo_dbh_methods mysql_methods = { /* }}} */ #ifdef PHP_WIN32 -# define MYSQL_UNIX_ADDR NULL +# define PDO_DEFAULT_MYSQL_UNIX_ADDR NULL #else -# define MYSQL_UNIX_ADDR PDO_MYSQL_G(default_socket) +# define PDO_DEFAULT_MYSQL_UNIX_ADDR PDO_MYSQL_G(default_socket) #endif /* {{{ pdo_mysql_handle_factory */ @@ -545,7 +545,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ { "dbname", "", 0 }, { "host", "localhost", 0 }, { "port", "3306", 0 }, - { "unix_socket", MYSQL_UNIX_ADDR, 0 }, + { "unix_socket", PDO_DEFAULT_MYSQL_UNIX_ADDR, 0 }, }; int connect_opts = 0 #ifdef CLIENT_MULTI_RESULTS @@ -710,7 +710,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ } } -#if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND) +#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) { char *public_key = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY, NULL TSRMLS_CC); if (public_key) { diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 401d20d8b3..78c4ceefe9 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -118,7 +118,7 @@ static PHP_MINIT_FUNCTION(pdo_mysql) REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CA", (long)PDO_MYSQL_ATTR_SSL_CA); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CAPATH", (long)PDO_MYSQL_ATTR_SSL_CAPATH); REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CIPHER", (long)PDO_MYSQL_ATTR_SSL_CIPHER); -#if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND) +#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SERVER_PUBLIC_KEY", (long)PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY); #endif diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h index 42debf07e9..24f7aa2182 100644 --- a/ext/pdo_mysql/php_pdo_mysql_int.h +++ b/ext/pdo_mysql/php_pdo_mysql_int.h @@ -171,7 +171,7 @@ enum { PDO_MYSQL_ATTR_SSL_CA, PDO_MYSQL_ATTR_SSL_CAPATH, PDO_MYSQL_ATTR_SSL_CIPHER, -#if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND) +#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY #endif }; diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 638c1ef83a..ec8e5fbde7 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2579,6 +2579,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, php_serialize_data_t metadata_hash; smart_str main_metadata_str = {0}; int free_user_stub, free_fp = 1, free_ufp = 1; + int manifest_hack = 0; if (phar->is_persistent) { if (error) { @@ -2930,6 +2931,12 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, manifest_len = offset + phar->alias_len + sizeof(manifest) + main_metadata_str.len; phar_set_32(manifest, manifest_len); + /* Hack - see bug #65028, add padding byte to the end of the manifest */ + if(manifest[0] == '\r' || manifest[0] == '\n') { + manifest_len++; + phar_set_32(manifest, manifest_len); + manifest_hack = 1; + } phar_set_32(manifest+4, new_manifest_count); if (has_dirs) { *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF); @@ -3054,6 +3061,22 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert, return EOF; } } + /* Hack - see bug #65028, add padding byte to the end of the manifest */ + if(manifest_hack) { + if(1 != php_stream_write(newfile, manifest, 1)) { + if (closeoldfile) { + php_stream_close(oldfile); + } + + php_stream_close(newfile); + + if (error) { + spprintf(error, 0, "unable to write manifest padding byte"); + } + + return EOF; + } + } /* now copy the actual file data to the new phar */ offset = php_stream_tell(newfile); diff --git a/ext/phar/tests/bug65028.phpt b/ext/phar/tests/bug65028.phpt new file mode 100644 index 0000000000..74273b850b --- /dev/null +++ b/ext/phar/tests/bug65028.phpt @@ -0,0 +1,156 @@ +--TEST-- +Phar - test specific manifest length +--INI-- +phar.readonly=0 +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php + +$files = array( + "lib/widgets/Widgets.php", + "lib/events/FormBeginEventArgs.php", + "lib/events/FormEndEventArgs.php", + "lib/Core.php", + "lib/database/MySqlDatabase.php", + "lib/utils/DateUtil.php", + "js/global.js", + "files/_emptyDirectory", + "files/search/schema.xml", + "vendor/Fusonic/Linq/Internal/WhereIterator.php", + "vendor/Fusonic/Linq/Internal/SelectManyIterator.php", + "vendor/Fusonic/Linq/Internal/SelectIterator.php", + "vendor/Fusonic/Linq/Internal/DiffIterator.php", + "vendor/Fusonic/Linq/Internal/GroupIterator.php", + "vendor/Fusonic/Linq/Internal/DistinctIterator.php", + "vendor/Fusonic/Linq/Internal/LinqHelper.php", + "vendor/Fusonic/Linq/Internal/OrderIterator.php", + "vendor/Fusonic/Linq/Internal/IntersectIterator.php", + "vendor/Fusonic/Linq/GroupedLinq.php", + "vendor/Fusonic/Linq.php", + "vendor/Fusonic/UI/Widgets/Forms/FormBegin.php", + "vendor/Fusonic/UI/Widgets/Forms/FormSectionBuilder.php", + "vendor/Fusonic/UI/Widgets/Forms/AutoSelect.php", + "vendor/Fusonic/UI/Widgets/Forms/ControlGroup.php", + "vendor/Fusonic/UI/Widgets/Forms/FormEnd.php", + "vendor/Fusonic/UI/Widgets/WidgetBase.php", + "modules/calendar/ajax/calendarGetInvitedUsersContentAjaxHandler.php", + "modules/calendar/js/calendarAppointmentForm.js", + "modules/calendar/misc/calendarAppointment.php", + "modules/calendar/pages/forms/calendarAppointmentForm.php", + "modules/calendar/setup/config.xml", + "modules/cmt/js/cmtMicroCommentsWidget.js", + "modules/cmt/setup/config.xml", + "modules/meta/misc/metaContentHelper.php", + "modules/meta/setup/config.xml", + "modules/brd/misc/brdPostStreamFormatter.php", + "modules/brd/misc/brdPost.php", + "modules/brd/setup/config/streamContents.xml", + "modules/brd/setup/resources/lang/en.xml", + "modules/brd/setup/resources/lang/de.xml", + "modules/brd/setup/config.xml", + "modules/auth/misc/authLoginService.php", + "modules/auth/setup/config.xml", + "modules/bwd/cache/bwdWordCacheCreator.php", + "modules/bwd/bwd.php", + "modules/bwd/setup/config.xml", + "modules/nws/templates/pages/forms/nwsNewsForm.tpl", + "modules/nws/templates/pages/nwsShowNewsPage.tpl", + "modules/nws/pages/forms/nwsNewsForm.php", + "modules/nws/pages/nwsShowNewsPage.php", + "modules/nws/setup/config.xml", + "modules/gmp/cache/gmpMarkersCacheCreator.php", + "modules/gmp/select/gmpMapContentSelect.php", + "modules/gmp/templates/gmpShowAppointmentPage.tpl", + "modules/gmp/templates/gmpShowLinkPage.tpl", + "modules/gmp/setup/config.xml", + "modules/mul/cache/mulVideoPortalCacheCreator.php", + "modules/mul/misc/mulPermissionHelper.php", + "modules/mul/templates/widgets/mulFileEmbedWidget_Video_Flv.tpl", + "modules/mul/setup/config/mulUploadVideoPortalMatches.xml", + "modules/mul/setup/config.xml", + "modules/cat/select/catCategorySelect.php", + "modules/cat/misc/catCategory.php", + "modules/cat/templates/pages/forms/catCategoryForm.tpl", + "modules/cat/pages/forms/catEditCategoryForm.php", + "modules/cat/pages/forms/catAddCategoryForm.php", + "modules/cat/setup/config.xml", + "modules/sty/events/styPageShowEventHandler.php", + "modules/sty/misc/styBox.php", + "modules/sty/templates/pages/forms/styLayoutForm.tpl", + "modules/sty/templates/pages/forms/styBoxForm.tpl", + "modules/sty/templates/pages/forms/styVariantForm.tpl", + "modules/sty/setup/resources/lang/en.xml", + "modules/sty/setup/resources/lang/de.xml", + "modules/sty/setup/config.xml", + "modules/reg/misc/regRegistrationHelper.php", + "modules/reg/setup/config.xml", + "modules/not/misc/notEmailNotificationProvider.php", + "modules/not/setup/config.xml", + "modules/styfusonic/setup/config.xml", + "modules/sys/ajax/sysUserAutoSuggestSelectAjaxHandler.php", + "modules/sys/js/sysUserAutoSuggestSelect.js", + "modules/sys/select/sysPermissionSelect.php", + "modules/sys/misc/sysHtaccessConfigWriter.php", + "modules/sys/misc/sysUserRepository.php", + "modules/sys/setup/resources/lang/en.xml", + "modules/sys/setup/resources/lang/de.xml", + "modules/sys/setup/config.xml", + "modules/igr/boxes/igrGreatestEntriesBoxTab.php", + "modules/igr/boxes/igrTopRatedEntriesBoxTab.php", + "modules/igr/setup/config.xml", + "modules/rat/ajax/ratRateAjaxHandler.php", + "modules/rat/ajax/ratUnlikeAjaxHandler.php", + "modules/rat/setup/config.xml", + "modules/search/select/searchModuleSelect.php", + "modules/search/select/searchOrderSelect.php", + "modules/search/misc/searchResultFormatter.php", + "modules/search/misc/searchProviderSolr.php", + "modules/search/misc/searchProviderLucene.php", + "modules/search/misc/searchResultItem.php", + "modules/search/misc/searchProviderBase.php", + "modules/search/misc/searchIProvider.php", + "modules/search/templates/misc/searchResultFormatter.tpl", + "modules/search/templates/pages/searchIndexPage.tpl", + "modules/search/templates/pages/forms/searchSearchForm.tpl", + "modules/search/pages/forms/searchSearchForm.php", + "modules/search/css/searchResultFormatter.css", + "modules/search/setup/config/sysSettings.xml", + "modules/search/setup/resources/lang/en.xml", + "modules/search/setup/resources/lang/de.xml", + "modules/search/setup/config.xml", + "style/Fusonic/40components.css", + "style/_emptyDirectory", + "index.php", +// "a", // This will make the test pass +); + +// Create Phar with the filenames above +$phar = new Phar(__DIR__ . "/bug65028.phar"); +foreach($files as $file) +{ + $phar->addFromString($file, ""); +} + +// Copy phar +copy(__DIR__ . "/bug65028.phar", __DIR__ . "/bug65028-copy.phar"); + +// Open phar +try +{ + $phar = new Phar(__DIR__ . "/bug65028-copy.phar"); + echo "No exception thrown.\n"; +} +catch(UnexpectedValueException $ex) +{ + echo "Exception thrown: " . $ex->getMessage() . "\n"; +} +?> +--CLEAN-- +<?php +@unlink(__DIR__ . "/bug65028.phar"); +@unlink(__DIR__ . "/bug65028-copy.phar"); +?> +--EXPECT-- +No exception thrown. + diff --git a/ext/soap/tests/bugs/bug28985.phpt b/ext/soap/tests/bugs/bug28985.phpt index 5134cbf099..73ff899c39 100644 --- a/ext/soap/tests/bugs/bug28985.phpt +++ b/ext/soap/tests/bugs/bug28985.phpt @@ -44,7 +44,7 @@ array(42) { string iUserPassword; }" [8]=> - string(86) "struct MGCodeLibelle { + string(87) "struct MGCodeLibelle { string Code; string Libelle; boolean Default; @@ -203,4 +203,4 @@ array(42) { string(76) "struct GetEnvironnementResponse { MGEnvironnement GetEnvironnementResult; }" -}
\ No newline at end of file +} diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index c3a774ea96..a5ffdb7d14 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -744,7 +744,7 @@ PHP_FUNCTION(spl_autoload_functions) add_next_index_string(tmp, alfi->func_ptr->common.function_name, 1); add_next_index_zval(return_value, tmp); } else { - if (strncmp(alfi->func_ptr->common.function_name, ZEND_STRL("__lambda_func"))) { + if (strncmp(alfi->func_ptr->common.function_name, "__lambda_func", sizeof("__lambda_func") - 1)) { add_next_index_string(return_value, alfi->func_ptr->common.function_name, 1); } else { char *key; diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index ed13b8e576..9ca681688b 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1646,7 +1646,7 @@ SPL_METHOD(Array, getChildren) return; } if (instanceof_function(Z_OBJCE_PP(entry), Z_OBJCE_P(getThis()) TSRMLS_CC)) { - RETURN_ZVAL(*entry, 0, 0); + RETURN_ZVAL(*entry, 1, 0); } } diff --git a/ext/spl/tests/bug65328.phpt b/ext/spl/tests/bug65328.phpt new file mode 100644 index 0000000000..32e6c24fa7 --- /dev/null +++ b/ext/spl/tests/bug65328.phpt @@ -0,0 +1,348 @@ +--TEST-- +Bug #65328 (Segfault when getting SplStack object Value) +--FILE-- +<?php +/** + * @author AlexanderC + */ + +class Tree +{ + /** + * @var Node + */ + protected $head; + + /** + * @param Node $head + */ + public function __construct(Node $head = null) + { + $this->head = $head ? : new Node('HEAD'); + } + + /** + * @return Node + */ + public function getHead() + { + return $this->head; + } + + /** + * @param mixed $uid + * @return Node|bool + */ + public function find($uid) + { + $iterator = $this->getIterator(); + + /** @var Node $node */ + foreach($iterator as $node) { + if($node->getUid() === $uid) { + return $node; + } + } + + return false; + } + + /** + * @param mixed $uid + * @return \SplStack + */ + public function & findAll($uid) + { + $result = new \SplStack(); + + /** @var Node $node */ + foreach($this->getIterator() as $node) { + if($node->getUid() == $uid) { + $result->push($node); + } + } + + return $result; + } + + /** + * @return \RecursiveIteratorIterator + */ + public function getIterator() + { + return new \RecursiveIteratorIterator( + $this->head->getChildren(), + \RecursiveIteratorIterator::SELF_FIRST + ); + } +} + +class Node extends \RecursiveArrayIterator implements \Countable +{ + /** + * @var array + */ + protected $children = []; + + /** + * @var Node + */ + protected $parent; + + /** + * @var mixed + */ + protected $data; + + /** + * @var mixed + */ + protected $uid; + + /** + * @var int + */ + protected $index = 0; + + /** + * @var bool + */ + protected $assureUnique; + + /** + * @param mixed $data + * @param mixed $uid + * @param Node $parent + * @param bool $assureUnique + */ + public function __construct($data, $uid = null, Node $parent = null, $assureUnique = false) + { + if(null !== $parent) { + $this->parent = $parent; + } + + $this->data = $data; + $this->uid = $uid ? : uniqid(sha1(serialize($data)), true); + $this->assureUnique = $assureUnique; + } + + /** + * @param mixed $uid + */ + public function setUid($uid) + { + $this->uid = $uid; + } + + /** + * @return mixed + */ + public function getUid() + { + return $this->uid; + } + + /** + * @param Node $child + */ + public function addChild(Node $child) + { + $child->setParent($this); + $this->children[] = $child; + } + + /** + * @param array $children + */ + public function setChildren(array $children) + { + $this->children = $children; + } + + /** + * @return array + */ + public function getChildrenArray() + { + return $this->children; + } + + /** + * @param mixed $data + */ + public function setData($data) + { + $this->data = $data; + } + + /** + * @return mixed + */ + public function getData() + { + return $this->data; + } + + /** + * @param Node $parent + * @throws \RuntimeException + */ + public function setParent(Node $parent) + { + if(true === $this->assureUnique && !self::checkUnique($parent, $this->uid)) { + throw new \RuntimeException("Node uid is not unique in assigned node tree"); + } + + $this->parent = $parent; + } + + /** + * @param Node $node + * @param mixed $uid + * @return bool + */ + protected static function checkUnique(Node $node, $uid) + { + $headNode = $node; + do { + $headNode = $node; + } while($node = $node->getParent()); + + $tree = new Tree($headNode); + + return !$tree->find($uid); + } + + /** + * @return \IJsonRPC\Helpers\Tree\Node + */ + public function getParent() + { + return $this->parent; + } + + /** + * @return Node + */ + public function current() + { + return $this->children[$this->index]; + } + + /** + * @return scalar + */ + public function key() + { + return $this->index; + } + + /** + * @return void + */ + public function next() + { + ++$this->index; + } + + /** + * @return void + */ + public function rewind() + { + $this->index = 0; + } + + /** + * @return bool + */ + public function valid() + { + return array_key_exists($this->index, $this->children); + } + + /** + * @return int + */ + public function count() + { + return count($this->children); + } + + /** + * @return bool + */ + public function hasChildren() + { + return !empty($this->children); + } + + /** + * @return \RecursiveArrayIterator + */ + public function getChildren() + { + return new \RecursiveArrayIterator($this->children); + } +} + +$tree = new Tree(); +$node1 = new Node('value1', 1); +$tree->getHead()->addChild($node1); +$node2 = new Node('value2', 2); +$node1->addChild($node2); + +print_r($tree->findAll(2)->offsetGet(0)); +--EXPECTF-- +Node Object +( + [children:protected] => Array + ( + ) + + [parent:protected] => Node Object + ( + [children:protected] => Array + ( + [0] => Node Object + *RECURSION* + ) + + [parent:protected] => Node Object + ( + [children:protected] => Array + ( + [0] => Node Object + *RECURSION* + ) + + [parent:protected] => + [data:protected] => HEAD + [uid:protected] => %s + [index:protected] => 0 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + + ) + + [data:protected] => value1 + [uid:protected] => 1 + [index:protected] => 1 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + + ) + + [data:protected] => value2 + [uid:protected] => 2 + [index:protected] => 0 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + +) |