summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorErlend Egeberg Aasland <erlend.aasland@innova.no>2021-09-12 12:27:42 (GMT)
committerGitHub <noreply@github.com>2021-09-12 12:27:42 (GMT)
commitc78d5ca3806d02e26f9f3fa92ff567f0805eac4c (patch)
treeb26ff2afc45bea20a04097e5fb698591d7d1046f /Modules
parent92bf8691fb78f3484bf2daba836c416efedb1d8d (diff)
downloadcpython-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.h13
-rw-r--r--Modules/_sqlite/connection.c49
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;