[Python-checkins] cpython: #10811: Fix recursive usage of cursors. Instead of crashing, raise a

gerhard.haering python-checkins at python.org
Mon May 9 12:24:19 CEST 2011


http://hg.python.org/cpython/rev/c6523d6faef4
changeset: 69974:c6523d6faef4
user: Gerhard Haering <gh at ghaering.de>
date: Mon May 09 12:24:09 2011 +0200
summary:
 #10811: Fix recursive usage of cursors. Instead of crashing, raise a ProgrammingError now.
files:
 Lib/sqlite3/test/regression.py | 23 +++++++++++++++++
 Modules/_sqlite/cursor.c | 29 ++++++++++++++-------
 Modules/_sqlite/cursor.h | 1 +
 3 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py
--- a/Lib/sqlite3/test/regression.py
+++ b/Lib/sqlite3/test/regression.py
@@ -281,6 +281,29 @@
 # Lone surrogate cannot be encoded to the default encoding (utf8)
 "\uDC80", collation_cb)
 
+ 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
+
+ try:
+ cur.executemany("insert into b (baz) values (?)", ((i,) for i in foo()))
+ self.fail("should have raised ProgrammingError")
+ except sqlite.ProgrammingError:
+ pass
+
 def suite():
 regression_suite = unittest.makeSuite(RegressionTests, "Check")
 return unittest.TestSuite((regression_suite,))
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -430,9 +430,14 @@
 if (cur->closed) {
 PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
 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)
@@ -455,9 +460,10 @@
 int allow_8bit_chars;
 
 if (!check_cursor(self)) {
- return NULL;
+ goto error;
 }
 
+ self->locked = 1;
 self->reset = 0;
 
 /* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
@@ -470,12 +476,12 @@
 if (multiple) {
 /* executemany() */
 if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
- return NULL;
+ goto error;
 }
 
 if (!PyUnicode_Check(operation)) {
 PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
- return NULL;
+ goto error;
 }
 
 if (PyIter_Check(second_argument)) {
@@ -486,23 +492,23 @@
 /* sequence */
 parameters_iter = PyObject_GetIter(second_argument);
 if (!parameters_iter) {
- return NULL;
+ goto error;
 }
 }
 } else {
 /* execute() */
 if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
- return NULL;
+ goto error;
 }
 
 if (!PyUnicode_Check(operation)) {
 PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
- return NULL;
+ goto error;
 }
 
 parameters_list = PyList_New(0);
 if (!parameters_list) {
- return NULL;
+ goto error;
 }
 
 if (second_argument == NULL) {
@@ -742,7 +748,8 @@
 * ROLLBACK could have happened */
 #ifdef SQLITE_VERSION_NUMBER
 #if SQLITE_VERSION_NUMBER >= 3002002
- self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
+ if (self->connection && self->connection->db)
+ self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
 #endif
 #endif
 
@@ -750,6 +757,8 @@
 Py_XDECREF(parameters_iter);
 Py_XDECREF(parameters_list);
 
+ self->locked = 0;
+
 if (PyErr_Occurred()) {
 self->rowcount = -1L;
 return NULL;
diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h
--- a/Modules/_sqlite/cursor.h
+++ b/Modules/_sqlite/cursor.h
@@ -42,6 +42,7 @@
 pysqlite_Statement* statement;
 int closed;
 int reset;
+ int locked;
 int initialized;
 
 /* the next row to be returned, NULL if no next row available */
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /