mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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.
This commit is contained in:
parent
5eb8bff7e4
commit
7a1f6c2da4
3 changed files with 26 additions and 16 deletions
|
@ -51,6 +51,7 @@ extern int _PyFloat_Init(void);
|
||||||
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
|
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
|
||||||
|
|
||||||
extern PyStatus _PyTypes_Init(void);
|
extern PyStatus _PyTypes_Init(void);
|
||||||
|
extern PyStatus _PyTypes_InitSlotDefs(void);
|
||||||
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
|
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
|
||||||
extern PyStatus _PyGC_Init(PyThreadState *tstate);
|
extern PyStatus _PyGC_Init(PyThreadState *tstate);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
#include "pycore_pyerrors.h"
|
#include "pycore_pyerrors.h"
|
||||||
|
#include "pycore_pylifecycle.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
#include "interpreteridobject.h"
|
#include "interpreteridobject.h"
|
||||||
|
@ -1841,6 +1842,11 @@ PyObject _Py_NotImplementedStruct = {
|
||||||
PyStatus
|
PyStatus
|
||||||
_PyTypes_Init(void)
|
_PyTypes_Init(void)
|
||||||
{
|
{
|
||||||
|
PyStatus status = _PyTypes_InitSlotDefs();
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
#define INIT_TYPE(TYPE, NAME) \
|
#define INIT_TYPE(TYPE, NAME) \
|
||||||
do { \
|
do { \
|
||||||
if (PyType_Ready(TYPE) < 0) { \
|
if (PyType_Ready(TYPE) < 0) { \
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_call.h"
|
#include "pycore_call.h"
|
||||||
|
#include "pycore_initconfig.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
#include "pycore_pyerrors.h"
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pystate.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__,
|
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
|
__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
|
(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;
|
typedef struct wrapperbase slotdef;
|
||||||
|
@ -7423,28 +7425,29 @@ update_slots_callback(PyTypeObject *type, void *data)
|
||||||
static int slotdefs_initialized = 0;
|
static int slotdefs_initialized = 0;
|
||||||
/* Initialize the slotdefs table by adding interned string objects for the
|
/* Initialize the slotdefs table by adding interned string objects for the
|
||||||
names. */
|
names. */
|
||||||
static void
|
PyStatus
|
||||||
init_slotdefs(void)
|
_PyTypes_InitSlotDefs(void)
|
||||||
{
|
{
|
||||||
slotdef *p;
|
if (slotdefs_initialized) {
|
||||||
|
return _PyStatus_OK();
|
||||||
|
}
|
||||||
|
|
||||||
if (slotdefs_initialized)
|
for (slotdef *p = slotdefs; p->name; p++) {
|
||||||
return;
|
|
||||||
for (p = slotdefs; p->name; p++) {
|
|
||||||
/* Slots must be ordered by their offset in the PyHeapTypeObject. */
|
/* Slots must be ordered by their offset in the PyHeapTypeObject. */
|
||||||
assert(!p[1].name || p->offset <= p[1].offset);
|
assert(!p[1].name || p->offset <= p[1].offset);
|
||||||
p->name_strobj = PyUnicode_InternFromString(p->name);
|
p->name_strobj = PyUnicode_InternFromString(p->name);
|
||||||
if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj))
|
if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) {
|
||||||
Py_FatalError("Out of memory interning slotdef names");
|
return _PyStatus_NO_MEMORY();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
slotdefs_initialized = 1;
|
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)
|
static void clear_slotdefs(void)
|
||||||
{
|
{
|
||||||
slotdef *p;
|
for (slotdef *p = slotdefs; p->name; p++) {
|
||||||
for (p = slotdefs; p->name; p++) {
|
|
||||||
Py_CLEAR(p->name_strobj);
|
Py_CLEAR(p->name_strobj);
|
||||||
}
|
}
|
||||||
slotdefs_initialized = 0;
|
slotdefs_initialized = 0;
|
||||||
|
@ -7462,7 +7465,7 @@ update_slot(PyTypeObject *type, PyObject *name)
|
||||||
assert(PyUnicode_CheckExact(name));
|
assert(PyUnicode_CheckExact(name));
|
||||||
assert(PyUnicode_CHECK_INTERNED(name));
|
assert(PyUnicode_CHECK_INTERNED(name));
|
||||||
|
|
||||||
init_slotdefs();
|
assert(slotdefs_initialized);
|
||||||
pp = ptrs;
|
pp = ptrs;
|
||||||
for (p = slotdefs; p->name; p++) {
|
for (p = slotdefs; p->name; p++) {
|
||||||
if (p->name_strobj == name)
|
if (p->name_strobj == name)
|
||||||
|
@ -7490,7 +7493,7 @@ fixup_slot_dispatchers(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
slotdef *p;
|
slotdef *p;
|
||||||
|
|
||||||
init_slotdefs();
|
assert(slotdefs_initialized);
|
||||||
for (p = slotdefs; p->name; )
|
for (p = slotdefs; p->name; )
|
||||||
p = update_one_slot(type, p);
|
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. */
|
/* Clear the VALID_VERSION flag of 'type' and all its subclasses. */
|
||||||
PyType_Modified(type);
|
PyType_Modified(type);
|
||||||
|
|
||||||
init_slotdefs();
|
assert(slotdefs_initialized);
|
||||||
for (p = slotdefs; p->name; p++) {
|
for (p = slotdefs; p->name; p++) {
|
||||||
/* update_slot returns int but can't actually fail */
|
/* update_slot returns int but can't actually fail */
|
||||||
update_slot(type, p->name_strobj);
|
update_slot(type, p->name_strobj);
|
||||||
|
@ -7663,7 +7666,7 @@ add_operators(PyTypeObject *type)
|
||||||
PyObject *descr;
|
PyObject *descr;
|
||||||
void **ptr;
|
void **ptr;
|
||||||
|
|
||||||
init_slotdefs();
|
assert(slotdefs_initialized);
|
||||||
for (p = slotdefs; p->name; p++) {
|
for (p = slotdefs; p->name; p++) {
|
||||||
if (p->wrapper == NULL)
|
if (p->wrapper == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue