summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-01-30 11:18:32 (GMT)
committerGitHub <noreply@github.com>2020-01-30 11:18:32 (GMT)
commitec3c99c8a73650d7833189bd973ec492564aa479 (patch)
treea1f02317982a7b5369a077cf82781872acc8b84e
parent38c878b56cff997de8fb04a586c963039b69b414 (diff)
downloadcpython-ec3c99c8a73650d7833189bd973ec492564aa479.zip
cpython-ec3c99c8a73650d7833189bd973ec492564aa479.tar.gz
cpython-ec3c99c8a73650d7833189bd973ec492564aa479.tar.bz2
bpo-38631: Avoid Py_FatalError() in unicodeobject.c (GH-18281)
Replace Py_FatalError() calls with _PyErr_WriteUnraisableMsg(), _PyObject_ASSERT_FAILED_MSG() or Py_UNREACHABLE() in unicode_dealloc() and unicode_release_interned().
-rw-r--r--Objects/unicodeobject.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 1ec2acc..8e1161e 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -1900,25 +1900,29 @@ unicode_dealloc(PyObject *unicode)
case SSTATE_INTERNED_MORTAL:
/* revive dead object temporarily for DelItem */
Py_REFCNT(unicode) = 3;
- if (PyDict_DelItem(interned, unicode) != 0)
- Py_FatalError(
- "deletion of interned string failed");
+ if (PyDict_DelItem(interned, unicode) != 0) {
+ _PyErr_WriteUnraisableMsg("deletion of interned string failed",
+ NULL);
+ }
break;
case SSTATE_INTERNED_IMMORTAL:
- Py_FatalError("Immortal interned string died.");
- /* fall through */
+ _PyObject_ASSERT_FAILED_MSG(unicode, "Immortal interned string died");
+ break;
default:
- Py_FatalError("Inconsistent interned string state.");
+ Py_UNREACHABLE();
}
- if (_PyUnicode_HAS_WSTR_MEMORY(unicode))
+ if (_PyUnicode_HAS_WSTR_MEMORY(unicode)) {
PyObject_DEL(_PyUnicode_WSTR(unicode));
- if (_PyUnicode_HAS_UTF8_MEMORY(unicode))
+ }
+ if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) {
PyObject_DEL(_PyUnicode_UTF8(unicode));
- if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode))
+ }
+ if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode)) {
PyObject_DEL(_PyUnicode_DATA_ANY(unicode));
+ }
Py_TYPE(unicode)->tp_free(unicode);
}
@@ -15401,14 +15405,10 @@ PyUnicode_InternFromString(const char *cp)
static void
unicode_release_interned(void)
{
- PyObject *keys;
- PyObject *s;
- Py_ssize_t i, n;
- Py_ssize_t immortal_size = 0, mortal_size = 0;
-
- if (interned == NULL || !PyDict_Check(interned))
+ if (interned == NULL || !PyDict_Check(interned)) {
return;
- keys = PyDict_Keys(interned);
+ }
+ PyObject *keys = PyDict_Keys(interned);
if (keys == NULL || !PyList_Check(keys)) {
PyErr_Clear();
return;
@@ -15419,30 +15419,35 @@ unicode_release_interned(void)
rather, we give them their stolen references back, and then clear
and DECREF the interned dict. */
- n = PyList_GET_SIZE(keys);
+ Py_ssize_t n = PyList_GET_SIZE(keys);
#ifdef INTERNED_STATS
fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n",
n);
+
+ Py_ssize_t immortal_size = 0, mortal_size = 0;
#endif
- for (i = 0; i < n; i++) {
- s = PyList_GET_ITEM(keys, i);
+ for (Py_ssize_t i = 0; i < n; i++) {
+ PyObject *s = PyList_GET_ITEM(keys, i);
if (PyUnicode_READY(s) == -1) {
Py_UNREACHABLE();
}
switch (PyUnicode_CHECK_INTERNED(s)) {
- case SSTATE_NOT_INTERNED:
- /* XXX Shouldn't happen */
- break;
case SSTATE_INTERNED_IMMORTAL:
Py_REFCNT(s) += 1;
+#ifdef INTERNED_STATS
immortal_size += PyUnicode_GET_LENGTH(s);
+#endif
break;
case SSTATE_INTERNED_MORTAL:
Py_REFCNT(s) += 2;
+#ifdef INTERNED_STATS
mortal_size += PyUnicode_GET_LENGTH(s);
+#endif
break;
+ case SSTATE_NOT_INTERNED:
+ /* fall through */
default:
- Py_FatalError("Inconsistent interned string state.");
+ Py_UNREACHABLE();
}
_PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED;
}