mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
gh-113993: For string interning, do not rely on (or assert) _Py_IsImmortal (GH-121358)
Older stable ABI extensions are allowed to make immortal objects mortal. Instead, use `_PyUnicode_STATE` (`interned` and `statically_allocated`).
This commit is contained in:
parent
a0b205bba5
commit
956270d08d
2 changed files with 10 additions and 7 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
Removed debug build assertions related to interning strings, which were
|
||||||
|
falsely triggered by stable ABI extensions.
|
|
@ -252,7 +252,8 @@ _PyUnicode_InternedSize_Immortal(void)
|
||||||
// value, to help detect bugs in optimizations.
|
// value, to help detect bugs in optimizations.
|
||||||
|
|
||||||
while (PyDict_Next(dict, &pos, &key, &value)) {
|
while (PyDict_Next(dict, &pos, &key, &value)) {
|
||||||
if (_Py_IsImmortal(key)) {
|
assert(PyUnicode_CHECK_INTERNED(key) != SSTATE_INTERNED_IMMORTAL_STATIC);
|
||||||
|
if (PyUnicode_CHECK_INTERNED(key) == SSTATE_INTERNED_IMMORTAL) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,10 +689,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
|
||||||
|
|
||||||
/* Check interning state */
|
/* Check interning state */
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
|
// Note that we do not check `_Py_IsImmortal(op)`, since stable ABI
|
||||||
|
// extensions can make immortal strings mortal (but with a high enough
|
||||||
|
// refcount).
|
||||||
|
// The other way is extremely unlikely (worth a potential failed assertion
|
||||||
|
// in a debug build), so we do check `!_Py_IsImmortal(op)`.
|
||||||
switch (PyUnicode_CHECK_INTERNED(op)) {
|
switch (PyUnicode_CHECK_INTERNED(op)) {
|
||||||
case SSTATE_NOT_INTERNED:
|
case SSTATE_NOT_INTERNED:
|
||||||
if (ascii->state.statically_allocated) {
|
if (ascii->state.statically_allocated) {
|
||||||
CHECK(_Py_IsImmortal(op));
|
|
||||||
// This state is for two exceptions:
|
// This state is for two exceptions:
|
||||||
// - strings are currently checked before they're interned
|
// - strings are currently checked before they're interned
|
||||||
// - the 256 one-latin1-character strings
|
// - the 256 one-latin1-character strings
|
||||||
|
@ -707,11 +712,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
|
||||||
break;
|
break;
|
||||||
case SSTATE_INTERNED_IMMORTAL:
|
case SSTATE_INTERNED_IMMORTAL:
|
||||||
CHECK(!ascii->state.statically_allocated);
|
CHECK(!ascii->state.statically_allocated);
|
||||||
CHECK(_Py_IsImmortal(op));
|
|
||||||
break;
|
break;
|
||||||
case SSTATE_INTERNED_IMMORTAL_STATIC:
|
case SSTATE_INTERNED_IMMORTAL_STATIC:
|
||||||
CHECK(ascii->state.statically_allocated);
|
CHECK(ascii->state.statically_allocated);
|
||||||
CHECK(_Py_IsImmortal(op));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Py_UNREACHABLE();
|
Py_UNREACHABLE();
|
||||||
|
@ -1867,7 +1870,6 @@ static PyObject*
|
||||||
get_latin1_char(Py_UCS1 ch)
|
get_latin1_char(Py_UCS1 ch)
|
||||||
{
|
{
|
||||||
PyObject *o = LATIN1(ch);
|
PyObject *o = LATIN1(ch);
|
||||||
assert(_Py_IsImmortal(o));
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15352,7 +15354,6 @@ intern_static(PyInterpreterState *interp, PyObject *s /* stolen */)
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
assert(_PyUnicode_CHECK(s));
|
assert(_PyUnicode_CHECK(s));
|
||||||
assert(_PyUnicode_STATE(s).statically_allocated);
|
assert(_PyUnicode_STATE(s).statically_allocated);
|
||||||
assert(_Py_IsImmortal(s));
|
|
||||||
|
|
||||||
switch (PyUnicode_CHECK_INTERNED(s)) {
|
switch (PyUnicode_CHECK_INTERNED(s)) {
|
||||||
case SSTATE_NOT_INTERNED:
|
case SSTATE_NOT_INTERNED:
|
||||||
|
@ -15493,7 +15494,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
|
||||||
{
|
{
|
||||||
PyObject *r = (PyObject *)_Py_hashtable_get(INTERNED_STRINGS, s);
|
PyObject *r = (PyObject *)_Py_hashtable_get(INTERNED_STRINGS, s);
|
||||||
if (r != NULL) {
|
if (r != NULL) {
|
||||||
assert(_Py_IsImmortal(r));
|
assert(_PyUnicode_STATE(r).statically_allocated);
|
||||||
assert(r != s); // r must be statically_allocated; s is not
|
assert(r != s); // r must be statically_allocated; s is not
|
||||||
Py_DECREF(s);
|
Py_DECREF(s);
|
||||||
return Py_NewRef(r);
|
return Py_NewRef(r);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue