diff options
author | Victor Stinner <vstinner@python.org> | 2020-01-30 08:02:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-30 08:02:14 (GMT) |
commit | 7a1f6c2da46a04d0ff0acc01542f30bfeaf0e0c7 (patch) | |
tree | 97f3f57ed5557bb6eef9bc0fd3071f0fdaf3acd8 | |
parent | 5eb8bff7e4aa7e4d8580a30323641388c8ff59a5 (diff) | |
download | cpython-7a1f6c2da46a04d0ff0acc01542f30bfeaf0e0c7.zip cpython-7a1f6c2da46a04d0ff0acc01542f30bfeaf0e0c7.tar.gz cpython-7a1f6c2da46a04d0ff0acc01542f30bfeaf0e0c7.tar.bz2 |
bpo-38631: Avoid Py_FatalError() in init_slotdefs() (GH-18263)
Rename init_slotdefs() to _PyTypes_InitSlotDefs() and add a return
value of type PyStatus. The function is now called exactly once from
_PyTypes_Init(). Replace calls to init_slotdefs() with an assertion
checking that slotdefs is initialized.
-rw-r--r-- | Include/internal/pycore_pylifecycle.h | 1 | ||||
-rw-r--r-- | Objects/object.c | 6 | ||||
-rw-r--r-- | Objects/typeobject.c | 35 |
3 files changed, 26 insertions, 16 deletions
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 7292349..2dd6149 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -51,6 +51,7 @@ extern int _PyFloat_Init(void); extern PyStatus _Py_HashRandomization_Init(const PyConfig *); extern PyStatus _PyTypes_Init(void); +extern PyStatus _PyTypes_InitSlotDefs(void); extern PyStatus _PyImportZip_Init(PyThreadState *tstate); extern PyStatus _PyGC_Init(PyThreadState *tstate); diff --git a/Objects/object.c b/Objects/object.c index aa84114..c5d28e5 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -6,6 +6,7 @@ #include "pycore_initconfig.h" #include "pycore_object.h" #include "pycore_pyerrors.h" +#include "pycore_pylifecycle.h" #include "pycore_pystate.h" #include "frameobject.h" #include "interpreteridobject.h" @@ -1841,6 +1842,11 @@ PyObject _Py_NotImplementedStruct = { PyStatus _PyTypes_Init(void) { + PyStatus status = _PyTypes_InitSlotDefs(); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + #define INIT_TYPE(TYPE, NAME) \ do { \ if (PyType_Ready(TYPE) < 0) { \ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5773eb7..b095e29 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_call.h" +#include "pycore_initconfig.h" #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" @@ -6932,7 +6933,8 @@ which incorporates the additional structures used for numbers, sequences and mappings. Note that multiple names may map to the same slot (e.g. __eq__, __ne__ etc. all map to tp_richcompare) and one name may map to multiple slots (e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with -an all-zero entry. (This table is further initialized in init_slotdefs().) +an all-zero entry. (This table is further initialized in +_PyTypes_InitSlotDefs().) */ typedef struct wrapperbase slotdef; @@ -7423,28 +7425,29 @@ update_slots_callback(PyTypeObject *type, void *data) static int slotdefs_initialized = 0; /* Initialize the slotdefs table by adding interned string objects for the names. */ -static void -init_slotdefs(void) +PyStatus +_PyTypes_InitSlotDefs(void) { - slotdef *p; + if (slotdefs_initialized) { + return _PyStatus_OK(); + } - if (slotdefs_initialized) - return; - for (p = slotdefs; p->name; p++) { + for (slotdef *p = slotdefs; p->name; p++) { /* Slots must be ordered by their offset in the PyHeapTypeObject. */ assert(!p[1].name || p->offset <= p[1].offset); p->name_strobj = PyUnicode_InternFromString(p->name); - if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) - Py_FatalError("Out of memory interning slotdef names"); + if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) { + return _PyStatus_NO_MEMORY(); + } } slotdefs_initialized = 1; + return _PyStatus_OK(); } -/* Undo init_slotdefs, releasing the interned strings. */ +/* Undo _PyTypes_InitSlotDefs(), releasing the interned strings. */ static void clear_slotdefs(void) { - slotdef *p; - for (p = slotdefs; p->name; p++) { + for (slotdef *p = slotdefs; p->name; p++) { Py_CLEAR(p->name_strobj); } slotdefs_initialized = 0; @@ -7462,7 +7465,7 @@ update_slot(PyTypeObject *type, PyObject *name) assert(PyUnicode_CheckExact(name)); assert(PyUnicode_CHECK_INTERNED(name)); - init_slotdefs(); + assert(slotdefs_initialized); pp = ptrs; for (p = slotdefs; p->name; p++) { if (p->name_strobj == name) @@ -7490,7 +7493,7 @@ fixup_slot_dispatchers(PyTypeObject *type) { slotdef *p; - init_slotdefs(); + assert(slotdefs_initialized); for (p = slotdefs; p->name; ) p = update_one_slot(type, p); } @@ -7503,7 +7506,7 @@ update_all_slots(PyTypeObject* type) /* Clear the VALID_VERSION flag of 'type' and all its subclasses. */ PyType_Modified(type); - init_slotdefs(); + assert(slotdefs_initialized); for (p = slotdefs; p->name; p++) { /* update_slot returns int but can't actually fail */ update_slot(type, p->name_strobj); @@ -7663,7 +7666,7 @@ add_operators(PyTypeObject *type) PyObject *descr; void **ptr; - init_slotdefs(); + assert(slotdefs_initialized); for (p = slotdefs; p->name; p++) { if (p->wrapper == NULL) continue; |