Skip to content

Commit 110140b

Browse files
committed
Revert the fix for code that doesn't call __init__on Cursor/Connection, keeping the underlying delattr guards
1 parent f09a339 commit 110140b

4 files changed

Lines changed: 13 additions & 76 deletions

File tree

Lib/test/test_sqlite3/test_factory.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -164,35 +164,6 @@ def test_delete_cursor_row_factory(self):
164164
# Executing a query here should succeed.
165165
self.assertEqual(tuple(cur.execute("select 1").fetchone()), (1,))
166166

167-
def test_uninitialized_connection_factories(self):
168-
# gh-152817: skipping __init__() should still result in initialized factories (None not Null)
169-
con = sqlite.Connection.__new__(sqlite.Connection)
170-
self.assertIsNone(con.row_factory)
171-
self.assertIs(con.text_factory, str)
172-
173-
def test_uninitialized_cursor_row_factory(self):
174-
# gh-152817: skipping __init__() should still result in initialized factories (None not Null)
175-
# __init__ must not crash.
176-
cur = sqlite.Cursor.__new__(sqlite.Cursor)
177-
self.assertIsNone(cur.row_factory)
178-
179-
def test_subclass_skipping_super_init(self):
180-
# gh-152817: forgetting to call super().__init__() shouldn't leave a NULL {row,text}_factory
181-
class Connection(sqlite.Connection):
182-
def __init__(self, *args, **kwargs):
183-
pass
184-
185-
class Cursor(sqlite.Cursor):
186-
def __init__(self, *args, **kwargs):
187-
pass
188-
189-
con = Connection(":memory:")
190-
self.assertIsNone(con.row_factory)
191-
self.assertIs(con.text_factory, str)
192-
193-
cur = Cursor(self.con)
194-
self.assertIsNone(cur.row_factory)
195-
196167
def test_sqlite_row_index_unicode(self):
197168
row = self.con.execute("select 1 as \xff").fetchone()
198169
self.assertEqual(row["\xff"], 1)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
:mod:`sqlite3`: Prevent crashes caused by ``row_factory`` or ``text_factory`` being uninitialized, either
2-
by skipping ``__init__`` or by deleting the attributes.
1+
:mod:`sqlite3`: Disallow removing ``row_factory`` and ``text_factory`` attributes
2+
of a connection or cursor to prevent a crash on a query.

Modules/_sqlite/connection.c

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,8 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
300300
self->thread_ident = PyThread_get_thread_ident();
301301
self->statement_cache = statement_cache;
302302
self->blobs = blobs;
303-
// re-initialize the factory members here, as tp_clear() is called above in some cases
304-
Py_XSETREF(self->row_factory, Py_NewRef(Py_None));
305-
Py_XSETREF(self->text_factory, Py_NewRef((PyObject *)&PyUnicode_Type));
303+
self->row_factory = Py_NewRef(Py_None);
304+
self->text_factory = Py_NewRef(&PyUnicode_Type);
306305
self->trace_ctx = NULL;
307306
self->progress_ctx = NULL;
308307
self->authorizer_ctx = NULL;
@@ -340,19 +339,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
340339
return -1;
341340
}
342341

343-
static PyObject *
344-
pysqlite_connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
345-
{
346-
pysqlite_Connection *self = (pysqlite_Connection *)type->tp_alloc(type, 0);
347-
if (self == NULL) {
348-
return NULL;
349-
}
350-
// row_factory and text_factory should never be uninitialized, even if tp_init is bypassed.
351-
self->row_factory = Py_NewRef(Py_None);
352-
self->text_factory = Py_NewRef((PyObject *)&PyUnicode_Type);
353-
return (PyObject *)self;
354-
}
355-
356342
/*[clinic input]
357343
# Create a new destination 'connect' for the docstring and methoddef only.
358344
# This makes it possible to keep the signatures for Connection.__init__ and
@@ -563,7 +549,7 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
563549
return NULL;
564550
}
565551

566-
if (cursor && self->row_factory != NULL && !Py_IsNone(self->row_factory)) {
552+
if (cursor && self->row_factory != Py_None) {
567553
Py_INCREF(self->row_factory);
568554
Py_XSETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
569555
}
@@ -575,8 +561,7 @@ static PyObject *
575561
connection_get_row_factory(PyObject *op, void *closure)
576562
{
577563
pysqlite_Connection *self = (pysqlite_Connection *)op;
578-
PyObject *row_factory = self->row_factory;
579-
return Py_NewRef(row_factory != NULL ? row_factory : Py_None);
564+
return Py_NewRef(self->row_factory);
580565
}
581566

582567
static int
@@ -596,9 +581,7 @@ static PyObject *
596581
connection_get_text_factory(PyObject *op, void *closure)
597582
{
598583
pysqlite_Connection *self = (pysqlite_Connection *)op;
599-
PyObject *text_factory = self->text_factory;
600-
return Py_NewRef(text_factory != NULL ? text_factory
601-
: (PyObject *)&PyUnicode_Type);
584+
return Py_NewRef(self->text_factory);
602585
}
603586

604587
static int
@@ -2739,7 +2722,6 @@ static PyType_Slot connection_slots[] = {
27392722
{Py_tp_methods, connection_methods},
27402723
{Py_tp_members, connection_members},
27412724
{Py_tp_getset, connection_getset},
2742-
{Py_tp_new, pysqlite_connection_new},
27432725
{Py_tp_init, pysqlite_connection_init},
27442726
{Py_tp_call, pysqlite_connection_call},
27452727
{Py_tp_traverse, connection_traverse},

Modules/_sqlite/cursor.c

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,6 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
143143
return 0;
144144
}
145145

146-
static PyObject *
147-
pysqlite_cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
148-
{
149-
pysqlite_Cursor *self = (pysqlite_Cursor *)type->tp_alloc(type, 0);
150-
if (self == NULL) {
151-
return NULL;
152-
}
153-
// row_factory should never be uninitialized, even if tp_init is bypassed.
154-
self->row_factory = Py_NewRef(Py_None);
155-
return (PyObject *)self;
156-
}
157-
158146
static inline int
159147
stmt_reset(pysqlite_Statement *self)
160148
{
@@ -425,9 +413,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
425413
}
426414

427415
nbytes = sqlite3_column_bytes(self->statement->st, i);
428-
PyObject *text_factory = self->connection->text_factory;
429-
if (text_factory == NULL ||
430-
text_factory == (PyObject*)&PyUnicode_Type) {
416+
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
431417
converted = PyUnicode_FromStringAndSize(text, nbytes);
432418
if (!converted && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
433419
PyErr_Clear();
@@ -448,12 +434,12 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
448434
Py_DECREF(error_msg);
449435
}
450436
}
451-
} else if (text_factory == (PyObject*)&PyBytes_Type) {
437+
} else if (self->connection->text_factory == (PyObject*)&PyBytes_Type) {
452438
converted = PyBytes_FromStringAndSize(text, nbytes);
453-
} else if (text_factory == (PyObject*)&PyByteArray_Type) {
439+
} else if (self->connection->text_factory == (PyObject*)&PyByteArray_Type) {
454440
converted = PyByteArray_FromStringAndSize(text, nbytes);
455441
} else {
456-
converted = PyObject_CallFunction(text_factory, "y#", text, nbytes);
442+
converted = PyObject_CallFunction(self->connection->text_factory, "y#", text, nbytes);
457443
}
458444
} else {
459445
/* coltype == SQLITE_BLOB */
@@ -1190,7 +1176,7 @@ pysqlite_cursor_iternext(PyObject *op)
11901176
}
11911177
return NULL;
11921178
}
1193-
if (self->row_factory != NULL && !Py_IsNone(self->row_factory)) {
1179+
if (!Py_IsNone(self->row_factory)) {
11941180
PyObject *factory = self->row_factory;
11951181
PyObject *args[] = { op, row, };
11961182
PyObject *new_row = PyObject_Vectorcall(factory, args, 2, NULL);
@@ -1422,8 +1408,7 @@ static PyObject *
14221408
cursor_get_row_factory(PyObject *op, void *closure)
14231409
{
14241410
pysqlite_Cursor *self = (pysqlite_Cursor *)op;
1425-
PyObject *row_factory = self->row_factory;
1426-
return Py_NewRef(row_factory != NULL ? row_factory : Py_None);
1411+
return Py_NewRef(self->row_factory);
14271412
}
14281413

14291414
static int
@@ -1456,7 +1441,6 @@ static PyType_Slot cursor_slots[] = {
14561441
{Py_tp_methods, cursor_methods},
14571442
{Py_tp_members, cursor_members},
14581443
{Py_tp_getset, cursor_getsets},
1459-
{Py_tp_new, pysqlite_cursor_new},
14601444
{Py_tp_init, pysqlite_cursor_init},
14611445
{Py_tp_traverse, cursor_traverse},
14621446
{Py_tp_clear, cursor_clear},

0 commit comments

Comments
 (0)