Merge branch 'PHP-7.4' into PHP-8.0

* PHP-7.4:
  Fix #77069: stream filter loses final block of data
This commit is contained in:
Christoph M. Becker 2020-12-08 11:49:14 +01:00
commit d6ae0f010e
7 changed files with 148 additions and 2 deletions

1
NEWS
View File

@ -9,6 +9,7 @@ PHP NEWS
. Fixed bug #80391 (Iterable not covariant to mixed). (Nikita)
. Fixed bug #80393 (Build of PHP extension fails due to configuration gap
with libtool). (kir dot morozov at gmail dot com)
. Fixed bug #77069 (stream filter loses final block of data). (cmb)
- Fileinfo:
. Fixed bug #77961 (finfo_open crafted magic parsing SIGABRT). (cmb)

View File

@ -0,0 +1,57 @@
--TEST--
Bug #77069 (stream filter loses final block of data)
--FILE--
<?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;
?>
--EXPECT--
eno eniL
owt eniL
eerht eniL

View File

@ -0,0 +1,16 @@
--TEST--
Bug #77080 (Deflate not working)
--SKIPIF--
<?php
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--FILE--
<?php
$string = str_repeat("0123456789", 100);
$stream = fopen('data://text/plain,' . $string,'r');
stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ, 6);
$compressed = stream_get_contents($stream);
var_dump(gzinflate($compressed) === $string);
?>
--EXPECT--
bool(true)

View File

@ -0,0 +1,57 @@
--TEST--
Bug #79984 (Stream filter is not called with closing arg)
--FILE--
<?php
class F extends php_user_filter
{
public function onCreate()
{
echo 'filter onCreate' . PHP_EOL;
return true;
}
public function onClose()
{
echo 'filter onClose' . PHP_EOL;
}
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = strtoupper($bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
echo 'filtered ' . ($consumed ? $consumed : 0) . ' bytes';
if ($closing) {
echo ' and closing.';
} else {
echo '.';
}
if (feof($this->stream)) {
echo ' Stream has reached end-of-file.';
}
echo PHP_EOL;
return PSFS_PASS_ON;
}
}
stream_filter_register('f', 'F');
$str = str_repeat('a', 8320);
$f2 = fopen('php://temp', 'r+b');
fwrite($f2, $str);
fseek($f2, 0, SEEK_SET);
stream_filter_append($f2, 'f', STREAM_FILTER_READ);
var_dump(strlen(stream_get_contents($f2)));
fclose($f2);
?>
--EXPECT--
filter onCreate
filtered 8192 bytes.
filtered 128 bytes and closing.
int(8320)
filter onClose

View File

@ -0,0 +1,15 @@
--TEST--
Bug #48725 (Support for flushing in zlib stream)
--SKIPIF--
<?php
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--FILE--
<?php
$stream = fopen('data://text/plain;base64,' . base64_encode('Foo bar baz'),
'r');
stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ);
print bin2hex(stream_get_contents($stream));
?>
--EXPECT--
72cbcf57484a2c02e22a00000000ffff0300

View File

@ -88,7 +88,7 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
inflateEnd(&(data->strm));
data->finished = '\1';
exit_status = PSFS_PASS_ON;
} else if (status != Z_OK) {
} else if (status != Z_OK && status != Z_BUF_ERROR) {
/* Something bad happened */
php_error_docref(NULL, E_NOTICE, "zlib: %s", zError(status));
php_stream_bucket_delref(bucket);

View File

@ -565,7 +565,7 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
/* after this call, bucket is owned by the brigade */
php_stream_bucket_append(brig_inp, bucket);
flags = PSFS_FLAG_NORMAL;
flags = stream->eof ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_NORMAL;
} else {
flags = stream->eof ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC;
}