php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #78375 stream_set_option method of stream wrapper is now called inside require()
Submitted: 2019-08-05 15:55 UTC Modified: 2019-08-08 08:20 UTC
From: mail at ciaranmcnulty dot com Assigned:
Status: Verified Package: Streams related
PHP Version: 7.4.0beta1 OS: Debian Slim (docker)
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2019-08-05 15:55 UTC] mail at ciaranmcnulty dot com
Description:
------------
Any `require` that is done through a protocol with a wrapper, now calls `stream_set_option` on the stream wrapper.

Because a stream wrapper doesn't have an interface, a class could not yet implement this method and therefore cause a fatal error.

The option being set is not one of the listed constants (STREAM_OPTION_BLOCKING, STREAM_OPTION_READ_TIMEOUT, STREAM_OPTION_WRITE_BUFFER), rather it is integer 2

Test script:
---------------
class StreamWrapper
{
    public function stream_open($path, $mode, $options, &$opened_path)
    {
        return true;
    }

    public function stream_stat() { return stat(__FILE__); }

    public function stream_read($count) { return ''; }

    public function stream_eof() { return true; }
}

stream_wrapper_register('test', StreamWrapper::class);

require_once('test://foo');

Expected result:
----------------
No output

Actual result:
--------------
Warning: require_once(): StreamWrapper::stream_set_option is not implemented!

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-08-05 16:00 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2019-08-05 16:00 UTC] cmb@php.net
Confirmed: <https://3v4l.org/QjgOW>
 [2019-08-05 17:15 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem
 [2019-08-05 17:15 UTC] cmb@php.net
Well, this is a deliberate BC break caused by an optimization[1],
and as such not a bug.  However, this change is not documented in
UPGRADING, and indeed PHP_STREAM_OPTION_READ_BUFFER (the option
with value 2) is missing from the PHP manual.

[1] <http://git.php.net/?p=php-src.git;a=commit;h=a986e70991057785cd3e5f4235215cb933351b4d>
 [2019-08-06 14:21 UTC] mail at ciaranmcnulty dot com
This is indeed a docs problem! For some reason I hadn’t realised it is just a Warning
 [2019-08-08 08:20 UTC] nikic@php.net
Upgrading note added in https://github.com/php/php-src/commit/8a4171ac457c048e1b05b2d9fc9b74f4816272a0. I considered adding a special hack to hide the warning for this case, but overall I feel it would do more harm than good. Custom stream wrapper implementations aren't exactly super common, so I'd err on the side of consistent behavior here.
 [2019-10-01 14:54 UTC] mail at ciaranmcnulty dot com
Just as a note the example at https://www.php.net/manual/en/stream.streamwrapper.example-1.php doesn't implement this method
 [2020-01-08 14:52 UTC] bkfake-php at yahoo dot com
More documentation issues:

stream_set_option (https://www.php.net/manual/en/streamwrapper.stream-set-option.php)
makes no mention of STREAM_OPTION_READ_BUFFER

stream_set_option documentation doesn't describe what STREAM_BUFFER_NONE and STREAM_BUFFER_FULL designate / how they should be handled  (as the previous comment mentions there is no example implementation)

stream constants documentation (https://www.php.net/manual/en/stream.constants.php) does not list any of these constants
STREAM_OPTION_BLOCKING
STREAM_OPTION_READ_TIMEOUT
STREAM_OPTION_READ_BUFFER
STREAM_OPTION_WRITE_BUFFER
STREAM_BUFFER_NONE
STREAM_BUFFER_FULL

In my attempt to find libraries that implement read/write buffer I've found broken implementations such as

case STREAM_OPTION_WRITE_BUFFER:
    return stream_set_write_buffer($this->fp, $arg1);
case STREAM_OPTION_READ_BUFFER:
    return stream_set_read_buffer($this->fp, $arg1);

This is broken on multiple levels  (passing $arg1 rather than $arg2 / assumes that stream_set_(read|write)_buffer return boolean [they do not] / otherwise ignoring $arg1's value)


-----

possibly related?:
I'm using a streamWrapper to inject "declare(ticks=1);" on the fly for a debugger/profiler...
in php 7.4 it appears that `require` only reads the number of bytes that stream_stat reports/returns...  Even though stream_read is returning the entire buffer...  This results in "PHP Parse error:  syntax error, unexpected end of file"
increasing $stats['size'] to account for the injected string length solves this...     
Could this be READ_BUFFER NONE/FULL related
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Nov 30 17:01:23 2020 UTC