From 26f91999b453563839466322164e566781f10ccd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Jul 2013 01:22:45 +0200 Subject: [PATCH] Close #18469: Replace PyDict_GetItemString() with _PyDict_GetItemId() in structseq.c _PyDict_GetItemId() is more efficient: it only builds the Unicode string once. Identifiers (dictionary keys) are now created at Python initialization, and if the creation failed, Python does exit with a fatal error. Before, PyDict_GetItemString() failure was not handled: structseq_new() could call PyObject_GC_NewVar() with a negative size, and structseq_dealloc() could also crash. --- Objects/structseq.c | 25 ++++++++++++++++++++----- Python/pythonrun.c | 3 +++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Objects/structseq.c b/Objects/structseq.c index c3b9a72989..212ab52d42 100644 --- a/Objects/structseq.c +++ b/Objects/structseq.c @@ -11,17 +11,20 @@ static char unnamed_fields_key[] = "n_unnamed_fields"; /* Fields with this name have only a field index, not a field name. They are only allowed for indices < n_visible_fields. */ char *PyStructSequence_UnnamedField = "unnamed field"; +_Py_IDENTIFIER(n_sequence_fields); +_Py_IDENTIFIER(n_fields); +_Py_IDENTIFIER(n_unnamed_fields); #define VISIBLE_SIZE(op) Py_SIZE(op) #define VISIBLE_SIZE_TP(tp) PyLong_AsLong( \ - PyDict_GetItemString((tp)->tp_dict, visible_length_key)) + _PyDict_GetItemId((tp)->tp_dict, &PyId_n_sequence_fields)) #define REAL_SIZE_TP(tp) PyLong_AsLong( \ - PyDict_GetItemString((tp)->tp_dict, real_length_key)) + _PyDict_GetItemId((tp)->tp_dict, &PyId_n_fields)) #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op)) #define UNNAMED_FIELDS_TP(tp) PyLong_AsLong( \ - PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key)) + _PyDict_GetItemId((tp)->tp_dict, &PyId_n_unnamed_fields)) #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op)) @@ -59,7 +62,7 @@ static void structseq_dealloc(PyStructSequence *obj) { Py_ssize_t i, size; - + size = REAL_SIZE(obj); for (i = 0; i < size; ++i) { Py_XDECREF(obj->ob_item[i]); @@ -382,9 +385,21 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc) PyTypeObject* PyStructSequence_NewType(PyStructSequence_Desc *desc) { - PyTypeObject *result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); + PyTypeObject *result; + + result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); if (result != NULL) { PyStructSequence_InitType(result, desc); } return result; } + +int _PyStructSequence_Init(void) +{ + if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL + || _PyUnicode_FromId(&PyId_n_fields) == NULL + || _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL) + return -1; + + return 0; +} diff --git a/Python/pythonrun.c b/Python/pythonrun.c index d95a09d4a7..814220b40e 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -86,6 +86,7 @@ static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(void); extern int _PyUnicode_Init(void); +extern int _PyStructSequence_Init(void); extern void _PyUnicode_Fini(void); extern int _PyLong_Init(void); extern void PyLong_Fini(void); @@ -336,6 +337,8 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) /* Init Unicode implementation; relies on the codec registry */ if (_PyUnicode_Init() < 0) Py_FatalError("Py_Initialize: can't initialize unicode"); + if (_PyStructSequence_Init() < 0) + Py_FatalError("Py_Initialize: can't initialize structseq"); bimod = _PyBuiltin_Init(); if (bimod == NULL) -- 2.40.0