Skip to content

Commit e51cc5b

Browse files
vstinnermiss-islington
authored andcommitted
pythongh-126876: Fix socket internal_select() for large timeout (pythonGH-126968)
If the timeout is larger than INT_MAX, replace it with INT_MAX, in the poll() code path. Add an unit test. (cherry picked from commit b3687ad) Co-authored-by: Victor Stinner <[email protected]>
1 parent 126acc1 commit e51cc5b

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

Lib/test/test_socket.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5059,6 +5059,33 @@ def _testRecv(self):
50595059
# send data: recv() will no longer block
50605060
self.cli.sendall(MSG)
50615061

5062+
def testLargeTimeout(self):
5063+
# gh-126876: Check that a timeout larger than INT_MAX is replaced with
5064+
# INT_MAX in the poll() code path. The following assertion must not
5065+
# fail: assert(INT_MIN <= ms && ms <= INT_MAX).
5066+
large_timeout = _testcapi.INT_MAX + 1
5067+
5068+
# test recv() with large timeout
5069+
conn, addr = self.serv.accept()
5070+
self.addCleanup(conn.close)
5071+
try:
5072+
conn.settimeout(large_timeout)
5073+
except OverflowError:
5074+
# On Windows, settimeout() fails with OverflowError, whereas
5075+
# we want to test recv(). Just give up silently.
5076+
return
5077+
msg = conn.recv(len(MSG))
5078+
5079+
def _testLargeTimeout(self):
5080+
# test sendall() with large timeout
5081+
large_timeout = _testcapi.INT_MAX + 1
5082+
self.cli.connect((HOST, self.port))
5083+
try:
5084+
self.cli.settimeout(large_timeout)
5085+
except OverflowError:
5086+
return
5087+
self.cli.sendall(MSG)
5088+
50625089

50635090
class FileObjectClassTestCase(SocketConnectedTest):
50645091
"""Unit tests for the object returned by socket.makefile()

Modules/socketmodule.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,9 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
816816

817817
/* s->sock_timeout is in seconds, timeout in ms */
818818
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
819-
assert(ms <= INT_MAX);
819+
if (ms > INT_MAX) {
820+
ms = INT_MAX;
821+
}
820822

821823
/* On some OSes, typically BSD-based ones, the timeout parameter of the
822824
poll() syscall, when negative, must be exactly INFTIM, where defined,
@@ -828,6 +830,7 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
828830
ms = -1;
829831
#endif
830832
}
833+
assert(INT_MIN <= ms && ms <= INT_MAX);
831834

832835
Py_BEGIN_ALLOW_THREADS;
833836
n = poll(&pollfd, 1, (int)ms);

0 commit comments

Comments
 (0)