mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
bpo-31746: Prevent segfaults when sqlite3.Connection is uninitialised (GH-27431)
This commit is contained in:
parent
8182c8329c
commit
7e311e496b
2 changed files with 44 additions and 7 deletions
|
@ -243,6 +243,26 @@ class ConnectionTests(unittest.TestCase):
|
||||||
self.assertEqual(cu.fetchone()[0], n)
|
self.assertEqual(cu.fetchone()[0], n)
|
||||||
|
|
||||||
|
|
||||||
|
class UninitialisedConnectionTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.cx = sqlite.Connection.__new__(sqlite.Connection)
|
||||||
|
|
||||||
|
def test_uninit_operations(self):
|
||||||
|
funcs = (
|
||||||
|
lambda: self.cx.isolation_level,
|
||||||
|
lambda: self.cx.total_changes,
|
||||||
|
lambda: self.cx.in_transaction,
|
||||||
|
lambda: self.cx.iterdump(),
|
||||||
|
lambda: self.cx.cursor(),
|
||||||
|
lambda: self.cx.close(),
|
||||||
|
)
|
||||||
|
for func in funcs:
|
||||||
|
with self.subTest(func=func):
|
||||||
|
self.assertRaisesRegex(sqlite.ProgrammingError,
|
||||||
|
"Base Connection.__init__ not called",
|
||||||
|
func)
|
||||||
|
|
||||||
|
|
||||||
class OpenTests(unittest.TestCase):
|
class OpenTests(unittest.TestCase):
|
||||||
_sql = "create table test(id integer)"
|
_sql = "create table test(id integer)"
|
||||||
|
|
||||||
|
@ -951,6 +971,7 @@ def suite():
|
||||||
ModuleTests,
|
ModuleTests,
|
||||||
SqliteOnConflictTests,
|
SqliteOnConflictTests,
|
||||||
ThreadTests,
|
ThreadTests,
|
||||||
|
UninitialisedConnectionTests,
|
||||||
]
|
]
|
||||||
return unittest.TestSuite(
|
return unittest.TestSuite(
|
||||||
[unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
|
[unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
|
||||||
|
|
|
@ -111,8 +111,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
|
|
||||||
const char *database = PyBytes_AsString(database_obj);
|
const char *database = PyBytes_AsString(database_obj);
|
||||||
|
|
||||||
self->initialized = 1;
|
|
||||||
|
|
||||||
self->begin_statement = NULL;
|
self->begin_statement = NULL;
|
||||||
|
|
||||||
Py_CLEAR(self->statement_cache);
|
Py_CLEAR(self->statement_cache);
|
||||||
|
@ -147,7 +145,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
Py_INCREF(isolation_level);
|
Py_INCREF(isolation_level);
|
||||||
}
|
}
|
||||||
Py_CLEAR(self->isolation_level);
|
Py_CLEAR(self->isolation_level);
|
||||||
if (pysqlite_connection_set_isolation_level(self, isolation_level, NULL) < 0) {
|
if (pysqlite_connection_set_isolation_level(self, isolation_level, NULL) != 0) {
|
||||||
Py_DECREF(isolation_level);
|
Py_DECREF(isolation_level);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -195,6 +193,8 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->initialized = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +371,13 @@ pysqlite_connection_close_impl(pysqlite_Connection *self)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!self->initialized) {
|
||||||
|
pysqlite_state *state = pysqlite_get_state(NULL);
|
||||||
|
PyErr_SetString(state->ProgrammingError,
|
||||||
|
"Base Connection.__init__ not called.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
pysqlite_do_all_statements(self, ACTION_FINALIZE, 1);
|
pysqlite_do_all_statements(self, ACTION_FINALIZE, 1);
|
||||||
connection_close(self);
|
connection_close(self);
|
||||||
|
|
||||||
|
@ -1258,6 +1265,9 @@ int pysqlite_check_thread(pysqlite_Connection* self)
|
||||||
|
|
||||||
static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* self, void* unused)
|
static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* self, void* unused)
|
||||||
{
|
{
|
||||||
|
if (!pysqlite_check_connection(self)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return Py_NewRef(self->isolation_level);
|
return Py_NewRef(self->isolation_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,11 +1299,17 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (isolation_level == Py_None) {
|
if (isolation_level == Py_None) {
|
||||||
PyObject *res = pysqlite_connection_commit(self, NULL);
|
/* We might get called during connection init, so we cannot use
|
||||||
if (!res) {
|
* pysqlite_connection_commit() here. */
|
||||||
return -1;
|
if (self->db && !sqlite3_get_autocommit(self->db)) {
|
||||||
|
int rc;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
rc = sqlite3_exec(self->db, "COMMIT", NULL, NULL, NULL);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
return _pysqlite_seterror(self->db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Py_DECREF(res);
|
|
||||||
|
|
||||||
self->begin_statement = NULL;
|
self->begin_statement = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue