https://github.com/python/cpython/commit/82b92e3cd180723a354cdeb0f0f1d593f1b5eb0d
commit: 82b92e3cd180723a354cdeb0f0f1d593f1b5eb0d
branch: main
author: Priyanshu Singh <[email protected]>
committer: vstinner <[email protected]>
date: 2026-02-13T16:35:08+01:00
summary:

gh-143637: Fix re-entrant mutation of ancillary data in socket.sendmsg() 
(#143892)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Victor Stinner <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst
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 934b7137096bc0..3806ad988db214 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -2222,6 +2222,24 @@ def test_addressinfo_enum(self):
                 source=_socket)
         enum._test_simple_enum(CheckedAddressInfo, socket.AddressInfo)
 
+    @unittest.skipUnless(hasattr(socket.socket, "sendmsg"),"sendmsg not 
supported")
+    def test_sendmsg_reentrant_ancillary_mutation(self):
+
+        class Mut:
+            def __index__(self):
+                seq.clear()
+                return 0
+
+        seq = [
+            (socket.SOL_SOCKET, Mut(), b'x'),
+            (socket.SOL_SOCKET, 0, b'x'),
+        ]
+
+        left, right = socket.socketpair()
+        self.addCleanup(left.close)
+        self.addCleanup(right.close)
+        self.assertRaises(OSError, left.sendmsg, [b'x'], seq)
+
 
 @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
 class BasicCANTest(unittest.TestCase):
diff --git 
a/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst 
b/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst
new file mode 100644
index 00000000000000..cbb21194d5b387
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst
@@ -0,0 +1 @@
+Fixed a crash in socket.sendmsg() that could occur if ancillary data is 
mutated re-entrantly during argument parsing.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index ee78ad01598262..d4df40c78e8a4f 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -4983,11 +4983,13 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, 
PyObject *data_arg,
     if (cmsg_arg == NULL)
         ncmsgs = 0;
     else {
-        if ((cmsg_fast = PySequence_Fast(cmsg_arg,
-                                         "sendmsg() argument 2 must be an "
-                                         "iterable")) == NULL)
+        cmsg_fast = PySequence_Tuple(cmsg_arg);
+        if (cmsg_fast == NULL) {
+            PyErr_SetString(PyExc_TypeError,
+                "sendmsg() argument 2 must be an iterable");
             goto finally;
-        ncmsgs = PySequence_Fast_GET_SIZE(cmsg_fast);
+        }
+        ncmsgs = PyTuple_GET_SIZE(cmsg_fast);
     }
 
 #ifndef CMSG_SPACE
@@ -5007,8 +5009,9 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, 
PyObject *data_arg,
     controllen = controllen_last = 0;
     while (ncmsgbufs < ncmsgs) {
         size_t bufsize, space;
+        PyObject *item = PyTuple_GET_ITEM(cmsg_fast, ncmsgbufs);
 
-        if (!PyArg_Parse(PySequence_Fast_GET_ITEM(cmsg_fast, ncmsgbufs),
+        if (!PyArg_Parse(item,
                          "(iiy*):[sendmsg() ancillary data items]",
                          &cmsgs[ncmsgbufs].level,
                          &cmsgs[ncmsgbufs].type,

_______________________________________________
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]

Reply via email to