Skip to content

Commit fa106a6

Browse files
authored
bpo-44304: Fix crash in the sqlite3 module when the GC clears Statement objects (GH-26545)
1 parent f171877 commit fa106a6

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

Lib/sqlite3/test/userfunctions.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import unittest
2525
import unittest.mock
26+
import gc
2627
import sqlite3 as sqlite
2728

2829
def func_returntext():
@@ -322,6 +323,22 @@ def test_func_deterministic_keyword_only(self):
322323
with self.assertRaises(TypeError):
323324
self.con.create_function("deterministic", 0, int, True)
324325

326+
def test_function_destructor_via_gc(self):
327+
# See bpo-44304: The destructor of the user function can
328+
# crash if is called without the GIL from the gc functions
329+
dest = sqlite.connect(':memory:')
330+
def md5sum(t):
331+
return
332+
333+
dest.create_function("md5", 1, md5sum)
334+
x = dest("create table lang (name, first_appeared)")
335+
del md5sum, dest
336+
337+
y = [x]
338+
y.append(y)
339+
340+
del x,y
341+
gc.collect()
325342

326343
class AggregateTests(unittest.TestCase):
327344
def setUp(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in the :mod:`sqlite3` module that happened when the garbage
2+
collector clears :class:`sqlite.Statement` objects. Patch by Pablo Galindo

Modules/_sqlite/statement.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,10 @@ stmt_dealloc(pysqlite_Statement *self)
403403
if (self->in_weakreflist != NULL) {
404404
PyObject_ClearWeakRefs((PyObject*)self);
405405
}
406+
if (self->st) {
407+
sqlite3_finalize(self->st);
408+
self->st = 0;
409+
}
406410
tp->tp_clear((PyObject *)self);
407411
tp->tp_free(self);
408412
Py_DECREF(tp);
@@ -411,13 +415,6 @@ stmt_dealloc(pysqlite_Statement *self)
411415
static int
412416
stmt_clear(pysqlite_Statement *self)
413417
{
414-
if (self->st) {
415-
Py_BEGIN_ALLOW_THREADS
416-
sqlite3_finalize(self->st);
417-
Py_END_ALLOW_THREADS
418-
self->st = 0;
419-
}
420-
421418
Py_CLEAR(self->sql);
422419
return 0;
423420
}

0 commit comments

Comments
 (0)