Skip to content

Commit b3687ad

Browse files
authored
gh-126876: Fix socket internal_select() for large timeout (#126968)
If the timeout is larger than INT_MAX, replace it with INT_MAX, in the poll() code path. Add an unit test.
1 parent d6b3e78 commit b3687ad

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
@@ -5132,6 +5132,33 @@ def _testRecv(self):
51325132
# send data: recv() will no longer block
51335133
self.cli.sendall(MSG)
51345134

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

51365163
class FileObjectClassTestCase(SocketConnectedTest):
51375164
"""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)