Skip to content

Commit

Permalink
Fix GH-10406: feof() behavior change for UNIX based socket resources
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bukka committed Mar 30, 2023
1 parent dc0171b commit e80073d
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 3 deletions.
3 changes: 3 additions & 0 deletions NEWS
Expand Up @@ -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

Expand Down
11 changes: 9 additions & 2 deletions ext/openssl/xp_ssl.c
Expand Up @@ -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) {
Expand Down
20 changes: 20 additions & 0 deletions ext/standard/tests/streams/gh10406.phpt
@@ -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)
2 changes: 2 additions & 0 deletions main/php_streams.h
Expand Up @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions main/streams/transports.c
Expand Up @@ -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 {
Expand Down
9 changes: 8 additions & 1 deletion main/streams/xp_socket.c
Expand Up @@ -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;
Expand Down

0 comments on commit e80073d

Please sign in to comment.