gh-139327: fix some reference leaks in sqlite3 error branches (#139328)
This commit is contained in:
@@ -144,7 +144,7 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
|
||||
[clinic start generated code]*/
|
||||
/*[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 set_callback_context(callback_context **ctx_pp,
|
||||
callback_context *ctx);
|
||||
@@ -561,7 +561,10 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
|
||||
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) {
|
||||
Py_INCREF(self->row_factory);
|
||||
@@ -1060,32 +1063,36 @@ error:
|
||||
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 */
|
||||
if (self->created_cursors++ < 200) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->created_cursors = 0;
|
||||
|
||||
PyObject* new_list = PyList_New(0);
|
||||
if (!new_list) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (Py_ssize_t i = 0; i < PyList_Size(self->cursors); i++) {
|
||||
PyObject* weakref = PyList_GetItem(self->cursors, i);
|
||||
assert(PyList_CheckExact(self->cursors));
|
||||
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)) {
|
||||
continue;
|
||||
}
|
||||
if (PyList_Append(new_list, weakref) != 0) {
|
||||
Py_DECREF(new_list);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Py_SETREF(self->cursors, new_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
assert(cur->connection != NULL);
|
||||
assert(cur->connection->state != NULL);
|
||||
|
||||
if (cur->closed) {
|
||||
PyErr_SetString(cur->connection->state->ProgrammingError,
|
||||
"Cannot operate on a closed cursor.");
|
||||
@@ -567,43 +570,40 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
|
||||
switch (paramtype) {
|
||||
case TYPE_LONG: {
|
||||
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
|
||||
if (value == -1 && PyErr_Occurred())
|
||||
rc = -1;
|
||||
else
|
||||
rc = sqlite3_bind_int64(self->st, pos, value);
|
||||
rc = (value == -1 && PyErr_Occurred())
|
||||
? SQLITE_ERROR
|
||||
: sqlite3_bind_int64(self->st, pos, value);
|
||||
break;
|
||||
}
|
||||
case TYPE_FLOAT: {
|
||||
double value = PyFloat_AsDouble(parameter);
|
||||
if (value == -1 && PyErr_Occurred()) {
|
||||
rc = -1;
|
||||
}
|
||||
else {
|
||||
rc = sqlite3_bind_double(self->st, pos, value);
|
||||
}
|
||||
rc = (value == -1 && PyErr_Occurred())
|
||||
? SQLITE_ERROR
|
||||
: sqlite3_bind_double(self->st, pos, value);
|
||||
break;
|
||||
}
|
||||
case TYPE_UNICODE:
|
||||
string = PyUnicode_AsUTF8AndSize(parameter, &buflen);
|
||||
if (string == NULL)
|
||||
return -1;
|
||||
if (string == NULL) {
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if (buflen > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"string longer than INT_MAX bytes");
|
||||
return -1;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
|
||||
break;
|
||||
case TYPE_BUFFER: {
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
|
||||
return -1;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if (view.len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"BLOB longer than INT_MAX bytes");
|
||||
PyBuffer_Release(&view);
|
||||
return -1;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
|
||||
PyBuffer_Release(&view);
|
||||
@@ -613,7 +613,7 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
|
||||
PyErr_Format(state->ProgrammingError,
|
||||
"Error binding parameter %d: type '%s' is not supported",
|
||||
pos, Py_TYPE(parameter)->tp_name);
|
||||
rc = -1;
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
final:
|
||||
@@ -733,14 +733,17 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
|
||||
}
|
||||
|
||||
binding_name++; /* skip first char (the colon) */
|
||||
PyObject *current_param;
|
||||
(void)PyMapping_GetOptionalItemString(parameters, binding_name, ¤t_param);
|
||||
if (!current_param) {
|
||||
if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) {
|
||||
PyErr_Format(state->ProgrammingError,
|
||||
"You did not supply a value for binding "
|
||||
"parameter :%s.", binding_name);
|
||||
}
|
||||
PyObject *current_param = NULL;
|
||||
int found = PyMapping_GetOptionalItemString(parameters,
|
||||
binding_name,
|
||||
¤t_param);
|
||||
if (found == -1) {
|
||||
return;
|
||||
}
|
||||
else if (found == 0) {
|
||||
PyErr_Format(state->ProgrammingError,
|
||||
"You did not supply a value for binding "
|
||||
"parameter :%s.", binding_name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user