Repository navigation
Conversation
When a filter returns PSFS_PASS_ON without consuming its input brigade, the read and write filter chains reset that brigade with memset() and leak the unconsumed buckets. When a write filter returns PSFS_FEED_ME or PSFS_ERR_FATAL after appending output buckets, those were leaked too. Discard leftover buckets in both cases.
|
When a stream filter does not move the buckets of its input brigade (for example a
user filter that simply returns
PSFS_PASS_ONwithout callingstream_bucket_make_writeable()),php_stream_write_filtered()andphp_stream_fill_read_buffer()swap the brigades and thenmemset()the old inputbrigade to zero. The unconsumed buckets are still linked to it, so they are leaked.
user_filters.calready warns about this situation("Unprocessed filter buckets remaining on input brigade"), but nothing frees the buckets.
Separately, when a write filter returns
PSFS_FEED_ME(orPSFS_ERR_FATAL) afterappending buckets to the output brigade,
php_stream_write_filtered()only cleans upthe input brigade, so the output buckets are leaked. The read path already discards
the output brigade in this case; the write path now does the same.
Reproducer (debug build):
Changes:
php_stream_bucket_brigade_discard()helper inmain/streams/streams.c.filter chains (the data was already reported as unprocessed and was being dropped
anyway, so behaviour is unchanged apart from the leak).
PSFS_FEED_ME/PSFS_ERR_FATALin the write path, also discard the output brigade.ext/standard/tests/filters/user_filter_unconsumed_buckets_leak.phptcovering the read/
PASS_ON, write/PASS_ONand write/FEED_MEcases.--XFAIL-- This leaks memorysections ofstream_filter_register_mock_class_filter.phptandstream_filter_register_class_coerce_consumed_by_ref_param.phptcan be removed;both pass with this fix.
Tested with a debug build:
ext/standard/tests/filtersandext/standard/tests/fileall pass on PHP-8.4; on master the two former XFAIL tests now pass.