Issue #10811: Fix recursive usage of cursors. Instead of crashing, raise a ProgrammingError now.
This commit is contained in:
parent
cec6a61d30
commit
c7fd523ac5
|
@ -264,6 +264,28 @@ class RegressionTests(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
self.assertRaises(sqlite.Warning, self.con, 1)
|
self.assertRaises(sqlite.Warning, self.con, 1)
|
||||||
|
|
||||||
|
def CheckRecursiveCursorUse(self):
|
||||||
|
"""
|
||||||
|
http://bugs.python.org/issue10811
|
||||||
|
|
||||||
|
Recursively using a cursor, such as when reusing it from a generator led to segfaults.
|
||||||
|
Now we catch recursive cursor usage and raise a ProgrammingError.
|
||||||
|
"""
|
||||||
|
con = sqlite.connect(":memory:")
|
||||||
|
|
||||||
|
cur = con.cursor()
|
||||||
|
cur.execute("create table a (bar)")
|
||||||
|
cur.execute("create table b (baz)")
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
cur.execute("insert into a (bar) values (?)", (1,))
|
||||||
|
yield 1
|
||||||
|
|
||||||
|
with self.assertRaises(sqlite.ProgrammingError):
|
||||||
|
cur.executemany("insert into b (baz) values (?)",
|
||||||
|
((i,) for i in foo()))
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
regression_suite = unittest.makeSuite(RegressionTests, "Check")
|
regression_suite = unittest.makeSuite(RegressionTests, "Check")
|
||||||
return unittest.TestSuite((regression_suite,))
|
return unittest.TestSuite((regression_suite,))
|
||||||
|
|
|
@ -90,6 +90,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10811: Fix recursive usage of cursors. Instead of crashing,
|
||||||
|
raise a ProgrammingError now.
|
||||||
|
|
||||||
- Issue #10881: Fix test_site failures with OS X framework builds.
|
- Issue #10881: Fix test_site failures with OS X framework builds.
|
||||||
|
|
||||||
- Issue #964437 Make IDLE help window non-modal.
|
- Issue #964437 Make IDLE help window non-modal.
|
||||||
|
|
|
@ -443,9 +443,14 @@ static int check_cursor(pysqlite_Cursor* cur)
|
||||||
if (cur->closed) {
|
if (cur->closed) {
|
||||||
PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
|
PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cur->locked) {
|
||||||
|
PyErr_SetString(pysqlite_ProgrammingError, "Recursive use of cursors not allowed.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
|
PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
|
||||||
|
@ -468,9 +473,10 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
|
||||||
int allow_8bit_chars;
|
int allow_8bit_chars;
|
||||||
|
|
||||||
if (!check_cursor(self)) {
|
if (!check_cursor(self)) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->locked = 1;
|
||||||
self->reset = 0;
|
self->reset = 0;
|
||||||
|
|
||||||
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
|
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
|
||||||
|
@ -483,12 +489,12 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
/* executemany() */
|
/* executemany() */
|
||||||
if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
|
if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
|
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
|
||||||
PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
|
PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyIter_Check(second_argument)) {
|
if (PyIter_Check(second_argument)) {
|
||||||
|
@ -499,23 +505,23 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
|
||||||
/* sequence */
|
/* sequence */
|
||||||
parameters_iter = PyObject_GetIter(second_argument);
|
parameters_iter = PyObject_GetIter(second_argument);
|
||||||
if (!parameters_iter) {
|
if (!parameters_iter) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* execute() */
|
/* execute() */
|
||||||
if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
|
if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
|
if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
|
||||||
PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
|
PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters_list = PyList_New(0);
|
parameters_list = PyList_New(0);
|
||||||
if (!parameters_list) {
|
if (!parameters_list) {
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (second_argument == NULL) {
|
if (second_argument == NULL) {
|
||||||
|
@ -761,6 +767,7 @@ error:
|
||||||
* ROLLBACK could have happened */
|
* ROLLBACK could have happened */
|
||||||
#ifdef SQLITE_VERSION_NUMBER
|
#ifdef SQLITE_VERSION_NUMBER
|
||||||
#if SQLITE_VERSION_NUMBER >= 3002002
|
#if SQLITE_VERSION_NUMBER >= 3002002
|
||||||
|
if (self->connection && self->connection->db)
|
||||||
self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
|
self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -770,6 +777,8 @@ error:
|
||||||
Py_XDECREF(parameters_iter);
|
Py_XDECREF(parameters_iter);
|
||||||
Py_XDECREF(parameters_list);
|
Py_XDECREF(parameters_list);
|
||||||
|
|
||||||
|
self->locked = 0;
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
self->rowcount = -1L;
|
self->rowcount = -1L;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -42,6 +42,7 @@ typedef struct
|
||||||
pysqlite_Statement* statement;
|
pysqlite_Statement* statement;
|
||||||
int closed;
|
int closed;
|
||||||
int reset;
|
int reset;
|
||||||
|
int locked;
|
||||||
int initialized;
|
int initialized;
|
||||||
|
|
||||||
/* the next row to be returned, NULL if no next row available */
|
/* the next row to be returned, NULL if no next row available */
|
||||||
|
|
Loading…
Reference in New Issue