[GIT-PULLS] [php-src] PR #22850: Fix GH-22845: use-after-free with a stashed user-filter bucket brigade

[email protected] (iliaal) Tue, 21 Jul 2026 14:35:05 +0000
Newsgroups php.git-pulls
Message-ID <[email protected]>
Pull Request: https://github.com/php/php-src/pull/22850
Author: iliaal

A user stream filter's `filter($in, $out, ...)` receives its bucket brigades as `le_bucket_brigade` resources, but every caller that dispatches a filter allocates those brigades on its own C stack. `userfilter_filter` only `zval_ptr_dtor`s the argument zvals after the callback and never closes the resources, so a filter that stashes `$in` or `$out` keeps a resource whose `ptr` still points at the popped stack frame. `stream_bucket_make_writeable()` and `stream_bucket_append()` fetch by resource type only, so reusing a stashed brigade dereferences freed stack (ASAN reports stack-use-after-return). Closing both resources right after the callback invalidates any stashed copy, which then throws a TypeError instead of corrupting memory.

The callback is wrapped in `zend_try`/`zend_catch` so the close runs even when the filter bails out (a fatal error would otherwise longjmp past it, leaving the resource fetchable from a `register_shutdown_function`).

Fixes #22845