mirror of
https://github.com/python/cpython.git
synced 2026-06-04 16:50:51 +00:00
gh-149738: Fix segmentation fault bug in sqllite3 (#149754)
Deleting the `row_factory` or `text_factory` attribute is no longer allowed.
This commit is contained in:
parent
5a2d2736a6
commit
60fdb3192b
4 changed files with 66 additions and 2 deletions
|
|
@ -1417,6 +1417,9 @@ Connection objects
|
|||
|
||||
See :ref:`sqlite3-howto-row-factory` for more details.
|
||||
|
||||
.. versionchanged:: next
|
||||
Deleting the ``row_factory`` attribute is no longer allowed.
|
||||
|
||||
.. attribute:: text_factory
|
||||
|
||||
A :term:`callable` that accepts a :class:`bytes` parameter
|
||||
|
|
@ -1426,6 +1429,9 @@ Connection objects
|
|||
|
||||
See :ref:`sqlite3-howto-encoding` for more details.
|
||||
|
||||
.. versionchanged:: next
|
||||
Deleting the ``text_factory`` attribute is no longer allowed.
|
||||
|
||||
.. attribute:: total_changes
|
||||
|
||||
Return the total number of database rows that have been modified, inserted, or
|
||||
|
|
@ -1709,6 +1715,9 @@ Cursor objects
|
|||
|
||||
See :ref:`sqlite3-howto-row-factory` for more details.
|
||||
|
||||
.. versionchanged:: next
|
||||
Deleting the ``row_factory`` attribute is no longer allowed.
|
||||
|
||||
|
||||
.. The sqlite3.Row example used to be a how-to. It has now been incorporated
|
||||
into the Row reference. We keep the anchor here in order not to break
|
||||
|
|
|
|||
|
|
@ -146,6 +146,16 @@ def test_sqlite_row_index(self):
|
|||
with self.assertRaises(IndexError):
|
||||
row[complex()] # index must be int or string
|
||||
|
||||
def test_delete_connection_row_factory(self):
|
||||
# gh-149738: deleting row_factory should raise an exception
|
||||
with self.assertRaises(AttributeError):
|
||||
del self.con.row_factory
|
||||
|
||||
def test_delete_connection_text_factory(self):
|
||||
# gh-149738: deleting text_factory should raise an exception
|
||||
with self.assertRaises(AttributeError):
|
||||
del self.con.text_factory
|
||||
|
||||
def test_sqlite_row_index_unicode(self):
|
||||
row = self.con.execute("select 1 as \xff").fetchone()
|
||||
self.assertEqual(row["\xff"], 1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
:mod:`sqlite3`: Disallow removing ``row_factory`` and ``text_factory`` attributes
|
||||
of a connection to prevent a crash on a query.
|
||||
|
|
@ -557,6 +557,47 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
|
|||
return cursor;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
connection_get_row_factory(PyObject *op, void *closure)
|
||||
{
|
||||
pysqlite_Connection *self = (pysqlite_Connection *)op;
|
||||
return Py_NewRef(self->row_factory);
|
||||
}
|
||||
|
||||
static int
|
||||
connection_set_row_factory(PyObject *op, PyObject *value, void *closure)
|
||||
{
|
||||
pysqlite_Connection *self = (pysqlite_Connection *)op;
|
||||
if (value == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError,
|
||||
"cannot delete row_factory attribute");
|
||||
return -1;
|
||||
}
|
||||
Py_XSETREF(self->row_factory, Py_NewRef(value));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
connection_get_text_factory(PyObject *op, void *closure)
|
||||
{
|
||||
pysqlite_Connection *self = (pysqlite_Connection *)op;
|
||||
return Py_NewRef(self->text_factory);
|
||||
}
|
||||
|
||||
static int
|
||||
connection_set_text_factory(PyObject *op, PyObject *value, void *closure)
|
||||
{
|
||||
pysqlite_Connection *self = (pysqlite_Connection *)op;
|
||||
if (value == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError,
|
||||
"cannot delete text_factory attribute");
|
||||
return -1;
|
||||
}
|
||||
Py_XSETREF(self->text_factory, Py_NewRef(value));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
_sqlite3.Connection.blobopen as blobopen
|
||||
|
||||
|
|
@ -2620,6 +2661,10 @@ static PyGetSetDef connection_getset[] = {
|
|||
{"in_transaction", pysqlite_connection_get_in_transaction, NULL},
|
||||
{"autocommit", get_autocommit, set_autocommit},
|
||||
{"__text_signature__", get_sig, NULL},
|
||||
{"row_factory", connection_get_row_factory,
|
||||
connection_set_row_factory},
|
||||
{"text_factory", connection_get_text_factory,
|
||||
connection_set_text_factory},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
|
@ -2667,8 +2712,6 @@ static struct PyMemberDef connection_members[] =
|
|||
{"InternalError", _Py_T_OBJECT, offsetof(pysqlite_Connection, InternalError), Py_READONLY},
|
||||
{"ProgrammingError", _Py_T_OBJECT, offsetof(pysqlite_Connection, ProgrammingError), Py_READONLY},
|
||||
{"NotSupportedError", _Py_T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), Py_READONLY},
|
||||
{"row_factory", _Py_T_OBJECT, offsetof(pysqlite_Connection, row_factory)},
|
||||
{"text_factory", _Py_T_OBJECT, offsetof(pysqlite_Connection, text_factory)},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue