[php-src] master: Merge branch 'PHP-8.5'

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-06-27T07:49:32-04:00

Commit: https://github.com/php/php-src/commit/da1f32361c6032efc6677fb94aa7738be6543fd7
Raw diff: https://github.com/php/php-src/commit/da1f32361c6032efc6677fb94aa7738be6543fd7.diff

Merge branch 'PHP-8.5'

* PHP-8.5:
  Fix use-after-free in RecursiveIteratorIterator on reentry

Changed paths:
  A  ext/spl/tests/recursiveiteratoriterator_rewind_during_next.phpt
  M  ext/spl/spl_iterators.c


Diff:

diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 86652ae4f5cc..6cbabff26a36 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -266,6 +266,7 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv
 						zend_clear_exception();
 					}
 				}
+				iterator = object->iterators[object->level].iterator;
 				ZEND_FALLTHROUGH;
 			case RS_START:
 				if (iterator->funcs->valid(iterator) == FAILURE) {
diff --git a/ext/spl/tests/recursiveiteratoriterator_rewind_during_next.phpt b/ext/spl/tests/recursiveiteratoriterator_rewind_during_next.phpt
new file mode 100644
index 000000000000..3c9863e81a30
--- /dev/null
+++ b/ext/spl/tests/recursiveiteratoriterator_rewind_during_next.phpt
@@ -0,0 +1,41 @@
+--TEST--
+RecursiveIteratorIterator: rewind() re-entered from an inner next() must not use-after-free
+--FILE--
+<?php
+class Reenter implements RecursiveIterator {
+    public $data; public $pos = 0; public $rii; public $depth;
+    public static bool $fired = false;
+    function __construct(array $d, $depth = 0) { $this->data = $d; $this->depth = $depth; }
+    function current(): mixed { return $this->data[$this->pos] ?? null; }
+    function key(): mixed { return $this->pos; }
+    function next(): void {
+        $this->pos++;
+        if ($this->rii && $this->depth === 1 && $this->pos === 1 && !self::$fired) {
+            self::$fired = true;
+            $this->rii->rewind();
+        }
+    }
+    function rewind(): void { $this->pos = 0; }
+    function valid(): bool { return $this->pos < count($this->data); }
+    function hasChildren(): bool { return is_array($this->current()); }
+    function getChildren(): RecursiveIterator {
+        $c = new Reenter($this->current(), $this->depth + 1);
+        $c->rii = $this->rii;
+        return $c;
+    }
+}
+$root = new Reenter([[10, 11], [20, 21]]);
+$rii = new RecursiveIteratorIterator($root, RecursiveIteratorIterator::SELF_FIRST);
+$root->rii = $rii;
+$seen = [];
+foreach ($rii as $v) {
+    if (is_array($v)) { $v = '[' . implode(',', $v) . ']'; }
+    $seen[] = $v;
+    if (count($seen) > 20) { $seen[] = '...'; break; }
+}
+echo implode(' ', $seen), "\n";
+echo "done\n";
+?>
+--EXPECT--
+[10,11] 10 [10,11] 10 11 [20,21] 20 21
+done
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.