]> granicus.if.org Git - php/commitdiff
Fixed bug #78506
authorNikita Popov <nikita.ppv@gmail.com>
Wed, 11 Sep 2019 08:27:32 +0000 (10:27 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 11 Sep 2019 08:27:32 +0000 (10:27 +0200)
NEWS
ext/standard/tests/streams/bug78506.phpt [new file with mode: 0644]
main/streams/streams.c

diff --git a/NEWS b/NEWS
index 9563d6c3681de4739c0d66f865f137ac53efe436..95f229afc71a68dbde64f1fb18914baa569acd5d 100644 (file)
--- 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 (file)
index 0000000..869fa2a
--- /dev/null
@@ -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)
index 566cdcde080650d9e29b5cd509f55f6e8cd44678..aef1ebe7626baf3b72b07c9d4d0b1b85db386552 100644 (file)
@@ -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) {