bpo-1635741: Fix unicode_dealloc() for mortal interned string (GH-21270)
When unicode_dealloc() is called on a mortal interned string, the string reference counter is now reset at zero.
This commit is contained in:
parent
91e1bc18bd
commit
3549ca313a
|
@ -1943,13 +1943,20 @@ unicode_dealloc(PyObject *unicode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSTATE_INTERNED_MORTAL:
|
case SSTATE_INTERNED_MORTAL:
|
||||||
/* revive dead object temporarily for DelItem */
|
|
||||||
Py_SET_REFCNT(unicode, 3);
|
|
||||||
#ifdef INTERNED_STRINGS
|
#ifdef INTERNED_STRINGS
|
||||||
|
/* Revive the dead object temporarily. PyDict_DelItem() removes two
|
||||||
|
references (key and value) which were ignored by
|
||||||
|
PyUnicode_InternInPlace(). Use refcnt=3 rather than refcnt=2
|
||||||
|
to prevent calling unicode_dealloc() again. Adjust refcnt after
|
||||||
|
PyDict_DelItem(). */
|
||||||
|
assert(Py_REFCNT(unicode) == 0);
|
||||||
|
Py_SET_REFCNT(unicode, 3);
|
||||||
if (PyDict_DelItem(interned, unicode) != 0) {
|
if (PyDict_DelItem(interned, unicode) != 0) {
|
||||||
_PyErr_WriteUnraisableMsg("deletion of interned string failed",
|
_PyErr_WriteUnraisableMsg("deletion of interned string failed",
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
assert(Py_REFCNT(unicode) == 1);
|
||||||
|
Py_SET_REFCNT(unicode, 0);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -15710,8 +15717,9 @@ PyUnicode_InternInPlace(PyObject **p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The two references in interned are not counted by refcnt.
|
/* The two references in interned dict (key and value) are not counted by
|
||||||
The deallocator will take care of this */
|
refcnt. unicode_dealloc() and _PyUnicode_ClearInterned() take care of
|
||||||
|
this. */
|
||||||
Py_SET_REFCNT(s, Py_REFCNT(s) - 2);
|
Py_SET_REFCNT(s, Py_REFCNT(s) - 2);
|
||||||
_PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL;
|
_PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -15780,6 +15788,8 @@ _PyUnicode_ClearInterned(PyThreadState *tstate)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case SSTATE_INTERNED_MORTAL:
|
case SSTATE_INTERNED_MORTAL:
|
||||||
|
// Restore the two references (key and value) ignored
|
||||||
|
// by PyUnicode_InternInPlace().
|
||||||
Py_SET_REFCNT(s, Py_REFCNT(s) + 2);
|
Py_SET_REFCNT(s, Py_REFCNT(s) + 2);
|
||||||
#ifdef INTERNED_STATS
|
#ifdef INTERNED_STATS
|
||||||
mortal_size += PyUnicode_GET_LENGTH(s);
|
mortal_size += PyUnicode_GET_LENGTH(s);
|
||||||
|
|
Loading…
Reference in New Issue