Skip to content

Commit 3e07c20

Browse files
[3.12] 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 58f7763 commit 3e07c20

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
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

+10-6
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ _PyUnicode_InternedSize_Immortal(void)
257257
// value, to help detect bugs in optimizations.
258258

259259
while (PyDict_Next(dict, &pos, &key, &value)) {
260-
if (_Py_IsImmortal(key)) {
260+
assert(PyUnicode_CHECK_INTERNED(key) != SSTATE_INTERNED_IMMORTAL_STATIC);
261+
if (PyUnicode_CHECK_INTERNED(key) == SSTATE_INTERNED_IMMORTAL) {
261262
count++;
262263
}
263264
}
@@ -691,10 +692,14 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
691692

692693
/* Check interning state */
693694
#ifdef Py_DEBUG
695+
// Note that we do not check `_Py_IsImmortal(op)`, since stable ABI
696+
// extensions can make immortal strings mortal (but with a high enough
697+
// refcount).
698+
// The other way is extremely unlikely (worth a potential failed assertion
699+
// in a debug build), so we do check `!_Py_IsImmortal(op)`.
694700
switch (PyUnicode_CHECK_INTERNED(op)) {
695701
case SSTATE_NOT_INTERNED:
696702
if (ascii->state.statically_allocated) {
697-
CHECK(_Py_IsImmortal(op));
698703
// This state is for two exceptions:
699704
// - strings are currently checked before they're interned
700705
// - the 256 one-latin1-character strings
@@ -710,11 +715,9 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
710715
break;
711716
case SSTATE_INTERNED_IMMORTAL:
712717
CHECK(!ascii->state.statically_allocated);
713-
CHECK(_Py_IsImmortal(op));
714718
break;
715719
case SSTATE_INTERNED_IMMORTAL_STATIC:
716720
CHECK(ascii->state.statically_allocated);
717-
CHECK(_Py_IsImmortal(op));
718721
break;
719722
default:
720723
Py_UNREACHABLE();
@@ -1899,7 +1902,8 @@ unicode_write_cstr(PyObject *unicode, Py_ssize_t index,
18991902
static PyObject*
19001903
get_latin1_char(Py_UCS1 ch)
19011904
{
1902-
return Py_NewRef(LATIN1(ch));
1905+
PyObject *o = LATIN1(ch);
1906+
return o;
19031907
}
19041908

19051909
static PyObject*
@@ -15015,7 +15019,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
1501515019
{
1501615020
PyObject *r = (PyObject *)_Py_hashtable_get(INTERNED_STRINGS, s);
1501715021
if (r != NULL) {
15018-
assert(_Py_IsImmortal(r));
15022+
assert(_PyUnicode_STATE(r).statically_allocated);
1501915023
assert(r != s); // r must be statically_allocated; s is not
1502015024
Py_DECREF(s);
1502115025
return Py_NewRef(r);

0 commit comments

Comments
 (0)