Skip to content

Commit 82b92e3

Browse files
priyanshu2282-cyberblurb-it[bot]vstinnerpicnixz
authored
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 <vstinner@python.org> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
1 parent 945bf8c commit 82b92e3

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

Lib/test/test_socket.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,6 +2222,24 @@ def test_addressinfo_enum(self):
22222222
source=_socket)
22232223
enum._test_simple_enum(CheckedAddressInfo, socket.AddressInfo)
22242224

2225+
@unittest.skipUnless(hasattr(socket.socket, "sendmsg"),"sendmsg not supported")
2226+
def test_sendmsg_reentrant_ancillary_mutation(self):
2227+
2228+
class Mut:
2229+
def __index__(self):
2230+
seq.clear()
2231+
return 0
2232+
2233+
seq = [
2234+
(socket.SOL_SOCKET, Mut(), b'x'),
2235+
(socket.SOL_SOCKET, 0, b'x'),
2236+
]
2237+
2238+
left, right = socket.socketpair()
2239+
self.addCleanup(left.close)
2240+
self.addCleanup(right.close)
2241+
self.assertRaises(OSError, left.sendmsg, [b'x'], seq)
2242+
22252243

22262244
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
22272245
class BasicCANTest(unittest.TestCase):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a crash in socket.sendmsg() that could occur if ancillary data is mutated re-entrantly during argument parsing.

Modules/socketmodule.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4983,11 +4983,13 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg,
49834983
if (cmsg_arg == NULL)
49844984
ncmsgs = 0;
49854985
else {
4986-
if ((cmsg_fast = PySequence_Fast(cmsg_arg,
4987-
"sendmsg() argument 2 must be an "
4988-
"iterable")) == NULL)
4986+
cmsg_fast = PySequence_Tuple(cmsg_arg);
4987+
if (cmsg_fast == NULL) {
4988+
PyErr_SetString(PyExc_TypeError,
4989+
"sendmsg() argument 2 must be an iterable");
49894990
goto finally;
4990-
ncmsgs = PySequence_Fast_GET_SIZE(cmsg_fast);
4991+
}
4992+
ncmsgs = PyTuple_GET_SIZE(cmsg_fast);
49914993
}
49924994

49934995
#ifndef CMSG_SPACE
@@ -5007,8 +5009,9 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg,
50075009
controllen = controllen_last = 0;
50085010
while (ncmsgbufs < ncmsgs) {
50095011
size_t bufsize, space;
5012+
PyObject *item = PyTuple_GET_ITEM(cmsg_fast, ncmsgbufs);
50105013

5011-
if (!PyArg_Parse(PySequence_Fast_GET_ITEM(cmsg_fast, ncmsgbufs),
5014+
if (!PyArg_Parse(item,
50125015
"(iiy*):[sendmsg() ancillary data items]",
50135016
&cmsgs[ncmsgbufs].level,
50145017
&cmsgs[ncmsgbufs].type,

0 commit comments

Comments
 (0)