Edit report at https://bugs.php.net/bug.php?id=79072&edit=1
ID: 79072
Updated by: cmb@php.net
Reported by: morozov at tut dot by
Summary: If passed via a stream processor, the included file
contents get corrupted
-Status: Open
+Status: Feedback
Type: Bug
Package: Streams related
Operating System: Linux
PHP Version: 7.4.1
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
It seems the original issue has been resolved, hasn't it?
> Looking at the code, it treats any non-array return value as the> stat failing...
Yeah, but I think we should leave documentation as is, and have to
leave implementation as is until next major at least.
Previous Comments:
------------------------------------------------------------------------
[2020-01-17 11:56:56] nikic@php.net
> You suggested to return false from stream_stat(), however the documentation says it should
> return an array. Is it safe to return false and be sure the return type of array
> won't be strictly enforced in a future PHP version? Returning an empty array seems to work as
> well.
Looking at the code, it treats any non-array return value as the stat failing...
------------------------------------------------------------------------
[2020-01-06 22:30:54] morozov at tut dot by
> Your stream filter solution should also work fine though as long as you return false from
> stream_stat() (or explicitly adjust the length).
Thank you for the recommendation. It worked.
The approach of using a temporary stream seems to be not that easy to integrate into the existing
code of php-vcr since its API designed around using php_user_filters while in your
example the entire file content is processed at once (although it indeed looks like a more
reasonable approach for processing included files).
You suggested to return false from stream_stat(), however the documentation says it should return an
array. Is it safe to return false and be sure the return type of array won't be
strictly enforced in a future PHP version? Returning an empty array seems to work as well.
------------------------------------------------------------------------
[2020-01-06 20:02:26] nikic@php.net
> How can this be done? Removing either of the stream_stat() and url_stat() methods from the
> stream wrapper makes PHP unable to include the file:
You can do this by returning false from stream_stat(). You'll likely only want to do that if
the stream was opened for include.
> Not sure I understand the suggestion. The purpose of this code is to register a file://
> protocol handler that would change the file contents on the fly w/o having to modify the code that
> includes or reads those files. How does simply open a php://temp stream solve this problem?
It so happens that I've recently been dealing with on-the-fly include transforms as well, and
the solution I adopted looks like this: https://github.com/nikic/include-interceptor/blob/8cffd8f75212eed30cbeaaf8ee8749d1b88d5c7f/src/Interceptor.php#L44-L47
That is, the transformed file contents are written to a php://temp stream (php://memory would
probably also work) and that is then used as the file resource in the stream wrapper.
Your stream filter solution should also work fine though as long as you return false from
stream_stat() (or explicitly adjust the length).
------------------------------------------------------------------------
[2020-01-06 19:55:54] morozov at tut dot by
> You are modifying the stream contents, but still report the old file size in your stream_stat()
> override.
This is true.
> You need to adjust the size there to account for the modification made by the stream filter
Not sure if that's possible given that the filtering is done by the underlying stream filter.
We don't know the resulting file size upfront.
> or else report the stream as un-statable.
How can this be done? Removing either of the stream_stat() and url_stat() methods from the stream
wrapper makes PHP unable to include the file:
$ php run.php # with stream_stat removed
Warning: include(): StreamProcessor::stream_stat is not implemented! in run.php on line 13
Call Stack:
0.0001 472552 1. {main}() run.php:0
$ php run.php # with url_stat removed
Warning: file_exists(): StreamProcessor::url_stat is not implemented! in StreamProcessor.php on line
57
Call Stack:
0.0001 472552 1. {main}() run.php:0
0.0004 497232 2. StreamProcessor->stream_open() run.php:13
0.0004 497232 3. file_exists() StreamProcessor.php:57
Warning: include(IncludeFile.php): failed to open stream: "StreamProcessor::stream_open"
call failed in run.php on line 13
Call Stack:
0.0001 472552 1. {main}() run.php:0
Warning: include(): Failed opening 'IncludeFile.php' for inclusion
(include_path='.:') in run.php on line 13
Call Stack:
0.0001 472552 1. {main}() run.php:0
> Your use of stream filters here seems unnecessary. I would recommend you to simply open a
> php://temp stream instead of dealing with that.
Not sure I understand the suggestion. The purpose of this code is to register a file:// protocol
handler that would change the file contents on the fly w/o having to modify the code that includes
or reads those files. How does simply open a php://temp stream solve this problem?
------------------------------------------------------------------------
[2020-01-06 18:04:39] nikic@php.net
I'd say the code is incorrect. You are modifying the stream contents, but still report the old
file size in your stream_stat() override. You need to adjust the size there to account for the
modification made by the stream filter, or else report the stream as un-statable.
PS: Your use of stream filters here seems unnecessary. I would recommend you to simply open a
php://temp stream instead of dealing with that.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=79072
--
Edit this bug report at https://bugs.php.net/bug.php?id=79072&edit=1