Skip to content

Commit 05560b6

Browse files
kkopachevkrakjoe
authored andcommitted
Fix #76859 stream_get_line skips data if used with data-generating filter
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.
1 parent f2fb37a commit 05560b6

File tree

5 files changed

+38
-6
lines changed

5 files changed

+38
-6
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ PHP NEWS
2121
(Thomas Calvet)
2222
. Fixed bug #78612 (strtr leaks memory when integer keys are used and the
2323
subject string shorter). (Nikita)
24+
. Fixed bug #76859 (stream_get_line skips data if used with data-generating
25+
filter). (kkopachev)
2426

2527
26 Sep 2019, PHP 7.2.23
2628

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Bug #46147 (after stream seek, appending stream filter reads incorrect data)
3+
--FILE--
4+
<?php
5+
$fp = tmpfile();
6+
fwrite($fp, "this is a lowercase string.\n");
7+
fseek($fp, 5);
8+
stream_filter_append($fp, "string.toupper");
9+
while (!feof($fp)) {
10+
echo fread($fp, 5);
11+
}
12+
13+
--EXPECT--
14+
IS A LOWERCASE STRING.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #76859 (stream_get_line skips data if used with filters)
3+
--FILE--
4+
<?php
5+
6+
$data = '123';
7+
8+
$fh = fopen('php://memory', 'r+b');
9+
fwrite($fh, $data);
10+
rewind($fh);
11+
stream_filter_append($fh, 'string.rot13', STREAM_FILTER_READ);
12+
13+
$out = '';
14+
while (!feof($fh)) {
15+
$out .= stream_get_line($fh, 1024);
16+
}
17+
18+
fclose($fh);
19+
20+
echo strlen($out) . "\n";
21+
--EXPECT--
22+
3

main/streams/filter.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,6 @@ PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_strea
357357
case PSFS_PASS_ON:
358358
/* If any data is consumed, we cannot rely upon the existing read buffer,
359359
as the filtered data must replace the existing data, so invalidate the cache */
360-
/* note that changes here should be reflected in
361-
main/streams/streams.c::php_stream_fill_read_buffer */
362360
stream->writepos = 0;
363361
stream->readpos = 0;
364362

main/streams/streams.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,6 @@ PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size)
531531
php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL };
532532
php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap;
533533

534-
/* Invalidate the existing cache, otherwise reads can fail, see note in
535-
main/streams/filter.c::_php_stream_filter_append */
536-
stream->writepos = stream->readpos = 0;
537-
538534
/* allocate a buffer for reading chunks */
539535
chunk_buf = emalloc(stream->chunk_size);
540536

0 commit comments

Comments
 (0)