Skip to content

Fix use-after-free when pclose() closes a stream from its user filter - #24175

Closed
EdmondDantes wants to merge 1 commit into
php:PHP-8.4from
true-async:stream-pclose-in-filter
Closed

EdmondDantes wants to merge 1 commit into
php:PHP-8.4from
true-async:stream-pclose-in-filter

Conversation

@EdmondDantes

Copy link
Copy Markdown
Contributor

While a user filter's filter() runs, its stream carries PHP_STREAM_FLAG_NO_FCLOSE, so fclose() from the callback fails with a warning. pclose() did not check the flag: it freed the stream and the filter under the running callback (use-after-free under Valgrind, no Fibers needed).

pclose() now refuses such a stream with the same warning as fclose() and returns -1, its documented error value. One visible change: pclose() of an opendir() handle, which also carries the flag, now fails the way fclose() of it already does.

Test: ext/standard/tests/filters/pclose_in_filter.phpt.

fclose() refuses a stream marked PHP_STREAM_FLAG_NO_FCLOSE, which a user
filter's callback sets on its stream; pclose() closed it anyway, freeing the
stream and the filter under the running callback.
@EdmondDantes
EdmondDantes force-pushed the stream-pclose-in-filter branch from f08b74d to e0643a1 Compare October 7, 2026 10:12

@bukka bukka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. proc_close seems to have a similar issue.

@bukka bukka closed this in a2011db Nov 7, 2026
@bukka

bukka commented Nov 7, 2026

Copy link
Copy Markdown
Member

The proc_open similar issue addressed in #25281

@EdmondDantes
EdmondDantes deleted the stream-pclose-in-filter branch November 11, 2026 09:58
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.

3 participants