From 74d716acc94cd8b21ddfa942de35e589b09566f3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 10 Jan 2010 04:38:55 +0100 Subject: [PATCH] _sqlite: block all operations on a closed connection Add call to pysqlite_check_connection() on the follow methods: * create_function() * create_aggregate() * set_authorizer() * set_progress_handler() * __call__() Eg. fix the following segfault: c = Connection("test") c.close() c.set_authorizer(func) --- Lib/sqlite3/test/dbapi.py | 56 ++++++++++++++--------------------------- Modules/_sqlite/connection.c | 20 ++++++++++++-- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 83ce174..cbf39f5 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -719,49 +719,31 @@ class ClosedTests(unittest.TestCase): pass def CheckClosedConCursor(self): - con = sqlite.connect(":memory:") - con.close() - try: - cur = con.cursor() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: + def callback(*args, **kw): pass - except: - self.fail("Should have raised a ProgrammingError") + class Aggregate: + def __init__(self): + pass - def CheckClosedConCommit(self): - con = sqlite.connect(":memory:") - con.close() - try: - con.commit() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") + def step(self, x): + pass - def CheckClosedConRollback(self): - con = sqlite.connect(":memory:") - con.close() - try: - con.rollback() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") + def finalize(self): + pass - def CheckClosedCurExecute(self): con = sqlite.connect(":memory:") - cur = con.cursor() + cursor = con.cursor() con.close() - try: - cur.execute("select 4") - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") + self.assertRaises(sqlite.ProgrammingError, con.cursor) + self.assertRaises(sqlite.ProgrammingError, con.commit) + self.assertRaises(sqlite.ProgrammingError, con.rollback) + self.assertRaises(sqlite.ProgrammingError, cursor.execute, "select 4") + self.assertRaises(sqlite.ProgrammingError, con.create_function, callback) + self.assertRaises(sqlite.ProgrammingError, con.set_authorizer, callback) + self.assertRaises(sqlite.ProgrammingError, con.set_progress_handler, callback) + self.assertRaises(sqlite.ProgrammingError, con.create_aggregate, "closed", 1, Aggregate) + self.assertRaises(sqlite.ProgrammingError, con, "select 4") + def suite(): module_suite = unittest.makeSuite(ModuleTests, "Check") diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 3747925..9dd6a1c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -3,7 +3,7 @@ * Copyright (C) 2004-2007 Gerhard Häring * * This file is part of pysqlite. - * + * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. @@ -37,7 +37,6 @@ static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level); - static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len) { /* in older SQLite versions, calling sqlite3_result_error in callbacks @@ -765,6 +764,9 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec int narg; int rc; + if (!pysqlite_check_connection(self)) + return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO", kwlist, &name, &narg, &func)) { @@ -795,6 +797,9 @@ PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObje static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL }; int rc; + if (!pysqlite_check_connection(self)) + return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate", kwlist, &name, &n_arg, &aggregate_class)) { return NULL; @@ -867,7 +872,7 @@ static int _progress_handler(void* user_arg) } /* abort query if error occurred */ - rc = 1; + rc = 1; } else { rc = (int)PyObject_IsTrue(ret); Py_DECREF(ret); @@ -886,6 +891,9 @@ PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject static char *kwlist[] = { "authorizer_callback", NULL }; int rc; + if (!pysqlite_check_connection(self)) + return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_authorizer", kwlist, &authorizer_cb)) { return NULL; @@ -912,6 +920,9 @@ PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, Py static char *kwlist[] = { "progress_handler", "n", NULL }; + if (!pysqlite_check_connection(self)) + return NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler", kwlist, &progress_handler, &n)) { return NULL; @@ -1024,6 +1035,9 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py PyObject* weakref; int rc; + if (!pysqlite_check_connection(self)) + return NULL; + if (!PyArg_ParseTuple(args, "O", &sql)) { return NULL; } -- 1.6.0.4