Skip to content

Commit 281ffb6

Browse files
[3.13] gh-113993: For string interning, do not rely on (or assert) _Py_IsImmortal (GH-121358) (GH-121851)
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`). (cherry picked from commit 956270d) Co-authored-by: Petr Viktorin <[email protected]>
1 parent f0e4b02 commit 281ffb6

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
@@ -247,7 +247,8 @@ _PyUnicode_InternedSize_Immortal(void)
247247
// value, to help detect bugs in optimizations.
248248

249249
while (PyDict_Next(dict, &pos, &key, &value)) {
250-
if (_Py_IsImmortal(key)) {
250+
assert(PyUnicode_CHECK_INTERNED(key) != SSTATE_INTERNED_IMMORTAL_STATIC);
251+
if (PyUnicode_CHECK_INTERNED(key) == SSTATE_INTERNED_IMMORTAL) {
251252
count++;
252253
}
253254
}
@@ -683,10 +684,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
683684

684685
/* Check interning state */
685686
#ifdef Py_DEBUG
687+
// Note that we do not check `_Py_IsImmortal(op)`, since stable ABI
688+
// extensions can make immortal strings mortal (but with a high enough
689+
// refcount).
690+
// The other way is extremely unlikely (worth a potential failed assertion
691+
// in a debug build), so we do check `!_Py_IsImmortal(op)`.
686692
switch (PyUnicode_CHECK_INTERNED(op)) {
687693
case SSTATE_NOT_INTERNED:
688694
if (ascii->state.statically_allocated) {
689-
CHECK(_Py_IsImmortal(op));
690695
// This state is for two exceptions:
691696
// - strings are currently checked before they're interned
692697
// - the 256 one-latin1-character strings
@@ -702,11 +707,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
702707
break;
703708
case SSTATE_INTERNED_IMMORTAL:
704709
CHECK(!ascii->state.statically_allocated);
705-
CHECK(_Py_IsImmortal(op));
706710
break;
707711
case SSTATE_INTERNED_IMMORTAL_STATIC:
708712
CHECK(ascii->state.statically_allocated);
709-
CHECK(_Py_IsImmortal(op));
710713
break;
711714
default:
712715
Py_UNREACHABLE();
@@ -1899,7 +1902,6 @@ static PyObject*
18991902
get_latin1_char(Py_UCS1 ch)
19001903
{
19011904
PyObject *o = LATIN1(ch);
1902-
assert(_Py_IsImmortal(o));
19031905
return o;
19041906
}
19051907

@@ -15049,7 +15051,6 @@ intern_static(PyInterpreterState *interp, PyObject *s /* stolen */)
1504915051
assert(s != NULL);
1505015052
assert(_PyUnicode_CHECK(s));
1505115053
assert(_PyUnicode_STATE(s).statically_allocated);
15052-
assert(_Py_IsImmortal(s));
1505315054

1505415055
switch (PyUnicode_CHECK_INTERNED(s)) {
1505515056
case SSTATE_NOT_INTERNED:
@@ -15190,7 +15191,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
1519015191
{
1519115192
PyObject *r = (PyObject *)_Py_hashtable_get(INTERNED_STRINGS, s);
1519215193
if (r != NULL) {
15193-
assert(_Py_IsImmortal(r));
15194+
assert(_PyUnicode_STATE(r).statically_allocated);
1519415195
assert(r != s); // r must be statically_allocated; s is not
1519515196
Py_DECREF(s);
1519615197
return Py_NewRef(r);

0 commit comments

Comments
 (0)