Skip to content

Conversation

@KonstantinKuklin
Copy link

Incorrect readable and writable flags for php:// streams

|| !strncasecmp(url, "fd/", 3)
|| !strncasecmp(url, "filter/", 7)
) {
ssb->sb.st_mode |= (S_IREAD | (S_IREAD >> 3) | (S_IREAD >> 6) | S_IWRITE | (S_IWRITE >> 3) | (S_IWRITE >> 6));
Copy link
Member

Choose a reason for hiding this comment

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

I'd use something like S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH here, to avoid the magic shift numbers.

Copy link
Member

Choose a reason for hiding this comment

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

Looking at

if (strpbrk(mode, "wa+")) {
and similar code, I don't think we can unconditionally say that these streams are read+write, it seems that there are also read-only modes.

I'm not really familiar with stream code -- would it be possible to implement fstat rather than stat, where we have access to the underlying stream, to fulfil the purpose here?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, the stream could be open only for read, or only for write or both.
Here I just provide information how the PATH(or sometimes it names URL in code) can be opened.
If u have file example.txt with RW, u should see that the file is able to open for read and for write - this information not related to any your stream to this file path and stream flags.

php-src/main/php_streams.h

Lines 140 to 143 in 9a74b23

/* stat a wrapped stream */
int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb);
/* stat a URL */
int (*url_stat)(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context);

In php_fopen_wrapper wrong comments, I implemented url_stat(path stat) which is I suppose correct for this case.

Copy link
Member

Choose a reason for hiding this comment

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

You're right, my comment about the mode was bogus, it's not relevant here.

However, I think that there might still be some issues with certain stream types. E.g. php://fd will be subject to the read/write mode of the original file descriptor, e.g. php://fd/0 should be read-only and php://fd/1 should be write-only, assuming they are stdin and stdout respectively. Similarly, for php://filter this probably also depends on the readability/writability of the wrapped resource.

Copy link
Author

@KonstantinKuklin KonstantinKuklin May 25, 2019

Choose a reason for hiding this comment

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

Right now I don't know how to provide info about fd and filter, because if u set chmod 666 to /dev/fd/0 will it means php://fd/1 became RW?
If I skip with TODO this two points FD and FILTER can we merge fix for others?

@KonstantinKuklin
Copy link
Author

thank u @nikic, fixed all remarks

TODO implement readable\writable flags for fd/
} else if (!strncasecmp(url, "filter/", sizeof("filter/") - 1)) {
TODO implement readable\writable flags for filter/
} */
Copy link
Member

Choose a reason for hiding this comment

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

Ignoring those cases seems fine for now. I think we might need to return -1 in that case though, to indicate that this is not supported. Can you also add a test for one of those (fd or filter) just so we see what the behavior will be?

}
/* }}} */

static int php_stream_url_stater(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context)
Copy link
Member

Choose a reason for hiding this comment

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

This function still needs to be reindented to tabs.

@phansys
Copy link
Contributor

phansys commented May 27, 2019

Are these changes related to the return value of \SplFileInfo::getSize()? I've executed a test based on this PR and this method is returning 0 regardless the stream's contents:

Test
$file = new \SplFileObject('php://temp');
$file->fwrite('some content');
var_dump($file->getSize()); // prints 0
$fp = fopen($file->getPathname(), 'rb');
$stats = fstat($fp);
fclose($fp);
var_dump($stats['size']); // prints 0

@KonstantinKuklin
Copy link
Author

KonstantinKuklin commented May 27, 2019

@phansys yes
before this PR behavior was https://3v4l.org/91gfq

Fatal error: Uncaught RuntimeException: SplFileInfo::getSize(): stat failed for php://temp in /in/91gfq:5
Stack trace:
#0 /in/91gfq(5): SplFileInfo->getSize()
#1 {main}
thrown in /in/91gfq on line 5

Process exited with code 255.

@phansys
Copy link
Contributor

phansys commented May 27, 2019

Right @KonstantinKuklin, I noticed that fix, thank you so much. I mean, I thought that after these change, the return value of \SplFileInfo::getSize() would be other than 0 when there is content in the stream.

@KonstantinKuklin
Copy link
Author

@phansys I'd say there should be still error message, because SplFileInfo is not about streams, but files. I will double check this behavior, thank you for case with size.

@krakjoe krakjoe requested a review from nikic October 2, 2019 06:22
@krakjoe
Copy link
Member

krakjoe commented Oct 2, 2019

@nikic can you please give this one a final review and probably merge (I think it's all good now) ... ta

@cmb69
Copy link
Member

cmb69 commented Oct 4, 2021

What's the status here? The PR targets PHP-7.2, but would need to target PHP-7.4 or higher.

@cmb69
Copy link
Member

cmb69 commented Dec 28, 2021

I'm closing this PR due to inactivity. @KonstantinKuklin, feel free to rebase onto PHP-8.0 change the target branch accordingly, and re-open. Thanks for your work, anyway! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants