Skip to content

Commit 956270d

Browse files
authored
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`).
1 parent a0b205b commit 956270d

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removed debug build assertions related to interning strings, which were
2+
falsely triggered by stable ABI extensions.

Objects/unicodeobject.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ _PyUnicode_InternedSize_Immortal(void)
252252
// value, to help detect bugs in optimizations.
253253

254254
while (PyDict_Next(dict, &pos, &key, &value)) {
255-
if (_Py_IsImmortal(key)) {
255+
assert(PyUnicode_CHECK_INTERNED(key) != SSTATE_INTERNED_IMMORTAL_STATIC);
256+
if (PyUnicode_CHECK_INTERNED(key) == SSTATE_INTERNED_IMMORTAL) {
256257
count++;
257258
}
258259
}
@@ -688,10 +689,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
688689

689690
/* Check interning state */
690691
#ifdef Py_DEBUG
692+
// Note that we do not check `_Py_IsImmortal(op)`, since stable ABI
693+
// extensions can make immortal strings mortal (but with a high enough
694+
// refcount).
695+
// The other way is extremely unlikely (worth a potential failed assertion
696+
// in a debug build), so we do check `!_Py_IsImmortal(op)`.
691697
switch (PyUnicode_CHECK_INTERNED(op)) {
692698
case SSTATE_NOT_INTERNED:
693699
if (ascii->state.statically_allocated) {
694-
CHECK(_Py_IsImmortal(op));
695700
// This state is for two exceptions:
696701
// - strings are currently checked before they're interned
697702
// - the 256 one-latin1-character strings
@@ -707,11 +712,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
707712
break;
708713
case SSTATE_INTERNED_IMMORTAL:
709714
CHECK(!ascii->state.statically_allocated);
710-
CHECK(_Py_IsImmortal(op));
711715
break;
712716
case SSTATE_INTERNED_IMMORTAL_STATIC:
713717
CHECK(ascii->state.statically_allocated);
714-
CHECK(_Py_IsImmortal(op));
715718
break;
716719
default:
717720
Py_UNREACHABLE();
@@ -1867,7 +1870,6 @@ static PyObject*
18671870
get_latin1_char(Py_UCS1 ch)
18681871
{
18691872
PyObject *o = LATIN1(ch);
1870-
assert(_Py_IsImmortal(o));
18711873
return o;
18721874
}
18731875

@@ -15352,7 +15354,6 @@ intern_static(PyInterpreterState *interp, PyObject *s /* stolen */)
1535215354
assert(s != NULL);
1535315355
assert(_PyUnicode_CHECK(s));
1535415356
assert(_PyUnicode_STATE(s).statically_allocated);
15355-
assert(_Py_IsImmortal(s));
1535615357

1535715358
switch (PyUnicode_CHECK_INTERNED(s)) {
1535815359
case SSTATE_NOT_INTERNED:
@@ -15493,7 +15494,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
1549315494
{
1549415495
PyObject *r = (PyObject *)_Py_hashtable_get(INTERNED_STRINGS, s);
1549515496
if (r != NULL) {
15496-
assert(_Py_IsImmortal(r));
15497+
assert(_PyUnicode_STATE(r).statically_allocated);
1549715498
assert(r != s); // r must be statically_allocated; s is not
1549815499
Py_DECREF(s);
1549915500
return Py_NewRef(r);

0 commit comments

Comments
 (0)