Fix GH-10406: feof() behavior change for UNIX based socket resources

This change restores the old behaviour for the server socket streams
that don't support IO. This is now stored in the stream flags so it can
be later used to do some other decisions and possibly introduce some
better error reporting.

Closes GH-10877
This commit is contained in:
Jakub Zelenka 2023-03-18 19:38:01 +00:00
parent dc0171b902
commit e80073d3d2
No known key found for this signature in database
GPG Key ID: 1C0779DC5C0A9DE4
6 changed files with 45 additions and 3 deletions

3
NEWS
View File

@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.2.6
- Streams:
. Fixed bug GH-10406 (feof() behavior change for UNIX based socket
resources). (Jakub Zelenka)
30 Mar 2023, PHP 8.2.5

View File

@ -2429,8 +2429,15 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
if (sslsock->s.socket == -1) {
alive = 0;
} else if ((!sslsock->ssl_active && value == 0 && ((MSG_DONTWAIT != 0) || !sslsock->s.is_blocked)) ||
php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
} else if (
(
!sslsock->ssl_active &&
value == 0 &&
!(stream->flags & PHP_STREAM_FLAG_NO_IO) &&
((MSG_DONTWAIT != 0) || !sslsock->s.is_blocked)
) ||
php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0
) {
/* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */
/* additionally, we don't use this optimization if SSL is active because in that case, we're not using MSG_DONTWAIT */
if (sslsock->ssl_active) {

View File

@ -0,0 +1,20 @@
--TEST--
GH-10406: feof() behavior change for UNIX based socket resources
--SKIPIF--
<?php
if (!strncasecmp(PHP_OS, 'WIN', 3)) die("skip. Do not run on Windows");
?>
--FILE--
<?php
$socket_path = '/tmp/gh-10406-test.socket';
if (file_exists($socket_path)) {
unlink($socket_path);
}
$socket = stream_socket_server('unix://' . $socket_path);
var_dump(feof($socket));
unlink($socket_path);
?>
--EXPECT--
bool(false)

View File

@ -188,6 +188,8 @@ struct _php_stream_wrapper {
/* Do not close handle except it is explicitly closed by user (e.g. fclose) */
#define PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE 0x200
#define PHP_STREAM_FLAG_NO_IO 0x400
#define PHP_STREAM_FLAG_WAS_WRITTEN 0x80000000
struct _php_stream {

View File

@ -169,6 +169,9 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
failed = true;
}
}
if (!failed) {
stream->flags |= PHP_STREAM_FLAG_NO_IO;
}
}
}
} zend_catch {

View File

@ -337,7 +337,14 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
if (sock->socket == -1) {
alive = 0;
} else if ((value == 0 && ((MSG_DONTWAIT != 0) || !sock->is_blocked)) || php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
} else if (
(
value == 0 &&
!(stream->flags & PHP_STREAM_FLAG_NO_IO) &&
((MSG_DONTWAIT != 0) || !sock->is_blocked)
) ||
php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0
) {
/* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */
#ifdef PHP_WIN32
int ret;