mirror of
https://github.com/python/cpython.git
synced 2026-04-13 15:20:52 +00:00
[3.13] gh-146090: fix memory management of internal sqlite3 callback contexts (GH-146569) (#146596)
gh-146090: fix memory management of internal `sqlite3` callback contexts (GH-146569)
(cherry picked from commit aa6680775d)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
parent
59f33e82ff
commit
6fdf084644
4 changed files with 30 additions and 7 deletions
|
|
@ -120,6 +120,21 @@ def test_collation_register_twice(self):
|
|||
self.assertEqual(result[0][0], 'b')
|
||||
self.assertEqual(result[1][0], 'a')
|
||||
|
||||
def test_collation_register_when_busy(self):
|
||||
# See https://github.com/python/cpython/issues/146090.
|
||||
con = self.con
|
||||
con.create_collation("mycoll", lambda x, y: (x > y) - (x < y))
|
||||
con.execute("CREATE TABLE t(x TEXT)")
|
||||
con.execute("INSERT INTO t VALUES (?)", ("a",))
|
||||
con.execute("INSERT INTO t VALUES (?)", ("b",))
|
||||
con.commit()
|
||||
|
||||
cursor = self.con.execute("SELECT x FROM t ORDER BY x COLLATE mycoll")
|
||||
next(cursor)
|
||||
# Replace the collation while the statement is active -> SQLITE_BUSY.
|
||||
with self.assertRaises(sqlite.OperationalError) as cm:
|
||||
self.con.create_collation("mycoll", lambda a, b: 0)
|
||||
|
||||
def test_deregister_collation(self):
|
||||
"""
|
||||
Register a collation, then deregister it. Make sure an error is raised if we try
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
:mod:`sqlite3`: properly raise :exc:`MemoryError` instead of :exc:`SystemError`
|
||||
when a context callback fails to be allocated. Patch by Bénédikt Tran.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
:mod:`sqlite3`: fix a crash when :meth:`sqlite3.Connection.create_collation`
|
||||
fails with `SQLITE_BUSY <https://sqlite.org/rescode.html#busy>`__. Patch by
|
||||
Bénédikt Tran.
|
||||
|
|
@ -1103,13 +1103,16 @@ static callback_context *
|
|||
create_callback_context(PyTypeObject *cls, PyObject *callable)
|
||||
{
|
||||
callback_context *ctx = PyMem_Malloc(sizeof(callback_context));
|
||||
if (ctx != NULL) {
|
||||
PyObject *module = PyType_GetModule(cls);
|
||||
ctx->refcount = 1;
|
||||
ctx->callable = Py_NewRef(callable);
|
||||
ctx->module = Py_NewRef(module);
|
||||
ctx->state = pysqlite_get_state(module);
|
||||
if (ctx == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *module = PyType_GetModule(cls);
|
||||
ctx->refcount = 1;
|
||||
ctx->callable = Py_NewRef(callable);
|
||||
ctx->module = Py_NewRef(module);
|
||||
ctx->state = pysqlite_get_state(module);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
@ -2212,7 +2215,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self,
|
|||
* the context before returning.
|
||||
*/
|
||||
if (callable != Py_None) {
|
||||
free_callback_context(ctx);
|
||||
decref_callback_context(ctx);
|
||||
}
|
||||
_pysqlite_seterror(self->state, self->db);
|
||||
return NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue