@@ -1943,13 +1943,20 @@ unicode_dealloc(PyObject *unicode)
1943
1943
break ;
1944
1944
1945
1945
case SSTATE_INTERNED_MORTAL :
1946
- /* revive dead object temporarily for DelItem */
1947
- Py_SET_REFCNT (unicode , 3 );
1948
1946
#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 );
1949
1954
if (PyDict_DelItem (interned , unicode ) != 0 ) {
1950
1955
_PyErr_WriteUnraisableMsg ("deletion of interned string failed" ,
1951
1956
NULL );
1952
1957
}
1958
+ assert (Py_REFCNT (unicode ) == 1 );
1959
+ Py_SET_REFCNT (unicode , 0 );
1953
1960
#endif
1954
1961
break ;
1955
1962
@@ -15710,8 +15717,9 @@ PyUnicode_InternInPlace(PyObject **p)
15710
15717
return ;
15711
15718
}
15712
15719
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. */
15715
15723
Py_SET_REFCNT (s , Py_REFCNT (s ) - 2 );
15716
15724
_PyUnicode_STATE (s ).interned = SSTATE_INTERNED_MORTAL ;
15717
15725
#endif
@@ -15780,6 +15788,8 @@ _PyUnicode_ClearInterned(PyThreadState *tstate)
15780
15788
#endif
15781
15789
break ;
15782
15790
case SSTATE_INTERNED_MORTAL :
15791
+ // Restore the two references (key and value) ignored
15792
+ // by PyUnicode_InternInPlace().
15783
15793
Py_SET_REFCNT (s , Py_REFCNT (s ) + 2 );
15784
15794
#ifdef INTERNED_STATS
15785
15795
mortal_size += PyUnicode_GET_LENGTH (s );
0 commit comments