This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Oren Milman
Recipients Oren Milman
Date 2017-10-12.08:18:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1507796316.87.0.213398074469.issue31770@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2017-10-12 08:18:36Oren Milmansetrecipients: + Oren Milman
2017-10-12 08:18:36Oren Milmansetmessageid: <1507796316.87.0.213398074469.issue31770@psf.upfronthosting.co.za>
2017-10-12 08:18:36Oren Milmanlinkissue31770 messages
2017-10-12 08:18:36Oren Milmancreate