Skip to content

Commit b49e902

Browse files
[3.12] gh-126876: Fix socket internal_select() for large timeout (GH-126968) (#127003)
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 c40656e commit b49e902

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

Lib/test/test_socket.py

+30
Original file line numberDiff line numberDiff line change
@@ -5059,6 +5059,36 @@ def _testRecv(self):
50595059
# send data: recv() will no longer block
50605060
self.cli.sendall(MSG)
50615061

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

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

Modules/socketmodule.c

+4-1
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)