@@ -138,6 +138,7 @@ As a consequence of this, split keys have a maximum size of 16.
138138// Forward declarations
139139static PyObject * frozendict_new (PyTypeObject * type , PyObject * args ,
140140 PyObject * kwds );
141+ static int frozendict_check_mutable (PyObject * self );
141142
142143
143144/*[clinic input]
@@ -3317,6 +3318,11 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
33173318 }
33183319 }
33193320 else if (PyFrozenDict_CheckExact (d )) {
3321+ // Check if the class constructor kept a reference to the frozendict
3322+ if (frozendict_check_mutable (d ) < 0 ) {
3323+ return NULL ;
3324+ }
3325+
33203326 if (PyDict_CheckExact (iterable )) {
33213327 PyDictObject * mp = (PyDictObject * )d ;
33223328
@@ -3360,6 +3366,11 @@ dict_iter_exit:;
33603366 Py_END_CRITICAL_SECTION ();
33613367 }
33623368 else if (PyFrozenDict_CheckExact (d )) {
3369+ // Check if the class constructor kept a reference to the frozendict
3370+ if (frozendict_check_mutable (d ) < 0 ) {
3371+ goto Fail ;
3372+ }
3373+
33633374 while ((key = PyIter_Next (it )) != NULL ) {
33643375 // anydict_setitem_take2 consumes a reference to key
33653376 status = anydict_setitem_take2 ((PyDictObject * )d ,
@@ -7889,6 +7900,17 @@ _PyObject_InlineValuesConsistencyCheck(PyObject *obj)
78897900
78907901// --- frozendict implementation ---------------------------------------------
78917902
7903+ static int
7904+ frozendict_check_mutable (PyObject * self )
7905+ {
7906+ if (Py_REFCNT (self ) > 1 ) {
7907+ PyErr_SetString (PyExc_RuntimeError ,
7908+ "cannot mutate frozendict already exposed in Python" );
7909+ return -1 ;
7910+ }
7911+ return 0 ;
7912+ }
7913+
78927914static PyNumberMethods frozendict_as_number = {
78937915 .nb_or = frozendict_or ,
78947916};
@@ -7994,6 +8016,8 @@ frozendict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
79948016 if (d == NULL ) {
79958017 return NULL ;
79968018 }
8019+ assert (Py_REFCNT (self ) == 1 );
8020+
79978021 PyFrozenDictObject * self = _PyFrozenDictObject_CAST (d );
79988022 self -> ma_hash = -1 ;
79998023
0 commit comments