diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 8da0a64a3f90a4..e0a1707348c912 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -44,14 +44,29 @@ pysqlite_new_node(PyObject *key, PyObject *data) return node; } +static int +node_traverse(pysqlite_Node *self, visitproc visit, void *arg) +{ + Py_VISIT(self->key); + Py_VISIT(self->data); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +node_clear(pysqlite_Node *self) +{ + Py_CLEAR(self->key); + Py_CLEAR(self->data); + return 0; +} + static void pysqlite_node_dealloc(pysqlite_Node *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_DECREF(self->key); - Py_DECREF(self->data); - + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -88,31 +103,51 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs) return 0; } -static void -pysqlite_cache_dealloc(pysqlite_Cache *self) +static int +cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); - pysqlite_Node* node; - pysqlite_Node* delete_node; - - if (!self->factory) { - /* constructor failed, just get out of here */ - return; + pysqlite_Node *node = self->first; + while (node) { + Py_VISIT(node); + node = node->next; + } + Py_VISIT(self->mapping); + if (self->decref_factory) { + Py_VISIT(self->factory); } + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cache_clear(pysqlite_Cache *self) +{ /* iterate over all nodes and deallocate them */ - node = self->first; + pysqlite_Node *node = self->first; + self->first = NULL; while (node) { - delete_node = node; + pysqlite_Node *delete_node = node; node = node->next; - Py_DECREF(delete_node); + Py_CLEAR(delete_node); } - if (self->decref_factory) { - Py_DECREF(self->factory); + Py_CLEAR(self->factory); + } + Py_CLEAR(self->mapping); + return 0; +} + +static void +pysqlite_cache_dealloc(pysqlite_Cache *self) +{ + if (!self->factory) { + /* constructor failed, just get out of here */ + return; } - Py_DECREF(self->mapping); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -260,14 +295,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args) static PyType_Slot node_slots[] = { {Py_tp_dealloc, pysqlite_node_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, node_traverse}, + {Py_tp_clear, node_clear}, {0, NULL}, }; static PyType_Spec node_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = node_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -283,15 +319,16 @@ static PyMethodDef cache_methods[] = { static PyType_Slot cache_slots[] = { {Py_tp_dealloc, pysqlite_cache_dealloc}, {Py_tp_methods, cache_methods}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cache_init}, + {Py_tp_traverse, cache_traverse}, + {Py_tp_clear, cache_clear}, {0, NULL}, }; static PyType_Spec cache_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cache_slots, }; PyTypeObject *pysqlite_CacheType = NULL; diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 28932726b74257..47d97d17a91b98 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -225,28 +225,51 @@ pysqlite_do_all_statements(pysqlite_Connection *self, int action, } } +static int +connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) +{ + Py_VISIT(self->statement_cache); + Py_VISIT(self->isolation_level); + Py_VISIT(self->function_pinboard_trace_callback); + Py_VISIT(self->function_pinboard_progress_handler); + Py_VISIT(self->function_pinboard_authorizer_cb); + Py_VISIT(self->row_factory); + Py_VISIT(self->text_factory); + Py_VISIT(self->collations); + Py_VISIT(self->statements); + Py_VISIT(self->cursors); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +connection_clear(pysqlite_Connection *self) +{ + Py_CLEAR(self->statement_cache); + Py_CLEAR(self->isolation_level); + Py_CLEAR(self->function_pinboard_trace_callback); + Py_CLEAR(self->function_pinboard_progress_handler); + Py_CLEAR(self->function_pinboard_authorizer_cb); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->text_factory); + Py_CLEAR(self->collations); + Py_CLEAR(self->statements); + Py_CLEAR(self->cursors); + return 0; +} + static void -pysqlite_connection_dealloc(pysqlite_Connection *self) +connection_dealloc(pysqlite_Connection *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_XDECREF(self->statement_cache); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); /* Clean up if user has not called .close() explicitly. */ if (self->db) { sqlite3_close_v2(self->db); } - Py_XDECREF(self->isolation_level); - Py_XDECREF(self->function_pinboard_trace_callback); - Py_XDECREF(self->function_pinboard_progress_handler); - Py_XDECREF(self->function_pinboard_authorizer_cb); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->text_factory); - Py_XDECREF(self->collations); - Py_XDECREF(self->statements); - Py_XDECREF(self->cursors); - tp->tp_free(self); Py_DECREF(tp); } @@ -1328,7 +1351,7 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType); + statement = PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType); if (!statement) { return NULL; } @@ -1909,21 +1932,22 @@ static struct PyMemberDef connection_members[] = }; static PyType_Slot connection_slots[] = { - {Py_tp_dealloc, pysqlite_connection_dealloc}, + {Py_tp_dealloc, 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}, + {Py_tp_traverse, connection_traverse}, + {Py_tp_clear, connection_clear}, {0, NULL}, }; static PyType_Spec connection_spec = { .name = MODULE_NAME ".Connection", .basicsize = sizeof(pysqlite_Connection), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = connection_slots, }; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index b71f780a0b4dfd..b3e1ce2c04784b 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -81,27 +81,46 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self, return 0; } -static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) +static int +cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); + Py_VISIT(self->connection); + Py_VISIT(self->row_cast_map); + Py_VISIT(self->row_factory); + Py_VISIT(self->next_row); + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cursor_clear(pysqlite_Cursor *self) +{ /* Reset the statement if the user has not closed the cursor */ if (self->statement) { pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); + Py_CLEAR(self->statement); } - Py_XDECREF(self->connection); - Py_XDECREF(self->row_cast_map); - Py_XDECREF(self->description); - Py_XDECREF(self->lastrowid); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->next_row); + Py_CLEAR(self->connection); + Py_CLEAR(self->row_cast_map); + Py_CLEAR(self->description); + Py_CLEAR(self->lastrowid); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->next_row); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} + +static void +cursor_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -487,7 +506,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, pysqlite_StatementType)); + PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType)); if (!self->statement) { goto error; } @@ -1006,21 +1025,22 @@ static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); static PyType_Slot cursor_slots[] = { - {Py_tp_dealloc, pysqlite_cursor_dealloc}, + {Py_tp_dealloc, 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}, + {Py_tp_traverse, cursor_traverse}, + {Py_tp_clear, cursor_clear}, {0, NULL}, }; static PyType_Spec cursor_spec = { .name = MODULE_NAME ".Cursor", .basicsize = sizeof(pysqlite_Cursor), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cursor_slots, }; diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7d2d7ade591467..ece42f4df6f5ac 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -30,26 +30,33 @@ pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args, return 0; } +static int +pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self) { PyTypeObject *tp = Py_TYPE(self); - + PyObject_GC_UnTrack(self); tp->tp_free(self); Py_DECREF(tp); } static PyType_Slot type_slots[] = { {Py_tp_dealloc, pysqlite_prepare_protocol_dealloc}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_prepare_protocol_init}, + {Py_tp_traverse, pysqlite_prepare_protocol_traverse}, {0, NULL}, }; static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = type_slots, }; diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index f9dfcbd5d615e5..af8be803c805a5 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -31,14 +31,29 @@ class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ -static void -pysqlite_row_dealloc(pysqlite_Row *self) +static int +row_clear(pysqlite_Row *self) { - PyTypeObject *tp = Py_TYPE(self); + Py_CLEAR(self->data); + Py_CLEAR(self->description); + return 0; +} - Py_XDECREF(self->data); - Py_XDECREF(self->description); +static int +row_traverse(pysqlite_Row *self, visitproc visit, void *arg) +{ + Py_VISIT(self->data); + Py_VISIT(self->description); + Py_VISIT(Py_TYPE(self)); + return 0; +} +static void +pysqlite_row_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -231,13 +246,15 @@ static PyType_Slot row_slots[] = { {Py_sq_length, pysqlite_row_length}, {Py_sq_item, pysqlite_row_item}, {Py_tp_new, pysqlite_row_new}, + {Py_tp_traverse, row_traverse}, + {Py_tp_clear, row_clear}, {0, NULL}, }; static PyType_Spec row_spec = { .name = MODULE_NAME ".Row", .basicsize = sizeof(pysqlite_Row), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = row_slots, }; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 57026270e1eeb5..3be12c79b47d9a 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -369,26 +369,38 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) } static void -pysqlite_statement_dealloc(pysqlite_Statement *self) +stmt_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); +} +static int +stmt_clear(pysqlite_Statement *self) +{ if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); Py_END_ALLOW_THREADS + self->st = 0; } - self->st = NULL; - - Py_XDECREF(self->sql); - + Py_CLEAR(self->sql); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} - tp->tp_free(self); - Py_DECREF(tp); +static int +stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) +{ + Py_VISIT(self->sql); + Py_VISIT(Py_TYPE(self)); + return 0; } /* @@ -467,15 +479,16 @@ static PyMemberDef stmt_members[] = { }; static PyType_Slot stmt_slots[] = { {Py_tp_members, stmt_members}, - {Py_tp_dealloc, pysqlite_statement_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_dealloc, stmt_dealloc}, + {Py_tp_traverse, stmt_traverse}, + {Py_tp_clear, stmt_clear}, {0, NULL}, }; static PyType_Spec stmt_spec = { .name = MODULE_NAME ".Statement", .basicsize = sizeof(pysqlite_Statement), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = stmt_slots, }; PyTypeObject *pysqlite_StatementType = NULL;
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: