Skip to content

Commit 072b8eb

Browse files
committed
Cleaning up tp_dict for static builtin types in subinterpreter
When initializing base types in a subinterpreters extra items are added to tp_dict which triggers incorrect behavior while running code under a subinterpreter. Here we're identifying which keys are not part of the original tp_dict in the main interpreter and removing them.
1 parent dba7a16 commit 072b8eb

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

Objects/typeobject.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,47 @@ lookup_tp_dict(PyTypeObject *self)
279279
return self->tp_dict;
280280
}
281281

282+
static inline int
283+
cleanup_tp_dict(PyTypeObject *self)
284+
{
285+
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
286+
PyInterpreterState *interp = _PyInterpreterState_GET();
287+
static_builtin_state *state = _PyStaticType_GetState(interp, self);
288+
assert(state != NULL);
289+
if (!_Py_IsMainInterpreter(interp)) {
290+
PyInterpreterState *main_interp = _PyInterpreterState_Main();
291+
static_builtin_state *main_state = _PyStaticType_GetState(main_interp, self);
292+
assert(main_state != NULL);
293+
294+
PyObject* keys_to_remove = PyList_New(0);
295+
if (!keys_to_remove) {
296+
return -1;
297+
}
298+
Py_ssize_t i = 0;
299+
PyObject *key, *value;
300+
while (PyDict_Next(state->tp_dict, &i, &key, &value)) {
301+
if (!PyDict_Contains(main_state->tp_dict, key)) {
302+
if (PyList_Append(keys_to_remove, key) < 0) {
303+
Py_DECREF(keys_to_remove);
304+
return -1;
305+
}
306+
}
307+
}
308+
309+
Py_ssize_t list_size = PyList_Size(keys_to_remove);
310+
for (Py_ssize_t i = 0; i < list_size; i++) {
311+
PyObject* key = PyList_GetItem(keys_to_remove, i);
312+
if (PyDict_DelItem(state->tp_dict, key) < 0) {
313+
Py_DECREF(keys_to_remove);
314+
return -1;
315+
}
316+
}
317+
Py_DECREF(keys_to_remove);
318+
}
319+
}
320+
return 0;
321+
}
322+
282323
PyObject *
283324
_PyType_GetDict(PyTypeObject *self)
284325
{
@@ -7858,6 +7899,9 @@ type_ready_fill_dict(PyTypeObject *type)
78587899
if (type_dict_set_doc(type) < 0) {
78597900
return -1;
78607901
}
7902+
if (cleanup_tp_dict(type) < 0) {
7903+
return -1;
7904+
}
78617905
return 0;
78627906
}
78637907

0 commit comments

Comments
 (0)