Skip to content

Commit c78d5ca

Browse files
author
Erlend Egeberg Aasland
authored
bpo-45126: Fix ref. leak in sqlite3.Connection.__init__ (GH-28231)
1 parent 92bf869 commit c78d5ca

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

Modules/_sqlite/clinic/connection.c.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ preserve
44

55
static int
66
pysqlite_connection_init_impl(pysqlite_Connection *self,
7-
PyObject *database_obj, double timeout,
7+
const char *database, double timeout,
88
int detect_types, PyObject *isolation_level,
99
int check_same_thread, PyObject *factory,
1010
int cached_statements, int uri);
@@ -19,7 +19,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
1919
PyObject * const *fastargs;
2020
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
2121
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
22-
PyObject *database_obj;
22+
const char *database = NULL;
2323
double timeout = 5.0;
2424
int detect_types = 0;
2525
PyObject *isolation_level = NULL;
@@ -32,7 +32,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
3232
if (!fastargs) {
3333
goto exit;
3434
}
35-
if (!PyUnicode_FSConverter(fastargs[0], &database_obj)) {
35+
if (!clinic_fsconverter(fastargs[0], &database)) {
3636
goto exit;
3737
}
3838
if (!noptargs) {
@@ -97,9 +97,12 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs)
9797
goto exit;
9898
}
9999
skip_optional_pos:
100-
return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database_obj, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri);
100+
return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri);
101101

102102
exit:
103+
/* Cleanup for database */
104+
PyMem_Free((void *)database);
105+
103106
return return_value;
104107
}
105108

@@ -816,4 +819,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss
816819
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
817820
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
818821
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
819-
/*[clinic end generated code: output=9c0dfc6c1ebf9039 input=a9049054013a1b77]*/
822+
/*[clinic end generated code: output=5b7268875f33c016 input=a9049054013a1b77]*/

Modules/_sqlite/connection.c

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,32 @@
3333
#define HAVE_TRACE_V2
3434
#endif
3535

36+
static int
37+
clinic_fsconverter(PyObject *pathlike, const char **result)
38+
{
39+
PyObject *bytes = NULL;
40+
Py_ssize_t len;
41+
char *str;
42+
43+
if (!PyUnicode_FSConverter(pathlike, &bytes)) {
44+
goto error;
45+
}
46+
if (PyBytes_AsStringAndSize(bytes, &str, &len) < 0) {
47+
goto error;
48+
}
49+
if ((*result = (const char *)PyMem_Malloc(len+1)) == NULL) {
50+
goto error;
51+
}
52+
53+
memcpy((void *)(*result), str, len+1);
54+
Py_DECREF(bytes);
55+
return 1;
56+
57+
error:
58+
Py_XDECREF(bytes);
59+
return 0;
60+
}
61+
3662
#define clinic_state() (pysqlite_get_state(NULL))
3763
#include "clinic/connection.c.h"
3864
#undef clinic_state
@@ -81,10 +107,21 @@ new_statement_cache(pysqlite_Connection *self, int maxsize)
81107
return res;
82108
}
83109

110+
/*[python input]
111+
class FSConverter_converter(CConverter):
112+
type = "const char *"
113+
converter = "clinic_fsconverter"
114+
def converter_init(self):
115+
self.c_default = "NULL"
116+
def cleanup(self):
117+
return f"PyMem_Free((void *){self.name});\n"
118+
[python start generated code]*/
119+
/*[python end generated code: output=da39a3ee5e6b4b0d input=7b3be538bc4058c0]*/
120+
84121
/*[clinic input]
85122
_sqlite3.Connection.__init__ as pysqlite_connection_init
86123
87-
database as database_obj: object(converter='PyUnicode_FSConverter')
124+
database: FSConverter
88125
timeout: double = 5.0
89126
detect_types: int = 0
90127
isolation_level: object = NULL
@@ -96,23 +133,21 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init
96133

97134
static int
98135
pysqlite_connection_init_impl(pysqlite_Connection *self,
99-
PyObject *database_obj, double timeout,
136+
const char *database, double timeout,
100137
int detect_types, PyObject *isolation_level,
101138
int check_same_thread, PyObject *factory,
102139
int cached_statements, int uri)
103-
/*[clinic end generated code: output=dc19df1c0e2b7b77 input=aa1f21bf12fe907a]*/
140+
/*[clinic end generated code: output=bc39e55eb0b68783 input=f8d1f7efc0d84104]*/
104141
{
105142
int rc;
106143

107-
if (PySys_Audit("sqlite3.connect", "O", database_obj) < 0) {
144+
if (PySys_Audit("sqlite3.connect", "s", database) < 0) {
108145
return -1;
109146
}
110147

111148
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
112149
self->state = state;
113150

114-
const char *database = PyBytes_AsString(database_obj);
115-
116151
self->begin_statement = NULL;
117152

118153
Py_CLEAR(self->statement_cache);
@@ -130,8 +165,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
130165
(uri ? SQLITE_OPEN_URI : 0), NULL);
131166
Py_END_ALLOW_THREADS
132167

133-
Py_DECREF(database_obj); // needed bco. the AC FSConverter
134-
135168
if (rc != SQLITE_OK) {
136169
_pysqlite_seterror(state, self->db);
137170
return -1;

0 commit comments

Comments
 (0)