Skip to content

Commit 309bacd

Browse files
miss-islingtonpriyanshu2282-cyberblurb-it[bot]vstinnerpicnixz
authored
[3.13] gh-143637: Fix re-entrant mutation of ancillary data in socket.sendmsg() (GH-143892) (#144785)
gh-143637: Fix re-entrant mutation of ancillary data in socket.sendmsg() (GH-143892) (cherry picked from commit 82b92e3) Co-authored-by: Priyanshu Singh <priyanshu2282@gmail.com> 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 99a4e55 commit 309bacd

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
@@ -2165,6 +2165,24 @@ def test_addressinfo_enum(self):
21652165
source=_socket)
21662166
enum._test_simple_enum(CheckedAddressInfo, socket.AddressInfo)
21672167

2168+
@unittest.skipUnless(hasattr(socket.socket, "sendmsg"),"sendmsg not supported")
2169+
def test_sendmsg_reentrant_ancillary_mutation(self):
2170+
2171+
class Mut:
2172+
def __index__(self):
2173+
seq.clear()
2174+
return 0
2175+
2176+
seq = [
2177+
(socket.SOL_SOCKET, Mut(), b'x'),
2178+
(socket.SOL_SOCKET, 0, b'x'),
2179+
]
2180+
2181+
left, right = socket.socketpair()
2182+
self.addCleanup(left.close)
2183+
self.addCleanup(right.close)
2184+
self.assertRaises(OSError, left.sendmsg, [b'x'], seq)
2185+
21682186

21692187
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
21702188
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
@@ -4737,11 +4737,13 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)
47374737
if (cmsg_arg == NULL)
47384738
ncmsgs = 0;
47394739
else {
4740-
if ((cmsg_fast = PySequence_Fast(cmsg_arg,
4741-
"sendmsg() argument 2 must be an "
4742-
"iterable")) == NULL)
4740+
cmsg_fast = PySequence_Tuple(cmsg_arg);
4741+
if (cmsg_fast == NULL) {
4742+
PyErr_SetString(PyExc_TypeError,
4743+
"sendmsg() argument 2 must be an iterable");
47434744
goto finally;
4744-
ncmsgs = PySequence_Fast_GET_SIZE(cmsg_fast);
4745+
}
4746+
ncmsgs = PyTuple_GET_SIZE(cmsg_fast);
47454747
}
47464748

47474749
#ifndef CMSG_SPACE
@@ -4761,8 +4763,9 @@ sock_sendmsg(PySocketSockObject *s, PyObject *args)
47614763
controllen = controllen_last = 0;
47624764
while (ncmsgbufs < ncmsgs) {
47634765
size_t bufsize, space;
4766+
PyObject *item = PyTuple_GET_ITEM(cmsg_fast, ncmsgbufs);
47644767

4765-
if (!PyArg_Parse(PySequence_Fast_GET_ITEM(cmsg_fast, ncmsgbufs),
4768+
if (!PyArg_Parse(item,
47664769
"(iiy*):[sendmsg() ancillary data items]",
47674770
&cmsgs[ncmsgbufs].level,
47684771
&cmsgs[ncmsgbufs].type,

0 commit comments

Comments
 (0)