Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix error handling in Stream::getContents() #294

Closed
wants to merge 3 commits into from

Conversation

odan
Copy link

@odan odan commented Nov 10, 2023

The current implementation of stream_get_contents() swallows errors, leading to issues like symfony/symfony#52490, where errors reported by the stream layer aren't propagated to user-land.

This is even in the C source:
https://github.com/php/php-src/blob/311cae03e730c76aed343312319ed8cf1c37ade0/main/streams/streams.c#L1512

Proposed Solution

To address the issue, @nicolas-grekas proposes replacing the usage of stream_get_contents() with fread(). This change will ensure that errors are not concealed, and they will be thrown as expected.

Using fread(), should fix this issue.

See here: Nyholm/psr7#252

Thanks to @nicolas-grekas

@nicolas-grekas
Copy link

Thanks for the follow up. Please don't merge now as I might change the patch a bit depending on my tests.

@nicolas-grekas
Copy link

Upstream PR updated, see Nyholm/psr7#252 (comment)

@odan
Copy link
Author

odan commented Nov 10, 2023

@nicolas-grekas Ok thanks, we are waiting.

@nicolas-grekas
Copy link

Merged upstream, you can now sync the patch.

src/Stream.php Outdated
while (!feof($this->stream)) {
$result = @fread($this->stream, 16372);
if ($result === false) {
throw new RuntimeException('Unable to read from stream: ' . (error_get_last()['message'] ?? ''));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas this code checks for false return value as well... (ref Nyholm/psr7#252 (review))

@l0gicgate l0gicgate added this to the 1.7.0 milestone Dec 12, 2023
@l0gicgate
Copy link
Member

@odan it appears CI is failing on 8.2. The changes look good to me otherwise

});

try {
$contents = stream_get_contents($this->stream);
Copy link

@piotr-cz piotr-cz Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value $this->resource in fact may be null in following edge case:

class StreamExtended extends Stream
{
    public function brokenMethod()
    {
        // This sets $this->resource to null...
        $this->detach();
        // ...and in effect this calls stream_get_contents with null parameter
        $this->getStreamContents();
    }
}

I see folowing possible solutions:

  • move method body exactly where the $contents = $this->getStreamContents(); was
  • throw an Exception then $this->resource === null
  • force stream to be a type of resource by changing new method's signature to protected static getStreamContents(resource $stream): string;

@odan odan closed this Apr 27, 2024
@odan odan deleted the fix-get-contents branch April 27, 2024 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants