Skip to content

Commit ad2f3b7

Browse files
bpo-44304: Fix crash in the sqlite3 module when the GC clears Statement objects (GH-26545)
(cherry picked from commit fa106a6) Co-authored-by: Pablo Galindo <[email protected]>
1 parent 4642caf commit ad2f3b7

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
@@ -397,6 +397,10 @@ stmt_dealloc(pysqlite_Statement *self)
397397
if (self->in_weakreflist != NULL) {
398398
PyObject_ClearWeakRefs((PyObject*)self);
399399
}
400+
if (self->st) {
401+
sqlite3_finalize(self->st);
402+
self->st = 0;
403+
}
400404
tp->tp_clear((PyObject *)self);
401405
tp->tp_free(self);
402406
Py_DECREF(tp);
@@ -405,13 +409,6 @@ stmt_dealloc(pysqlite_Statement *self)
405409
static int
406410
stmt_clear(pysqlite_Statement *self)
407411
{
408-
if (self->st) {
409-
Py_BEGIN_ALLOW_THREADS
410-
sqlite3_finalize(self->st);
411-
Py_END_ALLOW_THREADS
412-
self->st = 0;
413-
}
414-
415412
Py_CLEAR(self->sql);
416413
return 0;
417414
}

0 commit comments

Comments
 (0)