Skip to content

Commit 644e942

Browse files
author
Erlend Egeberg Aasland
authored
bpo-42021: Fix possible ref leaks during _sqlite3 module init (GH-22673)
1 parent b67cbbd commit 644e942

File tree

4 files changed

+93
-129
lines changed

4 files changed

+93
-129
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix possible ref leaks in :mod:`sqlite3` module init.

Modules/_sqlite/microprotocols.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ static PyObject *psyco_adapters = NULL;
3737
/* pysqlite_microprotocols_init - initialize the adapters dictionary */
3838

3939
int
40-
pysqlite_microprotocols_init(PyObject *dict)
40+
pysqlite_microprotocols_init(PyObject *module)
4141
{
4242
/* create adapters dictionary and put it in module namespace */
4343
if ((psyco_adapters = PyDict_New()) == NULL) {
4444
return -1;
4545
}
4646

47-
return PyDict_SetItemString(dict, "adapters", psyco_adapters);
47+
if (PyModule_AddObject(module, "adapters", psyco_adapters) < 0) {
48+
Py_DECREF(psyco_adapters);
49+
return -1;
50+
}
51+
52+
return 0;
4853
}
4954

5055

Modules/_sqlite/microprotocols.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
/** exported functions **/
3939

4040
/* used by module.c to init the microprotocols system */
41-
extern int pysqlite_microprotocols_init(PyObject *dict);
41+
extern int pysqlite_microprotocols_init(PyObject *module);
4242
extern int pysqlite_microprotocols_add(
4343
PyTypeObject *type, PyObject *proto, PyObject *cast);
4444
extern PyObject *pysqlite_microprotocols_adapt(

Modules/_sqlite/module.c

Lines changed: 84 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,17 @@ PyDoc_STRVAR(enable_callback_tracebacks_doc,
236236
\n\
237237
Enable or disable callback functions throwing errors to stderr.");
238238

239-
static void converters_init(PyObject* dict)
239+
static void converters_init(PyObject* module)
240240
{
241241
_pysqlite_converters = PyDict_New();
242242
if (!_pysqlite_converters) {
243243
return;
244244
}
245245

246-
PyDict_SetItemString(dict, "converters", _pysqlite_converters);
246+
if (PyModule_AddObject(module, "converters", _pysqlite_converters) < 0) {
247+
Py_DECREF(_pysqlite_converters);
248+
}
249+
return;
247250
}
248251

249252
static PyMethodDef module_methods[] = {
@@ -264,59 +267,52 @@ static PyMethodDef module_methods[] = {
264267
{NULL, NULL}
265268
};
266269

267-
struct _IntConstantPair {
268-
const char *constant_name;
269-
int constant_value;
270-
};
271-
272-
typedef struct _IntConstantPair IntConstantPair;
273-
274-
static const IntConstantPair _int_constants[] = {
275-
{"PARSE_DECLTYPES", PARSE_DECLTYPES},
276-
{"PARSE_COLNAMES", PARSE_COLNAMES},
277-
278-
{"SQLITE_OK", SQLITE_OK},
279-
{"SQLITE_DENY", SQLITE_DENY},
280-
{"SQLITE_IGNORE", SQLITE_IGNORE},
281-
{"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX},
282-
{"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE},
283-
{"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX},
284-
{"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE},
285-
{"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER},
286-
{"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW},
287-
{"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER},
288-
{"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW},
289-
{"SQLITE_DELETE", SQLITE_DELETE},
290-
{"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX},
291-
{"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE},
292-
{"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX},
293-
{"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE},
294-
{"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER},
295-
{"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW},
296-
{"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER},
297-
{"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW},
298-
{"SQLITE_INSERT", SQLITE_INSERT},
299-
{"SQLITE_PRAGMA", SQLITE_PRAGMA},
300-
{"SQLITE_READ", SQLITE_READ},
301-
{"SQLITE_SELECT", SQLITE_SELECT},
302-
{"SQLITE_TRANSACTION", SQLITE_TRANSACTION},
303-
{"SQLITE_UPDATE", SQLITE_UPDATE},
304-
{"SQLITE_ATTACH", SQLITE_ATTACH},
305-
{"SQLITE_DETACH", SQLITE_DETACH},
306-
{"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE},
307-
{"SQLITE_REINDEX", SQLITE_REINDEX},
308-
{"SQLITE_ANALYZE", SQLITE_ANALYZE},
309-
{"SQLITE_CREATE_VTABLE", SQLITE_CREATE_VTABLE},
310-
{"SQLITE_DROP_VTABLE", SQLITE_DROP_VTABLE},
311-
{"SQLITE_FUNCTION", SQLITE_FUNCTION},
312-
{"SQLITE_SAVEPOINT", SQLITE_SAVEPOINT},
270+
static int add_integer_constants(PyObject *module) {
271+
int ret = 0;
272+
273+
ret += PyModule_AddIntMacro(module, PARSE_DECLTYPES);
274+
ret += PyModule_AddIntMacro(module, PARSE_COLNAMES);
275+
ret += PyModule_AddIntMacro(module, SQLITE_OK);
276+
ret += PyModule_AddIntMacro(module, SQLITE_DENY);
277+
ret += PyModule_AddIntMacro(module, SQLITE_IGNORE);
278+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_INDEX);
279+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TABLE);
280+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_INDEX);
281+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TABLE);
282+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TRIGGER);
283+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_VIEW);
284+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TRIGGER);
285+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VIEW);
286+
ret += PyModule_AddIntMacro(module, SQLITE_DELETE);
287+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_INDEX);
288+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TABLE);
289+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_INDEX);
290+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TABLE);
291+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TRIGGER);
292+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_VIEW);
293+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_TRIGGER);
294+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_VIEW);
295+
ret += PyModule_AddIntMacro(module, SQLITE_INSERT);
296+
ret += PyModule_AddIntMacro(module, SQLITE_PRAGMA);
297+
ret += PyModule_AddIntMacro(module, SQLITE_READ);
298+
ret += PyModule_AddIntMacro(module, SQLITE_SELECT);
299+
ret += PyModule_AddIntMacro(module, SQLITE_TRANSACTION);
300+
ret += PyModule_AddIntMacro(module, SQLITE_UPDATE);
301+
ret += PyModule_AddIntMacro(module, SQLITE_ATTACH);
302+
ret += PyModule_AddIntMacro(module, SQLITE_DETACH);
303+
ret += PyModule_AddIntMacro(module, SQLITE_ALTER_TABLE);
304+
ret += PyModule_AddIntMacro(module, SQLITE_REINDEX);
305+
ret += PyModule_AddIntMacro(module, SQLITE_ANALYZE);
306+
ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VTABLE);
307+
ret += PyModule_AddIntMacro(module, SQLITE_DROP_VTABLE);
308+
ret += PyModule_AddIntMacro(module, SQLITE_FUNCTION);
309+
ret += PyModule_AddIntMacro(module, SQLITE_SAVEPOINT);
313310
#if SQLITE_VERSION_NUMBER >= 3008003
314-
{"SQLITE_RECURSIVE", SQLITE_RECURSIVE},
311+
ret += PyModule_AddIntMacro(module, SQLITE_RECURSIVE);
315312
#endif
316-
{"SQLITE_DONE", SQLITE_DONE},
317-
{(char*)NULL, 0}
318-
};
319-
313+
ret += PyModule_AddIntMacro(module, SQLITE_DONE);
314+
return ret;
315+
}
320316

321317
static struct PyModuleDef _sqlite3module = {
322318
PyModuleDef_HEAD_INIT,
@@ -338,11 +334,21 @@ do { \
338334
} \
339335
} while (0)
340336

337+
#define ADD_EXCEPTION(module, name, exc, base) \
338+
do { \
339+
exc = PyErr_NewException(MODULE_NAME "." name, base, NULL); \
340+
if (!exc) { \
341+
goto error; \
342+
} \
343+
if (PyModule_AddObject(module, name, exc) < 0) { \
344+
Py_DECREF(exc); \
345+
goto error; \
346+
} \
347+
} while (0)
348+
341349
PyMODINIT_FUNC PyInit__sqlite3(void)
342350
{
343-
PyObject *module, *dict;
344-
PyObject *tmp_obj;
345-
int i;
351+
PyObject *module;
346352

347353
if (sqlite3_libversion_number() < 3007003) {
348354
PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.3 or higher required");
@@ -368,101 +374,53 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
368374
ADD_TYPE(module, *pysqlite_PrepareProtocolType);
369375
ADD_TYPE(module, *pysqlite_RowType);
370376

371-
if (!(dict = PyModule_GetDict(module))) {
372-
goto error;
373-
}
374-
375377
/*** Create DB-API Exception hierarchy */
376-
377-
if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_Exception, NULL))) {
378-
goto error;
379-
}
380-
PyDict_SetItemString(dict, "Error", pysqlite_Error);
381-
382-
if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_Exception, NULL))) {
383-
goto error;
384-
}
385-
PyDict_SetItemString(dict, "Warning", pysqlite_Warning);
378+
ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception);
379+
ADD_EXCEPTION(module, "Warning", pysqlite_Warning, PyExc_Exception);
386380

387381
/* Error subclasses */
388-
389-
if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) {
390-
goto error;
391-
}
392-
PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError);
393-
394-
if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) {
395-
goto error;
396-
}
397-
PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError);
382+
ADD_EXCEPTION(module, "InterfaceError", pysqlite_InterfaceError, pysqlite_Error);
383+
ADD_EXCEPTION(module, "DatabaseError", pysqlite_DatabaseError, pysqlite_Error);
398384

399385
/* pysqlite_DatabaseError subclasses */
400-
401-
if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) {
402-
goto error;
403-
}
404-
PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError);
405-
406-
if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) {
407-
goto error;
408-
}
409-
PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError);
410-
411-
if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) {
412-
goto error;
413-
}
414-
PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError);
415-
416-
if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) {
417-
goto error;
418-
}
419-
PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError);
420-
421-
if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) {
422-
goto error;
423-
}
424-
PyDict_SetItemString(dict, "DataError", pysqlite_DataError);
425-
426-
if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) {
427-
goto error;
428-
}
429-
PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError);
386+
ADD_EXCEPTION(module, "InternalError", pysqlite_InternalError, pysqlite_DatabaseError);
387+
ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError, pysqlite_DatabaseError);
388+
ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError, pysqlite_DatabaseError);
389+
ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError, pysqlite_DatabaseError);
390+
ADD_EXCEPTION(module, "DataError", pysqlite_DataError, pysqlite_DatabaseError);
391+
ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError, pysqlite_DatabaseError);
430392

431393
/* In Python 2.x, setting Connection.text_factory to
432394
OptimizedUnicode caused Unicode objects to be returned for
433395
non-ASCII data and bytestrings to be returned for ASCII data.
434396
Now OptimizedUnicode is an alias for str, so it has no
435397
effect. */
436398
Py_INCREF((PyObject*)&PyUnicode_Type);
437-
PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type);
399+
if (PyModule_AddObject(module, "OptimizedUnicode", (PyObject*)&PyUnicode_Type) < 0) {
400+
Py_DECREF((PyObject*)&PyUnicode_Type);
401+
goto error;
402+
}
438403

439404
/* Set integer constants */
440-
for (i = 0; _int_constants[i].constant_name != NULL; i++) {
441-
tmp_obj = PyLong_FromLong(_int_constants[i].constant_value);
442-
if (!tmp_obj) {
443-
goto error;
444-
}
445-
PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj);
446-
Py_DECREF(tmp_obj);
405+
if (add_integer_constants(module) < 0) {
406+
goto error;
447407
}
448408

449-
if (!(tmp_obj = PyUnicode_FromString(PYSQLITE_VERSION))) {
409+
if (PyModule_AddStringConstant(module, "version", PYSQLITE_VERSION) < 0) {
450410
goto error;
451411
}
452-
PyDict_SetItemString(dict, "version", tmp_obj);
453-
Py_DECREF(tmp_obj);
454412

455-
if (!(tmp_obj = PyUnicode_FromString(sqlite3_libversion()))) {
413+
if (PyModule_AddStringConstant(module, "sqlite_version", sqlite3_libversion())) {
456414
goto error;
457415
}
458-
PyDict_SetItemString(dict, "sqlite_version", tmp_obj);
459-
Py_DECREF(tmp_obj);
460416

461417
/* initialize microprotocols layer */
462-
pysqlite_microprotocols_init(dict);
418+
if (pysqlite_microprotocols_init(module) < 0) {
419+
goto error;
420+
}
463421

464422
/* initialize the default converters */
465-
converters_init(dict);
423+
converters_init(module);
466424

467425
error:
468426
if (PyErr_Occurred())

0 commit comments

Comments
 (0)