[php-src] master: Merge branch 'PHP-8.5'
Weilin Du <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Weilin Du (LamentXU123)
Date: 2026-08-28T00:53:32+08:00
Commit: https://github.com/php/php-src/commit/623106050203405249890826d98b4a3a39b2224d
Raw diff: https://github.com/php/php-src/commit/623106050203405249890826d98b4a3a39b2224d.diff
Merge branch 'PHP-8.5'
* PHP-8.5:
Fix read buffer compaction in stream filter flush (#23439)
Changed paths:
A ext/standard/tests/filters/stream_filter_remove_compact_read_buffer.phpt
M NEWS
M main/streams/filter.c
Diff:
diff --git a/NEWS b/NEWS
index d0510be26579..1323057cc07e 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ PHP NEWS
- Standard:
. Fixed an out-of-bounds read when following a redirect response with an
empty Location header. (iliaal)
+ . Fixed read buffer compaction in php_stream_filter_flush(). (crystarm)
27 Aug 2026, PHP 8.6.0beta2
diff --git a/ext/standard/tests/filters/stream_filter_remove_compact_read_buffer.phpt b/ext/standard/tests/filters/stream_filter_remove_compact_read_buffer.phpt
new file mode 100644
index 000000000000..7cfef971e7e7
--- /dev/null
+++ b/ext/standard/tests/filters/stream_filter_remove_compact_read_buffer.phpt
@@ -0,0 +1,31 @@
+--TEST--
+stream_filter_remove() compacts unread data before appending flushed data
+--FILE--
+<?php
+class ClosingSuffixFilter extends php_user_filter
+{
+ public function filter($in, $out, &$consumed, $closing): int
+ {
+ while ($bucket = stream_bucket_make_writeable($in)) {
+ $consumed += $bucket->datalen;
+ stream_bucket_append($out, $bucket);
+ }
+ if ($closing) {
+ stream_bucket_append($out, stream_bucket_new($this->stream, 'END'));
+ }
+ return PSFS_PASS_ON;
+ }
+}
+stream_filter_register('closing-suffix', ClosingSuffixFilter::class);
+$stream = fopen('php://memory', 'w+');
+fwrite($stream, 'abcdef');
+rewind($stream);
+$filter = stream_filter_append($stream, 'closing-suffix', STREAM_FILTER_READ);
+var_dump(fread($stream, 2));
+var_dump(stream_filter_remove($filter));
+var_dump(stream_get_contents($stream));
+?>
+--EXPECT--
+string(2) "ab"
+bool(true)
+string(7) "cdefEND"
diff --git a/main/streams/filter.c b/main/streams/filter.c
index 1be5cb1b3e50..fdc5dfc00ad2 100644
--- a/main/streams/filter.c
+++ b/main/streams/filter.c
@@ -506,9 +506,9 @@ PHPAPI zend_result php_stream_filter_flush(php_stream_filter *filter, bool finis
/* Dump any newly flushed data to the read buffer */
if (stream->readpos > 0) {
/* Back the buffer up */
- memcpy(stream->readbuf, stream->readbuf + stream->readpos, stream->writepos - stream->readpos);
- stream->readpos = 0;
+ memmove(stream->readbuf, stream->readbuf + stream->readpos, stream->writepos - stream->readpos);
stream->writepos -= stream->readpos;
+ stream->readpos = 0;
}
if (flushed_size > (stream->readbuflen - stream->writepos)) {
/* Grow the buffer */