mirror of
https://github.com/python/cpython.git
synced 2025-11-12 23:16:47 +00:00
Issue #27861: Fixed a crash in sqlite3.Connection.cursor() when a factory
creates not a cursor. Patch by Xiang Zhang.
This commit is contained in:
commit
8631da64bb
4 changed files with 35 additions and 9 deletions
|
|
@ -285,11 +285,11 @@ Connection Objects
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
.. method:: cursor([cursorClass])
|
.. method:: cursor(factory=Cursor)
|
||||||
|
|
||||||
The cursor method accepts a single optional parameter *cursorClass*. If
|
The cursor method accepts a single optional parameter *factory*. If
|
||||||
supplied, this must be a custom cursor class that extends
|
supplied, this must be a callable returning an instance of :class:`Cursor`
|
||||||
:class:`sqlite3.Cursor`.
|
or its subclasses.
|
||||||
|
|
||||||
.. method:: commit()
|
.. method:: commit()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,20 @@ class CursorFactoryTests(unittest.TestCase):
|
||||||
self.con.close()
|
self.con.close()
|
||||||
|
|
||||||
def CheckIsInstance(self):
|
def CheckIsInstance(self):
|
||||||
cur = self.con.cursor(factory=MyCursor)
|
cur = self.con.cursor()
|
||||||
|
self.assertIsInstance(cur, sqlite.Cursor)
|
||||||
|
cur = self.con.cursor(MyCursor)
|
||||||
self.assertIsInstance(cur, MyCursor)
|
self.assertIsInstance(cur, MyCursor)
|
||||||
|
cur = self.con.cursor(factory=lambda con: MyCursor(con))
|
||||||
|
self.assertIsInstance(cur, MyCursor)
|
||||||
|
|
||||||
|
def CheckInvalidFactory(self):
|
||||||
|
# not a callable at all
|
||||||
|
self.assertRaises(TypeError, self.con.cursor, None)
|
||||||
|
# invalid callable with not exact one argument
|
||||||
|
self.assertRaises(TypeError, self.con.cursor, lambda: None)
|
||||||
|
# invalid callable returning non-cursor
|
||||||
|
self.assertRaises(TypeError, self.con.cursor, lambda con: None)
|
||||||
|
|
||||||
class RowFactoryTestsBackwardsCompat(unittest.TestCase):
|
class RowFactoryTestsBackwardsCompat(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
@ -183,10 +195,12 @@ class RowFactoryTests(unittest.TestCase):
|
||||||
def CheckFakeCursorClass(self):
|
def CheckFakeCursorClass(self):
|
||||||
# Issue #24257: Incorrect use of PyObject_IsInstance() caused
|
# Issue #24257: Incorrect use of PyObject_IsInstance() caused
|
||||||
# segmentation fault.
|
# segmentation fault.
|
||||||
|
# Issue #27861: Also applies for cursor factory.
|
||||||
class FakeCursor(str):
|
class FakeCursor(str):
|
||||||
__class__ = sqlite.Cursor
|
__class__ = sqlite.Cursor
|
||||||
cur = self.con.cursor(factory=FakeCursor)
|
self.con.row_factory = sqlite.Row
|
||||||
self.assertRaises(TypeError, sqlite.Row, cur, ())
|
self.assertRaises(TypeError, self.con.cursor, FakeCursor)
|
||||||
|
self.assertRaises(TypeError, sqlite.Row, FakeCursor(), ())
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.con.close()
|
self.con.close()
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #27861: Fixed a crash in sqlite3.Connection.cursor() when a factory
|
||||||
|
creates not a cursor. Patch by Xiang Zhang.
|
||||||
|
|
||||||
- Issue #19884: Avoid spurious output on OS X with Gnu Readline.
|
- Issue #19884: Avoid spurious output on OS X with Gnu Readline.
|
||||||
|
|
||||||
- Issue #10513: Fix a regression in Connection.commit(). Statements should
|
- Issue #10513: Fix a regression in Connection.commit(). Statements should
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ error:
|
||||||
|
|
||||||
PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
|
PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"factory", NULL, NULL};
|
static char *kwlist[] = {"factory", NULL};
|
||||||
PyObject* factory = NULL;
|
PyObject* factory = NULL;
|
||||||
PyObject* cursor;
|
PyObject* cursor;
|
||||||
|
|
||||||
|
|
@ -317,7 +317,16 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args,
|
||||||
factory = (PyObject*)&pysqlite_CursorType;
|
factory = (PyObject*)&pysqlite_CursorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = PyObject_CallFunction(factory, "O", self);
|
cursor = PyObject_CallFunctionObjArgs(factory, (PyObject *)self, NULL);
|
||||||
|
if (cursor == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (!PyObject_TypeCheck(cursor, &pysqlite_CursorType)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"factory must return a cursor, not %.100s",
|
||||||
|
Py_TYPE(cursor)->tp_name);
|
||||||
|
Py_DECREF(cursor);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
_pysqlite_drop_unused_cursor_references(self);
|
_pysqlite_drop_unused_cursor_references(self);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue