@@ -1943,13 +1943,20 @@ unicode_dealloc(PyObject *unicode)
19431943 break ;
19441944
19451945 case SSTATE_INTERNED_MORTAL :
1946- /* revive dead object temporarily for DelItem */
1947- Py_SET_REFCNT (unicode , 3 );
19481946#ifdef INTERNED_STRINGS
1947+ /* Revive the dead object temporarily. PyDict_DelItem() removes two
1948+ references (key and value) which were ignored by
1949+ PyUnicode_InternInPlace(). Use refcnt=3 rather than refcnt=2
1950+ to prevent calling unicode_dealloc() again. Adjust refcnt after
1951+ PyDict_DelItem(). */
1952+ assert (Py_REFCNT (unicode ) == 0 );
1953+ Py_SET_REFCNT (unicode , 3 );
19491954 if (PyDict_DelItem (interned , unicode ) != 0 ) {
19501955 _PyErr_WriteUnraisableMsg ("deletion of interned string failed" ,
19511956 NULL );
19521957 }
1958+ assert (Py_REFCNT (unicode ) == 1 );
1959+ Py_SET_REFCNT (unicode , 0 );
19531960#endif
19541961 break ;
19551962
@@ -15710,8 +15717,9 @@ PyUnicode_InternInPlace(PyObject **p)
1571015717 return ;
1571115718 }
1571215719
15713- /* The two references in interned are not counted by refcnt.
15714- The deallocator will take care of this */
15720+ /* The two references in interned dict (key and value) are not counted by
15721+ refcnt. unicode_dealloc() and _PyUnicode_ClearInterned() take care of
15722+ this. */
1571515723 Py_SET_REFCNT (s , Py_REFCNT (s ) - 2 );
1571615724 _PyUnicode_STATE (s ).interned = SSTATE_INTERNED_MORTAL ;
1571715725#endif
@@ -15780,6 +15788,8 @@ _PyUnicode_ClearInterned(PyThreadState *tstate)
1578015788#endif
1578115789 break ;
1578215790 case SSTATE_INTERNED_MORTAL :
15791+ // Restore the two references (key and value) ignored
15792+ // by PyUnicode_InternInPlace().
1578315793 Py_SET_REFCNT (s , Py_REFCNT (s ) + 2 );
1578415794#ifdef INTERNED_STATS
1578515795 mortal_size += PyUnicode_GET_LENGTH (s );
0 commit comments