diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-23-48-54.gh-issue-151763.Eu8pYQ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-23-48-54.gh-issue-151763.Eu8pYQ.rst new file mode 100644 index 00000000000000..d4746e992f8779 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-23-48-54.gh-issue-151763.Eu8pYQ.rst @@ -0,0 +1 @@ +Fixes possible crash on :class:`types.CodeType` deallocation. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 4ede8de6e8adc5..03036020b1cb1a 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -743,6 +743,10 @@ _PyCode_New(struct _PyCodeConstructor *con) return NULL; } +#ifdef Py_GIL_DISABLED + co->_co_unique_id = _Py_INVALID_UNIQUE_ID; +#endif + if (init_code(co, con) < 0) { Py_DECREF(co); return NULL; @@ -2449,15 +2453,17 @@ code_dealloc(PyObject *self) FT_CLEAR_WEAKREFS(self, co->co_weakreflist); free_monitoring_data(co->_co_monitoring); #ifdef Py_GIL_DISABLED - // The first element always points to the mutable bytecode at the end of - // the code object, which will be freed when the code object is freed. - for (Py_ssize_t i = 1; i < co->co_tlbc->size; i++) { - char *entry = co->co_tlbc->entries[i]; - if (entry != NULL) { - PyMem_Free(entry); + if (co->co_tlbc != NULL) { + // The first element always points to the mutable bytecode at the end of + // the code object, which will be freed when the code object is freed. + for (Py_ssize_t i = 1; i < co->co_tlbc->size; i++) { + char *entry = co->co_tlbc->entries[i]; + if (entry != NULL) { + PyMem_Free(entry); + } } + PyMem_Free(co->co_tlbc); } - PyMem_Free(co->co_tlbc); #endif PyObject_Free(co); }