@@ -819,6 +819,7 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
819819 _PyObjectCache * cache2 = & cache [-2 ].obj ;
820820
821821 PyTypeObject * owner_cls = Py_TYPE (owner );
822+ PyDictObject * owner_dict = NULL ;
822823 if (PyModule_CheckExact (owner )) {
823824 int err = specialize_module_load_attr (owner , instr , name , cache0 , cache1 ,
824825 LOAD_METHOD , LOAD_METHOD_MODULE );
@@ -846,11 +847,18 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
846847 }
847848 PyObject * * owner_dictptr = _PyObject_GetDictPtr (owner );
848849 int owner_has_dict = (owner_dictptr != NULL && * owner_dictptr != NULL );
849- PyDictObject * owner_dict = owner_has_dict ? (PyDictObject * )* owner_dictptr : NULL ;
850+ owner_dict = owner_has_dict ? (PyDictObject * )* owner_dictptr : NULL ;
851+ Py_XINCREF (owner_dict ); // make sure dict doesn't disappear halfway
850852 // Check for classmethods.
851853 int owner_is_class = PyType_Check (owner );
852854 owner_cls = owner_is_class ? (PyTypeObject * )owner : owner_cls ;
853855
856+ if ((owner_cls -> tp_flags & Py_TPFLAGS_VALID_VERSION_TAG ) == 0 ||
857+ owner_cls -> tp_version_tag == 0 ) {
858+ SPECIALIZATION_FAIL (LOAD_METHOD , SPEC_FAIL_OUT_OF_VERSIONS );
859+ goto fail ;
860+ }
861+
854862 PyObject * descr = NULL ;
855863 DesciptorClassification kind = 0 ;
856864 kind = analyze_descriptor (owner_cls , name , & descr , 0 );
@@ -928,11 +936,13 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
928936 LOAD_METHOD_CACHED , _Py_OPARG (* instr ));
929937 // Fall through.
930938success :
939+ Py_XDECREF (owner_dict );
931940 STAT_INC (LOAD_METHOD , specialization_success );
932941 assert (!PyErr_Occurred ());
933942 cache0 -> counter = saturating_start ();
934943 return 0 ;
935944fail :
945+ Py_XDECREF (owner_dict );
936946 STAT_INC (LOAD_METHOD , specialization_failure );
937947 assert (!PyErr_Occurred ());
938948 cache_backoff (cache0 );
0 commit comments