@@ -4618,9 +4618,14 @@ check_basicsize_includes_size_and_offsets(PyTypeObject* type)
4618
4618
}
4619
4619
4620
4620
static int
4621
- check_immutable_bases (const char * type_name , PyObject * bases )
4621
+ check_immutable_bases (const char * type_name , PyObject * bases , int skip_first )
4622
4622
{
4623
- for (Py_ssize_t i = 0 ; i < PyTuple_GET_SIZE (bases ); i ++ ) {
4623
+ Py_ssize_t i = 0 ;
4624
+ if (skip_first ) {
4625
+ // When testing the MRO, skip the type itself
4626
+ i = 1 ;
4627
+ }
4628
+ for (; i < PyTuple_GET_SIZE (bases ); i ++ ) {
4624
4629
PyTypeObject * b = (PyTypeObject * )PyTuple_GET_ITEM (bases , i );
4625
4630
if (!b ) {
4626
4631
return -1 ;
@@ -4793,7 +4798,7 @@ _PyType_FromMetaclass_impl(
4793
4798
* and only heap types can be mutable.)
4794
4799
*/
4795
4800
if (spec -> flags & Py_TPFLAGS_IMMUTABLETYPE ) {
4796
- if (check_immutable_bases (spec -> name , bases ) < 0 ) {
4801
+ if (check_immutable_bases (spec -> name , bases , 0 ) < 0 ) {
4797
4802
goto finally ;
4798
4803
}
4799
4804
}
@@ -11139,8 +11144,17 @@ add_operators(PyTypeObject *type, PyTypeObject *def)
11139
11144
int
11140
11145
PyType_Freeze (PyTypeObject * type )
11141
11146
{
11142
- PyObject * bases = type -> tp_bases ;
11143
- if (check_immutable_bases (type -> tp_name , bases ) < 0 ) {
11147
+ // gh-121654: Check the __mro__ instead of __bases__
11148
+ PyObject * mro = type_get_mro (type , NULL );
11149
+ if (!PyTuple_Check (mro )) {
11150
+ Py_DECREF (mro );
11151
+ PyErr_SetString (PyExc_TypeError , "unable to get the type MRO" );
11152
+ return -1 ;
11153
+ }
11154
+
11155
+ int check = check_immutable_bases (type -> tp_name , mro , 1 );
11156
+ Py_DECREF (mro );
11157
+ if (check < 0 ) {
11144
11158
return -1 ;
11145
11159
}
11146
11160
0 commit comments