Bug #76859 [Opn->Csd]: stream_get_line skips data if used with data-generating filter
| From: | krakjoe@php.net | Date: | Thu, 03 Oct 2019 04:52:51 +0000 |
| Subject: | Bug #76859 [Opn->Csd]: stream_get_line skips data if used with data-generating filter | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-223010@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=76859&edit=1
ID: 76859
Updated by: krakjoe@php.net
Reported by: tenzzor at gmail dot com
Summary: stream_get_line skips data if used with
data-generating filter
-Status: Open
+Status: Closed
Type: Bug
Package: Streams related
Operating System: Linux
PHP Version: master-Git-2018-09-11 (Git)
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of tenzzor@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=05560b67bc87a2bcbfd5b48a48443a62f3311e7d
Log: Fix #76859 stream_get_line skips data if used with data-generating filter
Previous Comments:
------------------------------------------------------------------------
[2018-09-11 04:48:21] tenzzor at gmail dot com
Description:
------------
This is happening with stream filters which create more data then they consume. For example,
base64_encode, zlib.inflate.
The issue is happening because stream_get_line internally calls php_stream_get_record function,
which repeatedly calls php_stream_fill_read_buffer until enough data is "accumulated" in
the buffer. Problem with that is repeated calls to populate read buffer force reset state of
stream->readpos and stream->writepos in case filters exist on the stream.
In other words, if on second call to get_record function, buffer holds some data, but does not have
delimiter in it and length of data is less then required, then function attempts to put more data
into buffer, which is in effect, resets buffer and content is lost.
Test script:
---------------
<?php
$h = fopen('php://temp', 'r+b');
$len = floor(1.5 * 8 * 1024); // 8*1024 == stream->chunk_size. We need a bit more.
$data = str_repeat('1', $len);
fwrite($h, $data);
rewind($h);
stream_filter_append($h, 'convert.base64-encode');
$out = '';
while (!feof($h)) {
$out .= stream_get_line($h, 1024);
}
fclose($h);
echo $len, ' and ', strlen(base64_decode($out)), PHP_EOL;
assert($data == base64_decode($out));
Expected result:
----------------
12288 and 12288
Actual result:
--------------
12288 and 11520
Warning: assert(): assert($data == base64_decode($out)) failed in /usr/src/app/t3.php on line 17
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=76859&edit=1