Skip to content

Commit b257f32

Browse files
committed
gh-143376: validate usages of _interpchannels.ChannelID in _channelid_shared
1 parent 1efe441 commit b257f32

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

Lib/test/test_interpreters/test_channels.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,30 @@ def test_highlevel_reloaded(self):
3030
# See gh-115490 (https://github.com/python/cpython/issues/115490).
3131
importlib.reload(channels)
3232

33+
def test_channel_id_types(self):
34+
# See https://github.com/python/cpython/issues/143376.
35+
class End:
36+
__slots__ = ()
37+
def __new__(cls, chan=None):
38+
return object.__new__(cls)
39+
@property
40+
def _id(self):
41+
return object()
42+
43+
class Send(End): pass
44+
class Recv(End): pass
45+
46+
_ = importlib.reload(_channels)
47+
_._register_end_types(Send, Recv)
48+
chan = _._channel_id(_.create(), _resolve=True)
49+
interp = interpreters.create()
50+
# The TypeError exception arises from our internal check,
51+
# but subinterpreters use a generic exception message instead
52+
# while retaining the original exception type.
53+
err = "does not support cross-interpreter data"
54+
with self.assertRaisesRegex(TypeError, err):
55+
interp.prepare_main(chan=Send(chan))
56+
3357

3458
class TestChannels(TestBase):
3559

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
@@ -2633,6 +2633,17 @@ _channelid_from_xid(_PyXIData_t *data)
26332633
static int
26342634
_channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
26352635
{
2636+
module_state *st = _get_current_module_state();
2637+
if (st == NULL) {
2638+
return -1;
2639+
}
2640+
if (!PyObject_IsInstance(obj, (PyObject *)st->ChannelIDType)) {
2641+
PyErr_Format(PyExc_TypeError,
2642+
"'_id' attribute must be an %N object, not %T",
2643+
st->ChannelIDType, obj);
2644+
return -1;
2645+
}
2646+
26362647
if (_PyXIData_InitWithSize(
26372648
data, tstate->interp, sizeof(struct _channelid_xid), obj,
26382649
_channelid_from_xid

0 commit comments

Comments
 (0)