Skip to content

Commit c6a084a

Browse files
authored
gh-143376: validate usages of _interpchannels.ChannelID in _channelid_shared (#146574)
1 parent 488ce0f commit c6a084a

3 files changed

Lines changed: 47 additions & 1 deletion

File tree

‎Lib/test/test_interpreters/test_channels.py‎

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# Raise SkipTest if subinterpreters not supported.
99
_channels = import_helper.import_module('_interpchannels')
1010
from concurrent import interpreters
11-
from test.support import channels
11+
from test.support import channels, force_not_colorized
1212
from .utils import _run_output, TestBase
1313

1414

@@ -34,6 +34,39 @@ def test_highlevel_reloaded(self):
3434
importlib.reload(channels)
3535
"""));
3636

37+
@force_not_colorized
38+
def test_channel_id_types(self):
39+
# See https://github.com/python/cpython/issues/143376.
40+
code = """\
41+
import _interpchannels
42+
import re
43+
from concurrent import interpreters
44+
45+
class End:
46+
__slots__ = ()
47+
def __new__(cls, chan=None):
48+
return object.__new__(cls)
49+
@property
50+
def _id(self):
51+
return object()
52+
53+
class Send(End): pass
54+
class Recv(End): pass
55+
56+
_interpchannels._register_end_types(Send, Recv)
57+
chan = _interpchannels._channel_id(_interpchannels.create(), _resolve=True)
58+
interp = interpreters.create()
59+
try:
60+
interp.prepare_main(chan=Send(chan))
61+
finally:
62+
interp.close()
63+
"""
64+
65+
out, err = self.assert_python_failure("-c", code)
66+
self.assertEqual(out, '')
67+
errmsg = "TypeError: '_id' attribute must be an _interpchannels.ChannelID object, not object"
68+
self.assertIn(errmsg, err)
69+
3770

3871
class TestChannels(TestBase):
3972

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`concurrent.interpreters`: fix a crash when internal cross-interpreter
2+
channel ends have incorrect channel IDs. Patch by Bénédikt Tran.

‎Modules/_interpchannelsmodule.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,6 +2634,17 @@ _channelid_from_xid(_PyXIData_t *data)
26342634
static int
26352635
_channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
26362636
{
2637+
module_state *st = _get_current_module_state();
2638+
if (st == NULL) {
2639+
return -1;
2640+
}
2641+
if (!PyObject_IsInstance(obj, (PyObject *)st->ChannelIDType)) {
2642+
PyErr_Format(PyExc_TypeError,
2643+
"'_id' attribute must be an %N object, not %T",
2644+
st->ChannelIDType, obj);
2645+
return -1;
2646+
}
2647+
26372648
if (_PyXIData_InitWithSize(
26382649
data, tstate->interp, sizeof(struct _channelid_xid), obj,
26392650
_channelid_from_xid

0 commit comments

Comments
 (0)