Skip to content

Fix use-after-free serializing an array grown by an element's hook#22714

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix-serialize-array-ref-uaf
Open

Fix use-after-free serializing an array grown by an element's hook#22714
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix-serialize-array-ref-uaf

Conversation

@iliaal

@iliaal iliaal commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

The IS_ARRAY case of php_var_serialize_intern() walks the array's HashTable without holding a reference while php_var_serialize_nested_data() recurses into user hooks, so a __serialize() that grows the same array through a by-reference alias reallocs the backing store mid-walk and the iterator reads freed memory. The object case, var_dump, and var_export already hold a ref across the walk; this adds the same GC_ADDREF/GC_DTOR_NO_REF for arrays, so the append separates a copy instead of reallocating in place. __sleep() and Serializable::serialize() reach the same walk, so one test covers all three.

Reproducer (invalid read in php_var_serialize_nested_data under ASan/valgrind; a normal build usually reads the freed memory and passes, so the test is an ASan canary):

<?php
class G {
    public $ref;
    public function __serialize(): array {
        for ($i = 0; $i < 128; $i++) $this->ref[] = 'x' . $i;
        return ['d' => 1];
    }
}
$g = new G();
$inner = [$g, 'tail'];
$g->ref = &$inner;
$top = [&$inner];
serialize($top);

The IS_ARRAY case of php_var_serialize_intern() walked the array's
HashTable without holding a reference across
php_var_serialize_nested_data(), which recurses into user hooks
(__serialize, __sleep, Serializable::serialize). A hook that grows the
same array through a by-reference alias reallocs the backing store
mid-walk, so the iterator reads freed memory. Hold a ref across the walk,
as the object path and var_dump/var_export already do, so the append
separates a copy instead of reallocating in place.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant