summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--ext/standard/tests/streams/bug77069.phpt57
-rw-r--r--ext/standard/tests/streams/bug77080.phpt16
-rw-r--r--ext/standard/tests/streams/bug79984.phpt57
-rw-r--r--ext/zlib/tests/bug48725_2.phpt15
-rw-r--r--ext/zlib/zlib_filter.c2
-rw-r--r--main/streams/streams.c2
7 files changed, 148 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index b242d30415..0de562eeaf 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ PHP NEWS
. Fixed bug #80393 (Build of PHP extension fails due to configuration gap
with libtool). (kir dot morozov at gmail dot com)
. Fixed bug #80402 (configure filtering out -lpthread). (Nikita)
+ . Fixed bug #77069 (stream filter loses final block of data). (cmb)
- Fileinfo:
. Fixed bug #77961 (finfo_open crafted magic parsing SIGABRT). (cmb)
diff --git a/ext/standard/tests/streams/bug77069.phpt b/ext/standard/tests/streams/bug77069.phpt
new file mode 100644
index 0000000000..ec78ac25c5
--- /dev/null
+++ b/ext/standard/tests/streams/bug77069.phpt
@@ -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
diff --git a/ext/standard/tests/streams/bug77080.phpt b/ext/standard/tests/streams/bug77080.phpt
new file mode 100644
index 0000000000..feb20656d6
--- /dev/null
+++ b/ext/standard/tests/streams/bug77080.phpt
@@ -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)
diff --git a/ext/standard/tests/streams/bug79984.phpt b/ext/standard/tests/streams/bug79984.phpt
new file mode 100644
index 0000000000..7126458fff
--- /dev/null
+++ b/ext/standard/tests/streams/bug79984.phpt
@@ -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
diff --git a/ext/zlib/tests/bug48725_2.phpt b/ext/zlib/tests/bug48725_2.phpt
new file mode 100644
index 0000000000..168afd8d3d
--- /dev/null
+++ b/ext/zlib/tests/bug48725_2.phpt
@@ -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
diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c
index 3654a140fd..3c19d38016 100644
--- a/ext/zlib/zlib_filter.c
+++ b/ext/zlib/zlib_filter.c
@@ -90,7 +90,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_stream_bucket_delref(bucket);
/* reset these because despite the error the filter may be used again */
diff --git a/main/streams/streams.c b/main/streams/streams.c
index cf411a1dd3..ab413872e0 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -567,7 +567,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;
}