https://github.com/python/cpython/commit/b3687ad454c4ac54c8599a10f3ace8a13ca48915
commit: b3687ad454c4ac54c8599a10f3ace8a13ca48915
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2024-11-19T09:08:42+01:00
summary:
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.
files:
M Lib/test/test_socket.py
M Modules/socketmodule.c
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index dc8a4a44f37e65..7b3914f30e5f52 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -5132,6 +5132,33 @@ def _testRecv(self):
# send data: recv() will no longer block
self.cli.sendall(MSG)
+ def testLargeTimeout(self):
+ # gh-126876: Check that a timeout larger than INT_MAX is replaced with
+ # INT_MAX in the poll() code path. The following assertion must not
+ # fail: assert(INT_MIN <= ms && ms <= INT_MAX).
+ large_timeout = _testcapi.INT_MAX + 1
+
+ # test recv() with large timeout
+ conn, addr = self.serv.accept()
+ self.addCleanup(conn.close)
+ try:
+ conn.settimeout(large_timeout)
+ except OverflowError:
+ # On Windows, settimeout() fails with OverflowError, whereas
+ # we want to test recv(). Just give up silently.
+ return
+ msg = conn.recv(len(MSG))
+
+ def _testLargeTimeout(self):
+ # test sendall() with large timeout
+ large_timeout = _testcapi.INT_MAX + 1
+ self.cli.connect((HOST, self.port))
+ try:
+ self.cli.settimeout(large_timeout)
+ except OverflowError:
+ return
+ self.cli.sendall(MSG)
+
class FileObjectClassTestCase(SocketConnectedTest):
"""Unit tests for the object returned by socket.makefile()
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 2764bd6e2b2a47..06be822c9555f9 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -810,7 +810,9 @@ internal_select(PySocketSockObject *s, int writing,
PyTime_t interval,
/* s->sock_timeout is in seconds, timeout in ms */
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
- assert(ms <= INT_MAX);
+ if (ms > INT_MAX) {
+ ms = INT_MAX;
+ }
/* On some OSes, typically BSD-based ones, the timeout parameter of the
poll() syscall, when negative, must be exactly INFTIM, where defined,
@@ -822,6 +824,7 @@ internal_select(PySocketSockObject *s, int writing,
PyTime_t interval,
ms = -1;
#endif
}
+ assert(INT_MIN <= ms && ms <= INT_MAX);
Py_BEGIN_ALLOW_THREADS;
n = poll(&pollfd, 1, (int)ms);
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]