Skip to content

Commit c0cf208

Browse files
committed
ext/sockets: further timeout handling changes.
close GH-17210
1 parent 4d140f7 commit c0cf208

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ PHP NEWS
7171
(David Carlier)
7272
. Added TCP_FUNCTION_BLK to change the TCP stack algorithm on FreeBSD.
7373
(David Carlier)
74+
. socket_set_option() catches possible overflow with SO_RCVTIMEO/SO_SNDTIMEO
75+
with timeout setting on windows. (David Carlier)
7476

7577
- Standard:
7678
. Fixed crypt() tests on musl when using --with-external-libcrypt

ext/sockets/sockets.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,8 @@ PHP_FUNCTION(socket_get_option)
16461646
struct timeval tv;
16471647
#ifdef PHP_WIN32
16481648
DWORD timeout = 0;
1649+
#else
1650+
struct timeval timeout;
16491651
#endif
16501652
socklen_t optlen;
16511653
php_socket *php_sock;
@@ -1749,23 +1751,19 @@ PHP_FUNCTION(socket_get_option)
17491751

17501752
case SO_RCVTIMEO:
17511753
case SO_SNDTIMEO:
1752-
#ifndef PHP_WIN32
1753-
optlen = sizeof(tv);
1754-
1755-
if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&tv, &optlen) != 0) {
1756-
PHP_SOCKET_ERROR(php_sock, "Unable to retrieve socket option", errno);
1757-
RETURN_FALSE;
1758-
}
1759-
#else
17601754
optlen = sizeof(timeout);
17611755

17621756
if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&timeout, &optlen) != 0) {
17631757
PHP_SOCKET_ERROR(php_sock, "Unable to retrieve socket option", errno);
17641758
RETURN_FALSE;
17651759
}
17661760

1761+
#ifndef PHP_WIN32
1762+
tv.tv_sec = timeout.tv_sec;
1763+
tv.tv_usec = timeout.tv_usec;
1764+
#else
17671765
tv.tv_sec = timeout ? (long)(timeout / 1000) : 0;
1768-
tv.tv_usec = timeout ? (long)((timeout * 1000) % 1000000) : 0;
1766+
tv.tv_usec = timeout ? (long)((timeout % 1000) * 1000) : 0;
17691767
#endif
17701768

17711769
array_init(return_value);
@@ -2046,7 +2044,24 @@ PHP_FUNCTION(socket_set_option)
20462044
optlen = sizeof(tv);
20472045
opt_ptr = &tv;
20482046
#else
2049-
timeout = Z_LVAL_P(sec) * 1000 + Z_LVAL_P(usec) / 1000;
2047+
if (valsec < 0 || valsec > ULONG_MAX / 1000) {
2048+
zend_argument_value_error(4, "\"%s\" must be between 0 and %u", sec_key, (ULONG_MAX / 1000));
2049+
RETURN_THROWS();
2050+
}
2051+
2052+
timeout = valsec * 1000;
2053+
2054+
2055+
/*
2056+
* We deliberately throw if (valusec / 1000) > ULONG_MAX, treating it as a programmer error.
2057+
* On Windows, ULONG_MAX = 2^32, unlike ZEND_LONG_MAX = 2^63.
2058+
*/
2059+
if (valusec < 0 || timeout > ULONG_MAX - (valusec / 1000)) {
2060+
zend_argument_value_error(4, "\"%s\" must be between 0 and %u", usec_key, (DWORD)(ULONG_MAX - (valusec / 1000)));
2061+
RETURN_THROWS();
2062+
}
2063+
2064+
timeout += valusec / 1000;
20502065
optlen = sizeof(timeout);
20512066
opt_ptr = &timeout;
20522067
#endif

0 commit comments

Comments
 (0)