summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-09-11 10:27:32 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-09-11 10:27:32 +0200
commit11f3e24190fa45689c8ccaeea54a28db6752092e (patch)
tree4bc2ed82e2fc21f7dfcfe74fd11e4208a4d8b346
parent0a24cd4e7c38d7565905152d4286ef0404d9d591 (diff)
downloadphp-git-11f3e24190fa45689c8ccaeea54a28db6752092e.tar.gz
Fixed bug #78506
-rw-r--r--NEWS4
-rw-r--r--ext/standard/tests/streams/bug78506.phpt27
-rw-r--r--main/streams/streams.c34
3 files changed, 47 insertions, 18 deletions
diff --git a/NEWS b/NEWS
index 9563d6c368..95f229afc7 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ PHP NEWS
. Fixed bug #78510 (Partially uninitialized buffer returned by
sodium_crypto_generichash_init()). (Frank Denis, cmb)
+- Standard:
+ . Fixed bug #78506 (Error in a php_user_filter::filter() is not reported).
+ (Nikita)
+
05 Sep 2019, PHP 7.4.0RC1
- Core:
diff --git a/ext/standard/tests/streams/bug78506.phpt b/ext/standard/tests/streams/bug78506.phpt
new file mode 100644
index 0000000000..869fa2a8ff
--- /dev/null
+++ b/ext/standard/tests/streams/bug78506.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #78506: Error in a php_user_filter::filter() is not reported
+--FILE--
+<?php
+
+class MyFilter extends php_user_filter {
+ public function filter($in, $out, &$consumed, $closing)
+ {
+ stream_bucket_make_writeable($in);
+ return PSFS_ERR_FATAL;
+ }
+
+}
+
+stream_filter_register('filtername', MyFilter::class);
+
+$source_resource = fopen('php://memory', 'rb+');
+fwrite($source_resource, 'Test data');
+rewind($source_resource);
+
+stream_filter_prepend($source_resource,'filtername',STREAM_FILTER_READ);
+
+var_dump(stream_copy_to_stream($source_resource, fopen('php://memory', 'wb')));
+
+?>
+--EXPECT--
+bool(false)
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 566cdcde08..aef1ebe762 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -1586,33 +1586,31 @@ PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size
while(1) {
size_t readchunk = sizeof(buf);
ssize_t didread;
+ char *writeptr;
if (maxlen && (maxlen - haveread) < readchunk) {
readchunk = maxlen - haveread;
}
didread = php_stream_read(src, buf, readchunk);
+ if (didread <= 0) {
+ *len = haveread;
+ return didread < 0 ? FAILURE : SUCCESS;
+ }
- if (didread > 0) {
- /* extra paranoid */
- char *writeptr;
-
- towrite = didread;
- writeptr = buf;
- haveread += didread;
-
- while (towrite) {
- ssize_t didwrite = php_stream_write(dest, writeptr, towrite);
- if (didwrite <= 0) {
- *len = haveread - (didread - towrite);
- return FAILURE;
- }
+ towrite = didread;
+ writeptr = buf;
+ haveread += didread;
- towrite -= didwrite;
- writeptr += didwrite;
+ while (towrite) {
+ ssize_t didwrite = php_stream_write(dest, writeptr, towrite);
+ if (didwrite <= 0) {
+ *len = haveread - (didread - towrite);
+ return FAILURE;
}
- } else {
- break;
+
+ towrite -= didwrite;
+ writeptr += didwrite;
}
if (maxlen - haveread == 0) {