[php-src] PR #25432: Fix GH-17935: Separate ArrayObject and ArrayIterator storage on write

From: Date: Thu, 12 Nov 2026 19:06:22 +0000
Subject: [php-src] PR #25432: Fix GH-17935: Separate ArrayObject and ArrayIterator storage on write
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-40601@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/25432 Author: nicolas-grekas Split from #23945. ArrayObject and ArrayIterator assume that they're the only owner of their storage. But __serialize(), __debugInfo(), var_export(), json_encode() and the sort methods return or borrow this storage without a copy. A write to the object then also changes the array that was returned, and debug builds fail the refcount assertion of zend_hash.c. That's GH-17935. This PR separates the storage before any write. When that happens during an iteration, the iterator moves to the copy of its position that zend_array_dup() registers on the new table. Object-backed storage isn't changed. An error handler can now separate the storage by writing to the object. So read paths fetch the table after the code that can call a handler. This also fixes use-after-frees when a handler calls exchangeArray() during a read with a null offset, or while an element is created. This is the delayed separation discussed in #17942. It overlaps with #20725, which separates at three write sites, and it fixes the array-backed cases of #22921. foreach over an ArrayObject needs about 3% more instructions (callgrind, 101 elements). /cc @ndossche @iluuu1994 @alexandre-daubois @iliaal

« previous php.git-pulls (#40601) next »