Skip to content

Commit 615197a

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Fix #77069: stream filter loses final block of data
2 parents 748d553 + d6ae0f0 commit 615197a

File tree

6 files changed

+147
-2
lines changed

6 files changed

+147
-2
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
Bug #77069 (stream filter loses final block of data)
3+
--FILE--
4+
<?php
5+
class MyFilter extends php_user_filter {
6+
private $data = '';
7+
8+
public function filter($in, $out, &$consumed, $closing) {
9+
$return = PSFS_FEED_ME;
10+
11+
// While input data is available, continue to read it.
12+
while ($bucket_in = stream_bucket_make_writeable($in)) {
13+
$this->data .= $bucket_in->data;
14+
$consumed += $bucket_in->datalen;
15+
16+
// Process whole lines.
17+
while (preg_match('/(.*?)[\r\n]+(.*)/s', $this->data, $match) === 1) {
18+
list(, $data, $this->data) = $match;
19+
// Send this record output.
20+
$data = strrev($data) . PHP_EOL;
21+
$bucket_out = stream_bucket_new($this->stream, $data);
22+
$return = PSFS_PASS_ON;
23+
stream_bucket_append($out, $bucket_out);
24+
}
25+
}
26+
27+
// Process the final line.
28+
if ($closing && $this->data !== '') {
29+
$data = strrev($this->data) . PHP_EOL;
30+
$bucket_out = stream_bucket_new($this->stream, $data);
31+
$return = PSFS_PASS_ON;
32+
stream_bucket_append($out, $bucket_out);
33+
}
34+
35+
return $return;
36+
}
37+
}
38+
39+
stream_filter_register('my-filter', 'MyFilter');
40+
41+
$input = "Line one\nLine two\nLine three";
42+
43+
$stream = fopen('data://text/plain,' . $input, 'r');
44+
stream_filter_append($stream, 'my-filter');
45+
46+
$output = '';
47+
while (!feof($stream)) {
48+
$output .= fread($stream, 16);
49+
}
50+
fclose($stream);
51+
52+
echo $output;
53+
?>
54+
--EXPECT--
55+
eno eniL
56+
owt eniL
57+
eerht eniL
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #77080 (Deflate not working)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('zlib')) die('skip zlib extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$string = str_repeat("0123456789", 100);
10+
$stream = fopen('data://text/plain,' . $string,'r');
11+
stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ, 6);
12+
$compressed = stream_get_contents($stream);
13+
var_dump(gzinflate($compressed) === $string);
14+
?>
15+
--EXPECT--
16+
bool(true)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
Bug #79984 (Stream filter is not called with closing arg)
3+
--FILE--
4+
<?php
5+
6+
class F extends php_user_filter
7+
{
8+
public function onCreate()
9+
{
10+
echo 'filter onCreate' . PHP_EOL;
11+
return true;
12+
}
13+
14+
public function onClose()
15+
{
16+
echo 'filter onClose' . PHP_EOL;
17+
}
18+
19+
public function filter($in, $out, &$consumed, $closing)
20+
{
21+
while ($bucket = stream_bucket_make_writeable($in)) {
22+
$bucket->data = strtoupper($bucket->data);
23+
$consumed += $bucket->datalen;
24+
stream_bucket_append($out, $bucket);
25+
}
26+
echo 'filtered ' . ($consumed ? $consumed : 0) . ' bytes';
27+
if ($closing) {
28+
echo ' and closing.';
29+
} else {
30+
echo '.';
31+
}
32+
if (feof($this->stream)) {
33+
echo ' Stream has reached end-of-file.';
34+
}
35+
echo PHP_EOL;
36+
return PSFS_PASS_ON;
37+
}
38+
}
39+
40+
stream_filter_register('f', 'F');
41+
42+
$str = str_repeat('a', 8320);
43+
44+
$f2 = fopen('php://temp', 'r+b');
45+
fwrite($f2, $str);
46+
fseek($f2, 0, SEEK_SET);
47+
stream_filter_append($f2, 'f', STREAM_FILTER_READ);
48+
var_dump(strlen(stream_get_contents($f2)));
49+
fclose($f2);
50+
51+
?>
52+
--EXPECT--
53+
filter onCreate
54+
filtered 8192 bytes.
55+
filtered 128 bytes and closing.
56+
int(8320)
57+
filter onClose

ext/zlib/tests/bug48725_2.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Bug #48725 (Support for flushing in zlib stream)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('zlib')) die('skip zlib extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$stream = fopen('data://text/plain;base64,' . base64_encode('Foo bar baz'),
10+
'r');
11+
stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ);
12+
print bin2hex(stream_get_contents($stream));
13+
?>
14+
--EXPECT--
15+
72cbcf57484a2c02e22a00000000ffff0300

ext/zlib/zlib_filter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
8888
inflateEnd(&(data->strm));
8989
data->finished = '\1';
9090
exit_status = PSFS_PASS_ON;
91-
} else if (status != Z_OK) {
91+
} else if (status != Z_OK && status != Z_BUF_ERROR) {
9292
/* Something bad happened */
9393
php_error_docref(NULL, E_NOTICE, "zlib: %s", zError(status));
9494
php_stream_bucket_delref(bucket);

main/streams/streams.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
565565
/* after this call, bucket is owned by the brigade */
566566
php_stream_bucket_append(brig_inp, bucket);
567567

568-
flags = PSFS_FLAG_NORMAL;
568+
flags = stream->eof ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_NORMAL;
569569
} else {
570570
flags = stream->eof ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC;
571571
}

0 commit comments

Comments
 (0)