Skip to content

Commit f693004

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 190d710 commit f693004

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
@@ -5126,6 +5126,33 @@ def _testRecv(self):
51265126
# send data: recv() will no longer block
51275127
self.cli.sendall(MSG)
51285128

5129+
def testLargeTimeout(self):
5130+
# gh-126876: Check that a timeout larger than INT_MAX is replaced with
5131+
# INT_MAX in the poll() code path. The following assertion must not
5132+
# fail: assert(INT_MIN <= ms && ms <= INT_MAX).
5133+
large_timeout = _testcapi.INT_MAX + 1
5134+
5135+
# test recv() with large timeout
5136+
conn, addr = self.serv.accept()
5137+
self.addCleanup(conn.close)
5138+
try:
5139+
conn.settimeout(large_timeout)
5140+
except OverflowError:
5141+
# On Windows, settimeout() fails with OverflowError, whereas
5142+
# we want to test recv(). Just give up silently.
5143+
return
5144+
msg = conn.recv(len(MSG))
5145+
5146+
def _testLargeTimeout(self):
5147+
# test sendall() with large timeout
5148+
large_timeout = _testcapi.INT_MAX + 1
5149+
self.cli.connect((HOST, self.port))
5150+
try:
5151+
self.cli.settimeout(large_timeout)
5152+
except OverflowError:
5153+
return
5154+
self.cli.sendall(MSG)
5155+
51295156

51305157
class FileObjectClassTestCase(SocketConnectedTest):
51315158
"""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
@@ -810,7 +810,9 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
810810

811811
/* s->sock_timeout is in seconds, timeout in ms */
812812
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
813-
assert(ms <= INT_MAX);
813+
if (ms > INT_MAX) {
814+
ms = INT_MAX;
815+
}
814816

815817
/* On some OSes, typically BSD-based ones, the timeout parameter of the
816818
poll() syscall, when negative, must be exactly INFTIM, where defined,
@@ -822,6 +824,7 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
822824
ms = -1;
823825
#endif
824826
}
827+
assert(INT_MIN <= ms && ms <= INT_MAX);
825828

826829
Py_BEGIN_ALLOW_THREADS;
827830
n = poll(&pollfd, 1, (int)ms);

0 commit comments

Comments
 (0)