]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-143637: Fix re-entrant mutation of ancillary data in socket.sendmsg() (#143892)
authorPriyanshu Singh <priyanshu2282@gmail.com>
Fri, 13 Feb 2026 15:35:08 +0000 (21:05 +0530)
committerGitHub <noreply@github.com>
Fri, 13 Feb 2026 15:35:08 +0000 (16:35 +0100)
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Lib/test/test_socket.py
Misc/NEWS.d/next/Library/2026-01-17-08-44-25.gh-issue-143637.qyPqDo.rst [new file with mode: 0644]
Modules/socketmodule.c

index 934b7137096bc04d2c2942a665ef51ff19725eea..3806ad988db21465080c4f064ea3f236057d693d 100644 (file)
@@ -2222,6 +2222,24 @@ class GeneralModuleTests(unittest.TestCase):
                 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 (file)
index 0000000..cbb2119
--- /dev/null
@@ -0,0 +1 @@
+Fixed a crash in socket.sendmsg() that could occur if ancillary data is mutated re-entrantly during argument parsing.
index ee78ad01598262b9d12b133af061d7c5f29b27a4..d4df40c78e8a4fad44035f119216bb7f47708ac7 100644 (file)
@@ -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,