diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-09-16-02-27.gh-issue-99293.oPstNV.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-09-16-02-27.gh-issue-99293.oPstNV.rst new file mode 100644 index 00000000000000..730e1a79c407ac --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-09-16-02-27.gh-issue-99293.oPstNV.rst @@ -0,0 +1 @@ +Fix an issue where extension modules could inadvertently trigger an assertion error in typeobject.c by clearing the Py_TPFLAGS_VALID_VERSION_TAG tp_flag without clearing the tp_version_tag field. (Extension modules should use PyType_Modified() instead, however.) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e2e40b5c15297d..d0f241d5b7c40b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4176,12 +4176,17 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) unsigned int h = MCACHE_HASH_METHOD(type, name); struct type_cache *cache = get_type_cache(); struct type_cache_entry *entry = &cache->hashtable[h]; + /* Some extension modules (e.g. those generated by SWIG) don't always + * change/clear tp_version_tag when they clear the + * Py_TPFLAGS_VALID_VERSION_TAG tp_flag, so check both tp_version_tag + * and the tp_flag. (Invalidated cache entries are replaced below.) + */ if (entry->version == type->tp_version_tag && - entry->name == name) { + entry->name == name && + _PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { #if MCACHE_STATS cache->hits++; #endif - assert(_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)); return entry->value; }