Bug #77069 [PATCH]: stream filter loses final block of data
Edit report at https://bugs.php.net/bug.php?id=77069&edit=1
ID: 77069
Patch added by: cmb@php.net
Reported by: fisharebest at gmail dot com
Summary: stream filter loses final block of data
Status: Open
Type: Bug
Package: Streams related
Operating System: Linux and OSX
PHP Version: 7.2.11
Block user comment: N
Private report: N
New Comment:
The following pull request has been associated:
Patch Name: Fix #77069: stream filter loses final block of data
On GitHub: https://github.com/php/php-src/pull/6001
Patch: https://github.com/php/php-src/pull/6001.patch
Previous Comments:
------------------------------------------------------------------------
[2018-10-27 13:43:08] cmb@php.net
FWIW: this behavioral change has been introduced with commit
0a45e8f[1] which fixed bug #75515.
[1] <http://git.php.net/?p=php-src.git;a=commit;h=0a45e8f096a04464bda6277c6f3d0b5461737a27>
------------------------------------------------------------------------
[2018-10-26 18:45:07] fisharebest at gmail dot com
Description:
------------
I'm using a stream filter to process data.
The test case below (also available at https://3v4l.org/kaeRJ)
shows a stream filter that reverses the text on each line.
Since PHP 7.2, the final block of data is not included in the output.
My initial debugging suggests an issue with the $closing parameter. It should be set to true when
processing the final block of data. Since PHP 7.2, it is always false.
It worked for PHP 5.5.21 -> 7.1.
It fails for PHP 7.2 and 7.3.
It fails for PHP <= 5.5.20
Test script:
---------------
<?php
class MyFilter extends php_user_filter {
private $data = '';
public function filter($in, $out, &$consumed, $closing) {
$return = PSFS_FEED_ME;
// While input data is available, continue to read it.
while ($bucket_in = stream_bucket_make_writeable($in)) {
$this->data .= $bucket_in->data;
$consumed += $bucket_in->datalen;
// Process whole lines.
while (preg_match('/(.*?)[\r\n]+(.*)/s', $this->data, $match) === 1) {
list(, $data, $this->data) = $match;
// Send this record output.
$data = strrev($data) . PHP_EOL;
$bucket_out = stream_bucket_new($this->stream, $data);
$return = PSFS_PASS_ON;
stream_bucket_append($out, $bucket_out);
}
}
// Process the final line.
if ($closing && $this->data !== '') {
$data = strrev($this->data) . PHP_EOL;
$bucket_out = stream_bucket_new($this->stream, $data);
$return = PSFS_PASS_ON;
stream_bucket_append($out, $bucket_out);
}
return $return;
}
}
stream_filter_register('my-filter', 'MyFilter');
$input = "Line one\nLine two\nLine three";
$stream = fopen('data://text/plain,' . $input, 'r');
stream_filter_append($stream, 'my-filter');
$output = '';
while (!feof($stream)) {
$output .= fread($stream, 16);
}
fclose($stream);
echo $output;
Expected result:
----------------
eno eniL
owt eniL
eerht eniL
Actual result:
--------------
eno eniL
owt eniL
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=77069&edit=1
Thread (5 messages)