Skip to content

Commit 059114c

Browse files
[3.13] gh-126876: Fix socket internal_select() for large timeout (GH-126968) (#127002)
gh-126876: Fix socket internal_select() for large timeout (GH-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 cab2ef5 commit 059114c

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

Lib/test/test_socket.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5126,6 +5126,39 @@ 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+
if _testcapi is not None:
5134+
large_timeout = _testcapi.INT_MAX + 1
5135+
else:
5136+
large_timeout = 2147483648
5137+
5138+
# test recv() with large timeout
5139+
conn, addr = self.serv.accept()
5140+
self.addCleanup(conn.close)
5141+
try:
5142+
conn.settimeout(large_timeout)
5143+
except OverflowError:
5144+
# On Windows, settimeout() fails with OverflowError, whereas
5145+
# we want to test recv(). Just give up silently.
5146+
return
5147+
msg = conn.recv(len(MSG))
5148+
5149+
def _testLargeTimeout(self):
5150+
# test sendall() with large timeout
5151+
if _testcapi is not None:
5152+
large_timeout = _testcapi.INT_MAX + 1
5153+
else:
5154+
large_timeout = 2147483648
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+
51295162

51305163
class FileObjectClassTestCase(SocketConnectedTest):
51315164
"""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)