mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-45126: Fix ref. leak in sqlite3.Connection.__init__
(GH-28231)
This commit is contained in:
parent
92bf8691fb
commit
c78d5ca380
2 changed files with 49 additions and 13 deletions
|
@ -4,7 +4,7 @@ preserve
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pysqlite_connection_init_impl(pysqlite_Connection *self,
|
pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
PyObject *database_obj, double timeout,
|
const char *database, double timeout,
|
||||||
int detect_types, PyObject *isolation_level,
|
int detect_types, PyObject *isolation_level,
|
||||||
int check_same_thread, PyObject *factory,
|
int check_same_thread, PyObject *factory,
|
||||||
int cached_statements, int uri);
|
int cached_statements, int uri);
|
||||||
|
@ -19,7 +19,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
PyObject * const *fastargs;
|
PyObject * const *fastargs;
|
||||||
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
|
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
|
||||||
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
|
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
|
||||||
PyObject *database_obj;
|
const char *database = NULL;
|
||||||
double timeout = 5.0;
|
double timeout = 5.0;
|
||||||
int detect_types = 0;
|
int detect_types = 0;
|
||||||
PyObject *isolation_level = NULL;
|
PyObject *isolation_level = NULL;
|
||||||
|
@ -32,7 +32,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
if (!fastargs) {
|
if (!fastargs) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!PyUnicode_FSConverter(fastargs[0], &database_obj)) {
|
if (!clinic_fsconverter(fastargs[0], &database)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!noptargs) {
|
if (!noptargs) {
|
||||||
|
@ -97,9 +97,12 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database_obj, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri);
|
return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
/* Cleanup for database */
|
||||||
|
PyMem_Free((void *)database);
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,4 +819,4 @@ exit:
|
||||||
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
|
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
|
||||||
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
|
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
|
||||||
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
|
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
|
||||||
/*[clinic end generated code: output=9c0dfc6c1ebf9039 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=5b7268875f33c016 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -33,6 +33,32 @@
|
||||||
#define HAVE_TRACE_V2
|
#define HAVE_TRACE_V2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
clinic_fsconverter(PyObject *pathlike, const char **result)
|
||||||
|
{
|
||||||
|
PyObject *bytes = NULL;
|
||||||
|
Py_ssize_t len;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if (!PyUnicode_FSConverter(pathlike, &bytes)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (PyBytes_AsStringAndSize(bytes, &str, &len) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((*result = (const char *)PyMem_Malloc(len+1)) == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void *)(*result), str, len+1);
|
||||||
|
Py_DECREF(bytes);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_XDECREF(bytes);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define clinic_state() (pysqlite_get_state(NULL))
|
#define clinic_state() (pysqlite_get_state(NULL))
|
||||||
#include "clinic/connection.c.h"
|
#include "clinic/connection.c.h"
|
||||||
#undef clinic_state
|
#undef clinic_state
|
||||||
|
@ -81,10 +107,21 @@ new_statement_cache(pysqlite_Connection *self, int maxsize)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[python input]
|
||||||
|
class FSConverter_converter(CConverter):
|
||||||
|
type = "const char *"
|
||||||
|
converter = "clinic_fsconverter"
|
||||||
|
def converter_init(self):
|
||||||
|
self.c_default = "NULL"
|
||||||
|
def cleanup(self):
|
||||||
|
return f"PyMem_Free((void *){self.name});\n"
|
||||||
|
[python start generated code]*/
|
||||||
|
/*[python end generated code: output=da39a3ee5e6b4b0d input=7b3be538bc4058c0]*/
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_sqlite3.Connection.__init__ as pysqlite_connection_init
|
_sqlite3.Connection.__init__ as pysqlite_connection_init
|
||||||
|
|
||||||
database as database_obj: object(converter='PyUnicode_FSConverter')
|
database: FSConverter
|
||||||
timeout: double = 5.0
|
timeout: double = 5.0
|
||||||
detect_types: int = 0
|
detect_types: int = 0
|
||||||
isolation_level: object = NULL
|
isolation_level: object = NULL
|
||||||
|
@ -96,23 +133,21 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pysqlite_connection_init_impl(pysqlite_Connection *self,
|
pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
PyObject *database_obj, double timeout,
|
const char *database, double timeout,
|
||||||
int detect_types, PyObject *isolation_level,
|
int detect_types, PyObject *isolation_level,
|
||||||
int check_same_thread, PyObject *factory,
|
int check_same_thread, PyObject *factory,
|
||||||
int cached_statements, int uri)
|
int cached_statements, int uri)
|
||||||
/*[clinic end generated code: output=dc19df1c0e2b7b77 input=aa1f21bf12fe907a]*/
|
/*[clinic end generated code: output=bc39e55eb0b68783 input=f8d1f7efc0d84104]*/
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (PySys_Audit("sqlite3.connect", "O", database_obj) < 0) {
|
if (PySys_Audit("sqlite3.connect", "s", database) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
|
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
|
||||||
self->state = state;
|
self->state = state;
|
||||||
|
|
||||||
const char *database = PyBytes_AsString(database_obj);
|
|
||||||
|
|
||||||
self->begin_statement = NULL;
|
self->begin_statement = NULL;
|
||||||
|
|
||||||
Py_CLEAR(self->statement_cache);
|
Py_CLEAR(self->statement_cache);
|
||||||
|
@ -130,8 +165,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
|
||||||
(uri ? SQLITE_OPEN_URI : 0), NULL);
|
(uri ? SQLITE_OPEN_URI : 0), NULL);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
Py_DECREF(database_obj); // needed bco. the AC FSConverter
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
_pysqlite_seterror(state, self->db);
|
_pysqlite_seterror(state, self->db);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue