mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-11972: RecursiveCallbackFilterIterator regression in 8.1.18
This commit is contained in:
4
NEWS
4
NEWS
@@ -11,6 +11,10 @@ PHP NEWS
|
||||
. Fixed GH-12077 (PHP 8.3.0RC1 borked socket-close-on-exec.phpt).
|
||||
(Jakub Zelenka)
|
||||
|
||||
- SPL:
|
||||
. Fixed bug GH-11972 (RecursiveCallbackFilterIterator regression in 8.1.18).
|
||||
(nielsdos)
|
||||
|
||||
31 Aug 2023, PHP 8.3.0RC1
|
||||
|
||||
- Core:
|
||||
|
||||
@@ -1060,13 +1060,12 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
|
||||
ZVAL_ARR(&intern->array, zend_array_dup(Z_ARR_P(array)));
|
||||
|
||||
if (intern->is_child) {
|
||||
Z_TRY_DELREF_P(&intern->bucket->val);
|
||||
Z_TRY_DELREF(intern->bucket->val);
|
||||
/*
|
||||
* replace bucket->val with copied array, so the changes between
|
||||
* parent and child object can affect each other.
|
||||
*/
|
||||
intern->bucket->val = intern->array;
|
||||
Z_TRY_ADDREF_P(&intern->array);
|
||||
ZVAL_COPY(&intern->bucket->val, &intern->array);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
196
ext/spl/tests/gh11972.phpt
Normal file
196
ext/spl/tests/gh11972.phpt
Normal file
@@ -0,0 +1,196 @@
|
||||
--TEST--
|
||||
GH-11972 (RecursiveCallbackFilterIterator regression in 8.1.18)
|
||||
--EXTENSIONS--
|
||||
spl
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveFilterTest {
|
||||
public function traverse(array $variables): array {
|
||||
$array_iterator = new \RecursiveArrayIterator($variables);
|
||||
$filter_iterator = new \RecursiveCallbackFilterIterator($array_iterator, [
|
||||
$this, 'isCyclic',
|
||||
]);
|
||||
$recursive_iterator = new \RecursiveIteratorIterator($filter_iterator, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
$recursive_iterator->setMaxDepth(20);
|
||||
foreach ($recursive_iterator as $value) {
|
||||
// Avoid recursion by marking where we've been.
|
||||
$value['#override_mode_breadcrumb'] = true;
|
||||
}
|
||||
return \iterator_to_array($recursive_iterator);
|
||||
}
|
||||
|
||||
public function isCyclic($current, string $key, \RecursiveArrayIterator $iterator): bool {
|
||||
var_dump($current);
|
||||
if (!is_array($current)) {
|
||||
return false;
|
||||
}
|
||||
// Avoid infinite loops by checking if we've been here before.
|
||||
// e.g. View > query > view > query ...
|
||||
if (isset($current['#override_mode_breadcrumb'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$test_array['e']['p'][] = ['a', 'a'];
|
||||
$test_array['e']['p'][] = ['b', 'b'];
|
||||
$test_array['e']['p'][] = ['c', 'c'];
|
||||
$serialized = serialize($test_array);
|
||||
$unserialized = unserialize($serialized);
|
||||
|
||||
$test_class = new RecursiveFilterTest();
|
||||
$test_class->traverse($unserialized);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
["p"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
}
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
string(1) "a"
|
||||
string(1) "a"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
string(1) "b"
|
||||
string(1) "b"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
string(1) "c"
|
||||
string(1) "c"
|
||||
array(1) {
|
||||
["p"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
}
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "a"
|
||||
[1]=>
|
||||
string(1) "a"
|
||||
}
|
||||
string(1) "a"
|
||||
string(1) "a"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "b"
|
||||
[1]=>
|
||||
string(1) "b"
|
||||
}
|
||||
string(1) "b"
|
||||
string(1) "b"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "c"
|
||||
[1]=>
|
||||
string(1) "c"
|
||||
}
|
||||
string(1) "c"
|
||||
string(1) "c"
|
||||
Done
|
||||
Reference in New Issue
Block a user