From 256e54acdbdb26745d4bbb5cf366454151e42773 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Thu, 1 Oct 2020 16:03:21 +0200 Subject: [PATCH] bpo-41861: Convert _sqlite3 CursorType and ConnectionType to heap types (GH-22478) --- Modules/_sqlite/connection.c | 80 +++++++++++++++--------------------- Modules/_sqlite/connection.h | 4 +- Modules/_sqlite/cursor.c | 76 ++++++++++++++-------------------- Modules/_sqlite/cursor.h | 4 +- Modules/_sqlite/module.c | 10 ++--- Modules/_sqlite/row.c | 2 +- 6 files changed, 74 insertions(+), 102 deletions(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 91e9046f50c..69203f85e05 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -220,6 +220,8 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset void pysqlite_connection_dealloc(pysqlite_Connection* self) { + PyTypeObject *tp = Py_TYPE(self); + Py_XDECREF(self->statement_cache); /* Clean up if user has not called .close() explicitly. */ @@ -236,7 +238,9 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self) Py_XDECREF(self->collations); Py_XDECREF(self->statements); Py_XDECREF(self->cursors); - Py_TYPE(self)->tp_free((PyObject*)self); + + tp->tp_free(self); + Py_DECREF(tp); } /* @@ -281,13 +285,13 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, } if (factory == NULL) { - factory = (PyObject*)&pysqlite_CursorType; + factory = (PyObject*)pysqlite_CursorType; } cursor = PyObject_CallOneArg(factory, (PyObject *)self); if (cursor == NULL) return NULL; - if (!PyObject_TypeCheck(cursor, &pysqlite_CursorType)) { + if (!PyObject_TypeCheck(cursor, pysqlite_CursorType)) { PyErr_Format(PyExc_TypeError, "factory must return a cursor, not %.100s", Py_TYPE(cursor)->tp_name); @@ -1494,7 +1498,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords, - &pysqlite_ConnectionType, &target, + pysqlite_ConnectionType, &target, &pages, &progress, &name, &sleep_obj)) { return NULL; } @@ -1831,50 +1835,32 @@ static struct PyMemberDef connection_members[] = {NULL} }; -PyTypeObject pysqlite_ConnectionType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Connection", /* tp_name */ - sizeof(pysqlite_Connection), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_connection_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)pysqlite_connection_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - connection_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - connection_methods, /* tp_methods */ - connection_members, /* tp_members */ - connection_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_connection_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot connection_slots[] = { + {Py_tp_dealloc, pysqlite_connection_dealloc}, + {Py_tp_doc, (void *)connection_doc}, + {Py_tp_methods, connection_methods}, + {Py_tp_members, connection_members}, + {Py_tp_getset, connection_getset}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_init, pysqlite_connection_init}, + {Py_tp_call, pysqlite_connection_call}, + {0, NULL}, }; -extern int pysqlite_connection_setup_types(void) +static PyType_Spec connection_spec = { + .name = MODULE_NAME ".Connection", + .basicsize = sizeof(pysqlite_Connection), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = connection_slots, +}; + +PyTypeObject *pysqlite_ConnectionType = NULL; + +extern int pysqlite_connection_setup_types(PyObject *module) { - pysqlite_ConnectionType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_ConnectionType); + pysqlite_ConnectionType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &connection_spec, NULL); + if (pysqlite_ConnectionType == NULL) { + return -1; + } + return 0; } diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 206085e00a0..aadf439034f 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -106,7 +106,7 @@ typedef struct PyObject* NotSupportedError; } pysqlite_Connection; -extern PyTypeObject pysqlite_ConnectionType; +extern PyTypeObject *pysqlite_ConnectionType; PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); void pysqlite_connection_dealloc(pysqlite_Connection* self); @@ -122,6 +122,6 @@ int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObjec int pysqlite_check_thread(pysqlite_Connection* self); int pysqlite_check_connection(pysqlite_Connection* con); -int pysqlite_connection_setup_types(void); +int pysqlite_connection_setup_types(PyObject *module); #endif diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index dbbdb12cadd..3c09c1c6b7e 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -33,7 +33,7 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* { pysqlite_Connection* connection; - if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) + if (!PyArg_ParseTuple(args, "O!", pysqlite_ConnectionType, &connection)) { return -1; } @@ -74,6 +74,8 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) { + PyTypeObject *tp = Py_TYPE(self); + /* Reset the statement if the user has not closed the cursor */ if (self->statement) { pysqlite_statement_reset(self->statement); @@ -91,7 +93,8 @@ static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) PyObject_ClearWeakRefs((PyObject*)self); } - Py_TYPE(self)->tp_free((PyObject*)self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -898,56 +901,39 @@ static struct PyMemberDef cursor_members[] = {"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY}, {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), READONLY}, {NULL} }; static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); -PyTypeObject pysqlite_CursorType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Cursor", /* tp_name */ - sizeof(pysqlite_Cursor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_cursor_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - cursor_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */ - cursor_methods, /* tp_methods */ - cursor_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_cursor_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot cursor_slots[] = { + {Py_tp_dealloc, pysqlite_cursor_dealloc}, + {Py_tp_doc, (void *)cursor_doc}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, pysqlite_cursor_iternext}, + {Py_tp_methods, cursor_methods}, + {Py_tp_members, cursor_members}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_init, pysqlite_cursor_init}, + {0, NULL}, }; -extern int pysqlite_cursor_setup_types(void) +static PyType_Spec cursor_spec = { + .name = MODULE_NAME ".Cursor", + .basicsize = sizeof(pysqlite_Cursor), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = cursor_slots, +}; + +PyTypeObject *pysqlite_CursorType = NULL; + +extern int pysqlite_cursor_setup_types(PyObject *module) { - pysqlite_CursorType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_CursorType); + pysqlite_CursorType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &cursor_spec, NULL); + if (pysqlite_CursorType == NULL) { + return -1; + } + return 0; } diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h index 4a20e756f78..3e6cde167f9 100644 --- a/Modules/_sqlite/cursor.h +++ b/Modules/_sqlite/cursor.h @@ -52,7 +52,7 @@ typedef struct PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Cursor; -extern PyTypeObject pysqlite_CursorType; +extern PyTypeObject *pysqlite_CursorType; PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); @@ -64,7 +64,7 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args); PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args); -int pysqlite_cursor_setup_types(void); +int pysqlite_cursor_setup_types(PyObject *module); #define UNKNOWN (-1) #endif diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 8ac9ea84773..102026663ab 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -82,7 +82,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* } if (factory == NULL) { - factory = (PyObject*)&pysqlite_ConnectionType; + factory = (PyObject*)pysqlite_ConnectionType; } if (PySys_Audit("sqlite3.connect", "O", database) < 0) { @@ -353,8 +353,8 @@ PyMODINIT_FUNC PyInit__sqlite3(void) if (!module || (pysqlite_row_setup_types(module) < 0) || - (pysqlite_cursor_setup_types() < 0) || - (pysqlite_connection_setup_types() < 0) || + (pysqlite_cursor_setup_types(module) < 0) || + (pysqlite_connection_setup_types(module) < 0) || (pysqlite_cache_setup_types(module) < 0) || (pysqlite_statement_setup_types(module) < 0) || (pysqlite_prepare_protocol_setup_types(module) < 0) @@ -363,8 +363,8 @@ PyMODINIT_FUNC PyInit__sqlite3(void) return NULL; } - ADD_TYPE(module, pysqlite_ConnectionType); - ADD_TYPE(module, pysqlite_CursorType); + ADD_TYPE(module, *pysqlite_ConnectionType); + ADD_TYPE(module, *pysqlite_CursorType); ADD_TYPE(module, *pysqlite_PrepareProtocolType); ADD_TYPE(module, *pysqlite_RowType); diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 85179e7f4df..76b6f04f0cc 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -49,7 +49,7 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) return NULL; - if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { + if (!PyObject_TypeCheck((PyObject*)cursor, pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); return NULL; }