Skip to content

Fix stream filter flush corrupting a partially-read buffer#22424

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:streams-filter-flush-writepos
Open

Fix stream filter flush corrupting a partially-read buffer#22424
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:streams-filter-flush-writepos

Conversation

@iliaal

@iliaal iliaal commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

When a read filter is flushed (for example via stream_filter_remove()) while the stream has already been partially read, _php_stream_filter_flush() backs the unconsumed tail of the read buffer up to offset 0. Two defects in that block diverged from the equivalent code in streams.c. The copy used memcpy() on source/destination ranges that overlap whenever writepos - readpos exceeds readpos, which is undefined behavior (ASAN reports memcpy-param-overlap). And writepos was shrunk with writepos -= readpos after readpos had already been zeroed, making the subtraction a no-op, so writepos stayed inflated by readpos bytes: the stale tail was kept live and later flushed buckets were appended past the real end, duplicating bytes and risking an out-of-bounds write. Use memmove() and subtract before zeroing, matching streams.c. The block dates to the original stream_filter_remove() commit (3455038) in 2004.

When a read filter is flushed (for example via stream_filter_remove())
while the stream has already been partially read, _php_stream_filter_flush()
backs the unconsumed tail of the read buffer up to offset 0. Two defects
in that block diverged from the equivalent code in streams.c. The copy
used memcpy() on source and destination ranges that overlap whenever
writepos - readpos exceeds readpos, which is undefined behavior (ASAN
reports memcpy-param-overlap). And writepos was shrunk with
writepos -= readpos after readpos had already been zeroed, making the
subtraction a no-op, so writepos stayed inflated by readpos bytes: the
stale tail was kept as live data and later flushed buckets were appended
past the real end, duplicating bytes and risking an out-of-bounds write.
Use memmove() and subtract before zeroing, matching streams.c.
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