Issue 31770: crash and refleaks when calling sqlite3.Cursor.init() more than once (original) (raw)
The following code crashes: import sqlite3 import weakref def callback(*args): pass
connection = sqlite3.connect(":memory:") cursor = sqlite3.Cursor(connection) ref = weakref.ref(cursor, callback) cursor.init(connection) del cursor del ref
IIUC, this is because pysqlite_cursor_init() (in Modules/_sqlite/cursor.c) sets
self->in_weakreflist
to NULL, and thus corrupts the weakref list. Later,
clear_weakref() (in Objects/weakrefobject.c) tries to remove a reference from
the corrupted list, and crashes.
In every other place (that i saw) where such a weakreflist field is used, it is
set to NULL right after allocating the object (usually in new()), or just
not set at all, e.g. in functools.partial
.
So since PyType_GenericNew() is the new() of sqlite3.Cursor, ISTM that the
simplest solution is to not touch self->in_weakreflist
at all in
pysqlite_cursor_init().
Also, the following code results in refleaks: import sys import sqlite3 connection = sqlite3.connect(":memory:") cursor = sqlite3.Cursor(connection) refcount_before = sys.gettotalrefcount() cursor.init(connection) print(sys.gettotalrefcount() - refcount_before) # should be close to 0
This is because pysqlite_cursor_init() doesn't decref before assigning to
fields of self
.
I would open a PR to fix this soon.