1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.3'

* PHP-8.3:
  Fix GH-11972: RecursiveCallbackFilterIterator regression in 8.1.18
This commit is contained in:
Niels Dossche
2023-08-30 22:29:56 +02:00
2 changed files with 198 additions and 3 deletions

View File

@@ -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
View 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