mirror of
https://github.com/python/cpython.git
synced 2025-07-12 13:55:34 +00:00
[3.12] gh-105699: Fix an Interned Strings Crasher (gh-106930) (#106963)
gh-105699: Fix an Interned Strings Crasher (gh-106930)
A static (process-global) str object must only have its "interned" state cleared when no longer interned in any interpreters. They are the only ones that can be shared by interpreters so we don't have to worry about any other str objects.
We trigger clearing the state with the main interpreter, since no other interpreters may exist at that point and _PyUnicode_ClearInterned() is only called during interpreter finalization.
We do not address here the fact that a string will only be interned in the first interpreter that interns it. In any subsequent interpreters str.state.interned is already set so _PyUnicode_InternInPlace() will skip it. That needs to be addressed separately from fixing the crasher.
(cherry picked from commit 87e7cb09e4
)
Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
This commit is contained in:
parent
957f14d0de
commit
d0176ed911
2 changed files with 15 additions and 1 deletions
|
@ -14817,6 +14817,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
|
|||
PyObject *s, *ignored_value;
|
||||
while (PyDict_Next(interned, &pos, &s, &ignored_value)) {
|
||||
assert(PyUnicode_IS_READY(s));
|
||||
int shared = 0;
|
||||
switch (PyUnicode_CHECK_INTERNED(s)) {
|
||||
case SSTATE_INTERNED_IMMORTAL:
|
||||
// Skip the Immortal Instance check and restore
|
||||
|
@ -14828,6 +14829,14 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
|
|||
#endif
|
||||
break;
|
||||
case SSTATE_INTERNED_IMMORTAL_STATIC:
|
||||
/* It is shared between interpreters, so we should unmark it
|
||||
only when this is the last interpreter in which it's
|
||||
interned. We immortalize all the statically initialized
|
||||
strings during startup, so we can rely on the
|
||||
main interpreter to be the last one. */
|
||||
if (!_Py_IsMainInterpreter(interp)) {
|
||||
shared = 1;
|
||||
}
|
||||
break;
|
||||
case SSTATE_INTERNED_MORTAL:
|
||||
/* fall through */
|
||||
|
@ -14836,7 +14845,9 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
|
|||
default:
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
_PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED;
|
||||
if (!shared) {
|
||||
_PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED;
|
||||
}
|
||||
}
|
||||
#ifdef INTERNED_STATS
|
||||
fprintf(stderr,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue