diff options
author | Erlend Egeberg Aasland <erlend.aasland@innova.no> | 2021-09-12 12:27:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-12 12:27:42 (GMT) |
commit | c78d5ca3806d02e26f9f3fa92ff567f0805eac4c (patch) | |
tree | b26ff2afc45bea20a04097e5fb698591d7d1046f /Modules | |
parent | 92bf8691fb78f3484bf2daba836c416efedb1d8d (diff) | |
download | cpython-c78d5ca3806d02e26f9f3fa92ff567f0805eac4c.zip cpython-c78d5ca3806d02e26f9f3fa92ff567f0805eac4c.tar.gz cpython-c78d5ca3806d02e26f9f3fa92ff567f0805eac4c.tar.bz2 |
bpo-45126: Fix ref. leak in `sqlite3.Connection.__init__` (GH-28231)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_sqlite/clinic/connection.c.h | 13 | ||||
-rw-r--r-- | Modules/_sqlite/connection.c | 49 |
2 files changed, 49 insertions, 13 deletions
diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 315d163..bf5a58d 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -4,7 +4,7 @@ preserve static int pysqlite_connection_init_impl(pysqlite_Connection *self, - PyObject *database_obj, double timeout, + const char *database, double timeout, int detect_types, PyObject *isolation_level, int check_same_thread, PyObject *factory, int cached_statements, int uri); @@ -19,7 +19,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1; - PyObject *database_obj; + const char *database = NULL; double timeout = 5.0; int detect_types = 0; PyObject *isolation_level = NULL; @@ -32,7 +32,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) if (!fastargs) { goto exit; } - if (!PyUnicode_FSConverter(fastargs[0], &database_obj)) { + if (!clinic_fsconverter(fastargs[0], &database)) { goto exit; } if (!noptargs) { @@ -97,9 +97,12 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } 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: + /* Cleanup for database */ + PyMem_Free((void *)database); + return return_value; } @@ -816,4 +819,4 @@ exit: #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define 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]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index bf80337..3b9e427 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -33,6 +33,32 @@ #define HAVE_TRACE_V2 #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)) #include "clinic/connection.c.h" #undef clinic_state @@ -81,10 +107,21 @@ new_statement_cache(pysqlite_Connection *self, int maxsize) 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] _sqlite3.Connection.__init__ as pysqlite_connection_init - database as database_obj: object(converter='PyUnicode_FSConverter') + database: FSConverter timeout: double = 5.0 detect_types: int = 0 isolation_level: object = NULL @@ -96,23 +133,21 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init static int pysqlite_connection_init_impl(pysqlite_Connection *self, - PyObject *database_obj, double timeout, + const char *database, double timeout, int detect_types, PyObject *isolation_level, int check_same_thread, PyObject *factory, int cached_statements, int uri) -/*[clinic end generated code: output=dc19df1c0e2b7b77 input=aa1f21bf12fe907a]*/ +/*[clinic end generated code: output=bc39e55eb0b68783 input=f8d1f7efc0d84104]*/ { int rc; - if (PySys_Audit("sqlite3.connect", "O", database_obj) < 0) { + if (PySys_Audit("sqlite3.connect", "s", database) < 0) { return -1; } pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); self->state = state; - const char *database = PyBytes_AsString(database_obj); - self->begin_statement = NULL; Py_CLEAR(self->statement_cache); @@ -130,8 +165,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, (uri ? SQLITE_OPEN_URI : 0), NULL); Py_END_ALLOW_THREADS - Py_DECREF(database_obj); // needed bco. the AC FSConverter - if (rc != SQLITE_OK) { _pysqlite_seterror(state, self->db); return -1; |