mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-139327: fix some reference leaks in sqlite3 error branches (#139328)
This commit is contained in:
parent
d936dbeb1f
commit
d0a3eff9d6
2 changed files with 42 additions and 32 deletions
|
|
@ -144,7 +144,7 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
|
||||||
|
|
||||||
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
|
static int _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
|
||||||
static void free_callback_context(callback_context *ctx);
|
static void free_callback_context(callback_context *ctx);
|
||||||
static void set_callback_context(callback_context **ctx_pp,
|
static void set_callback_context(callback_context **ctx_pp,
|
||||||
callback_context *ctx);
|
callback_context *ctx);
|
||||||
|
|
@ -561,7 +561,10 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_pysqlite_drop_unused_cursor_references(self);
|
if (_pysqlite_drop_unused_cursor_references(self) < 0) {
|
||||||
|
Py_DECREF(cursor);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (cursor && self->row_factory != Py_None) {
|
if (cursor && self->row_factory != Py_None) {
|
||||||
Py_INCREF(self->row_factory);
|
Py_INCREF(self->row_factory);
|
||||||
|
|
@ -1060,32 +1063,36 @@ final_callback(sqlite3_context *context)
|
||||||
PyGILState_Release(threadstate);
|
PyGILState_Release(threadstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
|
static int
|
||||||
|
_pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
|
||||||
{
|
{
|
||||||
/* we only need to do this once in a while */
|
/* we only need to do this once in a while */
|
||||||
if (self->created_cursors++ < 200) {
|
if (self->created_cursors++ < 200) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->created_cursors = 0;
|
self->created_cursors = 0;
|
||||||
|
|
||||||
PyObject* new_list = PyList_New(0);
|
PyObject* new_list = PyList_New(0);
|
||||||
if (!new_list) {
|
if (!new_list) {
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Py_ssize_t i = 0; i < PyList_Size(self->cursors); i++) {
|
assert(PyList_CheckExact(self->cursors));
|
||||||
PyObject* weakref = PyList_GetItem(self->cursors, i);
|
Py_ssize_t imax = PyList_GET_SIZE(self->cursors);
|
||||||
|
for (Py_ssize_t i = 0; i < imax; i++) {
|
||||||
|
PyObject* weakref = PyList_GET_ITEM(self->cursors, i);
|
||||||
if (_PyWeakref_IsDead(weakref)) {
|
if (_PyWeakref_IsDead(weakref)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (PyList_Append(new_list, weakref) != 0) {
|
if (PyList_Append(new_list, weakref) != 0) {
|
||||||
Py_DECREF(new_list);
|
Py_DECREF(new_list);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_SETREF(self->cursors, new_list);
|
Py_SETREF(self->cursors, new_list);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a UDF/callback context structure. In order to ensure that the state
|
/* Allocate a UDF/callback context structure. In order to ensure that the state
|
||||||
|
|
|
||||||
|
|
@ -471,6 +471,9 @@ static int check_cursor(pysqlite_Cursor* cur)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(cur->connection != NULL);
|
||||||
|
assert(cur->connection->state != NULL);
|
||||||
|
|
||||||
if (cur->closed) {
|
if (cur->closed) {
|
||||||
PyErr_SetString(cur->connection->state->ProgrammingError,
|
PyErr_SetString(cur->connection->state->ProgrammingError,
|
||||||
"Cannot operate on a closed cursor.");
|
"Cannot operate on a closed cursor.");
|
||||||
|
|
@ -567,43 +570,40 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
|
||||||
switch (paramtype) {
|
switch (paramtype) {
|
||||||
case TYPE_LONG: {
|
case TYPE_LONG: {
|
||||||
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
|
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
|
||||||
if (value == -1 && PyErr_Occurred())
|
rc = (value == -1 && PyErr_Occurred())
|
||||||
rc = -1;
|
? SQLITE_ERROR
|
||||||
else
|
: sqlite3_bind_int64(self->st, pos, value);
|
||||||
rc = sqlite3_bind_int64(self->st, pos, value);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_FLOAT: {
|
case TYPE_FLOAT: {
|
||||||
double value = PyFloat_AsDouble(parameter);
|
double value = PyFloat_AsDouble(parameter);
|
||||||
if (value == -1 && PyErr_Occurred()) {
|
rc = (value == -1 && PyErr_Occurred())
|
||||||
rc = -1;
|
? SQLITE_ERROR
|
||||||
}
|
: sqlite3_bind_double(self->st, pos, value);
|
||||||
else {
|
|
||||||
rc = sqlite3_bind_double(self->st, pos, value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_UNICODE:
|
case TYPE_UNICODE:
|
||||||
string = PyUnicode_AsUTF8AndSize(parameter, &buflen);
|
string = PyUnicode_AsUTF8AndSize(parameter, &buflen);
|
||||||
if (string == NULL)
|
if (string == NULL) {
|
||||||
return -1;
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
if (buflen > INT_MAX) {
|
if (buflen > INT_MAX) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"string longer than INT_MAX bytes");
|
"string longer than INT_MAX bytes");
|
||||||
return -1;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
|
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
|
||||||
break;
|
break;
|
||||||
case TYPE_BUFFER: {
|
case TYPE_BUFFER: {
|
||||||
Py_buffer view;
|
Py_buffer view;
|
||||||
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
|
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
|
||||||
return -1;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
if (view.len > INT_MAX) {
|
if (view.len > INT_MAX) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"BLOB longer than INT_MAX bytes");
|
"BLOB longer than INT_MAX bytes");
|
||||||
PyBuffer_Release(&view);
|
PyBuffer_Release(&view);
|
||||||
return -1;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
|
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
|
||||||
PyBuffer_Release(&view);
|
PyBuffer_Release(&view);
|
||||||
|
|
@ -613,7 +613,7 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
|
||||||
PyErr_Format(state->ProgrammingError,
|
PyErr_Format(state->ProgrammingError,
|
||||||
"Error binding parameter %d: type '%s' is not supported",
|
"Error binding parameter %d: type '%s' is not supported",
|
||||||
pos, Py_TYPE(parameter)->tp_name);
|
pos, Py_TYPE(parameter)->tp_name);
|
||||||
rc = -1;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
final:
|
final:
|
||||||
|
|
@ -733,14 +733,17 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
|
||||||
}
|
}
|
||||||
|
|
||||||
binding_name++; /* skip first char (the colon) */
|
binding_name++; /* skip first char (the colon) */
|
||||||
PyObject *current_param;
|
PyObject *current_param = NULL;
|
||||||
(void)PyMapping_GetOptionalItemString(parameters, binding_name, ¤t_param);
|
int found = PyMapping_GetOptionalItemString(parameters,
|
||||||
if (!current_param) {
|
binding_name,
|
||||||
if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) {
|
¤t_param);
|
||||||
PyErr_Format(state->ProgrammingError,
|
if (found == -1) {
|
||||||
"You did not supply a value for binding "
|
return;
|
||||||
"parameter :%s.", binding_name);
|
}
|
||||||
}
|
else if (found == 0) {
|
||||||
|
PyErr_Format(state->ProgrammingError,
|
||||||
|
"You did not supply a value for binding "
|
||||||
|
"parameter :%s.", binding_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue