Skip to content

Commit e56ab74

Browse files
orenmnvstinner
authored andcommitted
bpo-31770: Prevent a crash and refleaks when calling sqlite3.Cursor.__init__() more than once (#3968)
1 parent ad455cd commit e56ab74

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

Lib/sqlite3/test/regression.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import datetime
2525
import unittest
2626
import sqlite3 as sqlite
27+
import weakref
28+
from test import support
2729

2830
class RegressionTests(unittest.TestCase):
2931
def setUp(self):
@@ -376,6 +378,22 @@ def CheckCommitCursorReset(self):
376378
counter += 1
377379
self.assertEqual(counter, 3, "should have returned exactly three rows")
378380

381+
def CheckBpo31770(self):
382+
"""
383+
The interpreter shouldn't crash in case Cursor.__init__() is called
384+
more than once.
385+
"""
386+
def callback(*args):
387+
pass
388+
con = sqlite.connect(":memory:")
389+
cur = sqlite.Cursor(con)
390+
ref = weakref.ref(cur, callback)
391+
cur.__init__(con)
392+
del cur
393+
# The interpreter shouldn't crash when ref is collected.
394+
del ref
395+
support.gc_collect()
396+
379397

380398
def suite():
381399
regression_suite = unittest.makeSuite(RegressionTests, "Check")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent a crash when calling the ``__init__()`` method of a
2+
``sqlite3.Cursor`` object more than once. Patch by Oren Milman.

Modules/_sqlite/cursor.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,20 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
3939
}
4040

4141
Py_INCREF(connection);
42-
self->connection = connection;
43-
self->statement = NULL;
44-
self->next_row = NULL;
45-
self->in_weakreflist = NULL;
42+
Py_XSETREF(self->connection, connection);
43+
Py_CLEAR(self->statement);
44+
Py_CLEAR(self->next_row);
4645

47-
self->row_cast_map = PyList_New(0);
46+
Py_XSETREF(self->row_cast_map, PyList_New(0));
4847
if (!self->row_cast_map) {
4948
return -1;
5049
}
5150

5251
Py_INCREF(Py_None);
53-
self->description = Py_None;
52+
Py_XSETREF(self->description, Py_None);
5453

5554
Py_INCREF(Py_None);
56-
self->lastrowid= Py_None;
55+
Py_XSETREF(self->lastrowid, Py_None);
5756

5857
self->arraysize = 1;
5958
self->closed = 0;
@@ -62,7 +61,7 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
6261
self->rowcount = -1L;
6362

6463
Py_INCREF(Py_None);
65-
self->row_factory = Py_None;
64+
Py_XSETREF(self->row_factory, Py_None);
6665

6766
if (!pysqlite_check_thread(self->connection)) {
6867
return -1;

0 commit comments

Comments
 (0)