[3.11] bpo-35191: Fix unexpected integer truncation in socket.setblocking() (GH-10415)

On platforms with 64-bit long, socket.setblocking(x) treated all x
which lower 32 bits are zero as False due to integer truncation.

Reported by ubsan.
This commit is contained in:
Alexey Izbyshev 2023-12-01 18:44:03 +03:00 committed by GitHub
parent eb3c0dc667
commit 0443f926be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 9 additions and 5 deletions

View file

@ -4705,10 +4705,10 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
self.skipTest('needs UINT_MAX < ULONG_MAX') self.skipTest('needs UINT_MAX < ULONG_MAX')
self.serv.setblocking(False) self.serv.setblocking(False)
self.assertEqual(self.serv.gettimeout(), 0.0) self.assert_sock_timeout(self.serv, 0.0)
self.serv.setblocking(_testcapi.UINT_MAX + 1) self.serv.setblocking(_testcapi.UINT_MAX + 1)
self.assertIsNone(self.serv.gettimeout()) self.assert_sock_timeout(self.serv, None)
_testSetBlocking_overflow = support.cpython_only(_testSetBlocking) _testSetBlocking_overflow = support.cpython_only(_testSetBlocking)

View file

@ -0,0 +1,2 @@
Fix unexpected integer truncation in :meth:`socket.setblocking` which caused
it to interpret multiples of ``2**32`` as ``False``.

View file

@ -2815,12 +2815,14 @@ For IP sockets, the address info is a pair (hostaddr, port).");
static PyObject * static PyObject *
sock_setblocking(PySocketSockObject *s, PyObject *arg) sock_setblocking(PySocketSockObject *s, PyObject *arg)
{ {
long block; long value;
int block;
block = PyLong_AsLong(arg); value = PyLong_AsLong(arg);
if (block == -1 && PyErr_Occurred()) if (value == -1 && PyErr_Occurred())
return NULL; return NULL;
block = (value != 0);
s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0); s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0);
if (internal_setblocking(s, block) == -1) { if (internal_setblocking(s, block) == -1) {
return NULL; return NULL;