Title: crash and refleaks when calling sqlite3.Cursor.__init__() more than once
Type: crash Stage: patch review
Components: Extension Modules Versions: Python 3.7
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Oren Milman, haypo
Priority: normal Keywords: patch

Created on 2017-10-12 08:18 by Oren Milman, last changed 2017-10-12 16:26 by Oren Milman.

Pull Requests
URL Status Linked Edit
PR 3968 open Oren Milman, 2017-10-12 16:26
Messages (1)
msg304220 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-10-12 08:18
The following code crashes:
import sqlite3
import weakref
def callback(*args):

connection = sqlite3.connect(":memory:")
cursor = sqlite3.Cursor(connection)
ref = weakref.ref(cursor, callback)
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

Also, the following code results in refleaks:
import sys
import sqlite3
connection = sqlite3.connect(":memory:")
cursor = sqlite3.Cursor(connection)
refcount_before = sys.gettotalrefcount()
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.
Date User Action Args
2017-10-12 16:26:25Oren Milmansetkeywords: + patch
stage: patch review
pull_requests: + pull_request3946
2017-10-12 08:37:26hayposetnosy: + haypo
2017-10-12 08:18:36Oren Milmancreate