[GIT-PULLS] [php-src] PR #22921: Fix use-after-free when json_encode() re-enters an ArrayObject

[email protected] (iliaal) Wed, 29 Jul 2026 12:56:59 +0000
Newsgroups php.git-pulls
Message-ID <OFeTKGVz0JyFAiXSFjYZpgdISQc1fXcAvezqzXajzLk@main.internal.php.net>
Pull Request: https://github.com/php/php-src/pull/22921
Author: iliaal

json_encode() borrows an ArrayObject's storage table for the length of the encode and then runs userland through JsonSerializable::jsonSerialize() and property hooks. spl_array_get_hash_table_ptr() hands that same table back to the write paths, so an insert from the callback grows it and frees the buckets the encoder is iterating; valgrind reports invalid reads in php_json_encode_array() for the array-backed ArrayObject, ArrayIterator and self-backed cases in the test. The object-backed branch of that function already separates when the table is borrowed, so this gives the other two branches the same treatment. Encoding cost is unchanged: the separation only fires while a borrow is outstanding, and the refcount is 1 the rest of the time.

#20725 proposes the same SEPARATE_ARRAY call at the write sites instead. That placement leaves the by-reference auto-vivify path through spl_array_get_dimension_ptr() unprotected, which valgrind still reports as an invalid read, and it does not reach the self-backed case.