[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 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.