]> granicus.if.org Git - php/commitdiff
Fix #76859 stream_get_line skips data if used with data-generating filter
authorKonstantin Kopachev <tenzzor@gmail.com>
Tue, 18 Sep 2018 04:44:01 +0000 (21:44 -0700)
committerJoe Watkins <krakjoe@php.net>
Thu, 3 Oct 2019 04:50:43 +0000 (06:50 +0200)
stream_get-line repeatedly calls php_stream_fill_read_buffer until
enough data is accumulated in buffer. However, when stream contains
filters attached to it, then each call to fill buffer essentially
resets buffer read/write pointers and new data is written over old.
This causes stream_get_line to skip parts of data from stream
This patch fixes such behavior, so fill buffer call will append.

NEWS
ext/standard/tests/streams/bug46147.phpt [new file with mode: 0644]
ext/standard/tests/streams/bug76859.phpt [new file with mode: 0644]
main/streams/filter.c
main/streams/streams.c

diff --git a/NEWS b/NEWS
index 1c4ce6fe5d88cf61eaa19be5ba24e8f5152d7770..17d77557bfe1c05ad918b1feb6a2df46abbf6e56 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ PHP                                                                        NEWS
     (Thomas Calvet)
   . Fixed bug #78612 (strtr leaks memory when integer keys are used and the
     subject string shorter). (Nikita)
+  . Fixed bug #76859 (stream_get_line skips data if used with data-generating 
+    filter). (kkopachev)
 
 26 Sep 2019, PHP 7.2.23
 
diff --git a/ext/standard/tests/streams/bug46147.phpt b/ext/standard/tests/streams/bug46147.phpt
new file mode 100644 (file)
index 0000000..bed2ee5
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Bug #46147 (after stream seek, appending stream filter reads incorrect data)
+--FILE--
+<?php
+$fp = tmpfile();
+fwrite($fp, "this is a lowercase string.\n");
+fseek($fp, 5);
+stream_filter_append($fp, "string.toupper");
+while (!feof($fp)) {
+    echo fread($fp, 5);
+}
+
+--EXPECT--
+IS A LOWERCASE STRING.
diff --git a/ext/standard/tests/streams/bug76859.phpt b/ext/standard/tests/streams/bug76859.phpt
new file mode 100644 (file)
index 0000000..268b06a
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #76859 (stream_get_line skips data if used with filters)
+--FILE--
+<?php
+
+$data = '123';
+
+$fh = fopen('php://memory', 'r+b');
+fwrite($fh, $data);
+rewind($fh);
+stream_filter_append($fh, 'string.rot13', STREAM_FILTER_READ);
+
+$out = '';
+while (!feof($fh)) {
+    $out .= stream_get_line($fh, 1024);
+}
+
+fclose($fh);
+
+echo strlen($out) . "\n";
+--EXPECT--
+3
index 6ccd2b6bd40d3e4da4a49a2a73b934fd6f34df91..6ab98eb0e256ecb799954d58a025be58b09970e9 100644 (file)
@@ -357,8 +357,6 @@ PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_strea
                        case PSFS_PASS_ON:
                                /* If any data is consumed, we cannot rely upon the existing read buffer,
                                   as the filtered data must replace the existing data, so invalidate the cache */
-                               /* note that changes here should be reflected in
-                                  main/streams/streams.c::php_stream_fill_read_buffer */
                                stream->writepos = 0;
                                stream->readpos = 0;
 
index 399ec29810dccc3b2b7261b6673c40a97daf068f..b504711db36dd71b2a56045a250a66dec3bf17c8 100644 (file)
@@ -531,10 +531,6 @@ PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size)
                php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL };
                php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap;
 
-               /* Invalidate the existing cache, otherwise reads can fail, see note in
-                  main/streams/filter.c::_php_stream_filter_append */
-               stream->writepos = stream->readpos = 0;
-
                /* allocate a buffer for reading chunks */
                chunk_buf = emalloc(stream->chunk_size);