mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-42021: Fix possible ref leaks during _sqlite3 module init (GH-22673)
This commit is contained in:
		
							parent
							
								
									b67cbbda3a
								
							
						
					
					
						commit
						644e94272a
					
				
					 4 changed files with 94 additions and 130 deletions
				
			
		|  | @ -0,0 +1 @@ | ||||||
|  | Fix possible ref leaks in :mod:`sqlite3` module init. | ||||||
|  | @ -37,14 +37,19 @@ static PyObject *psyco_adapters = NULL; | ||||||
| /* pysqlite_microprotocols_init - initialize the adapters dictionary */ | /* pysqlite_microprotocols_init - initialize the adapters dictionary */ | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| pysqlite_microprotocols_init(PyObject *dict) | pysqlite_microprotocols_init(PyObject *module) | ||||||
| { | { | ||||||
|     /* create adapters dictionary and put it in module namespace */ |     /* create adapters dictionary and put it in module namespace */ | ||||||
|     if ((psyco_adapters = PyDict_New()) == NULL) { |     if ((psyco_adapters = PyDict_New()) == NULL) { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return PyDict_SetItemString(dict, "adapters", psyco_adapters); |     if (PyModule_AddObject(module, "adapters", psyco_adapters) < 0) { | ||||||
|  |         Py_DECREF(psyco_adapters); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ | ||||||
| /** exported functions **/ | /** exported functions **/ | ||||||
| 
 | 
 | ||||||
| /* used by module.c to init the microprotocols system */ | /* used by module.c to init the microprotocols system */ | ||||||
| extern int pysqlite_microprotocols_init(PyObject *dict); | extern int pysqlite_microprotocols_init(PyObject *module); | ||||||
| extern int pysqlite_microprotocols_add( | extern int pysqlite_microprotocols_add( | ||||||
|     PyTypeObject *type, PyObject *proto, PyObject *cast); |     PyTypeObject *type, PyObject *proto, PyObject *cast); | ||||||
| extern PyObject *pysqlite_microprotocols_adapt( | extern PyObject *pysqlite_microprotocols_adapt( | ||||||
|  |  | ||||||
|  | @ -236,14 +236,17 @@ PyDoc_STRVAR(enable_callback_tracebacks_doc, | ||||||
| \n\ | \n\ | ||||||
| Enable or disable callback functions throwing errors to stderr."); | Enable or disable callback functions throwing errors to stderr."); | ||||||
| 
 | 
 | ||||||
| static void converters_init(PyObject* dict) | static void converters_init(PyObject* module) | ||||||
| { | { | ||||||
|     _pysqlite_converters = PyDict_New(); |     _pysqlite_converters = PyDict_New(); | ||||||
|     if (!_pysqlite_converters) { |     if (!_pysqlite_converters) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyDict_SetItemString(dict, "converters", _pysqlite_converters); |     if (PyModule_AddObject(module, "converters", _pysqlite_converters) < 0) { | ||||||
|  |         Py_DECREF(_pysqlite_converters); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyMethodDef module_methods[] = { | static PyMethodDef module_methods[] = { | ||||||
|  | @ -264,59 +267,52 @@ static PyMethodDef module_methods[] = { | ||||||
|     {NULL, NULL} |     {NULL, NULL} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct _IntConstantPair { | static int add_integer_constants(PyObject *module) { | ||||||
|     const char *constant_name; |     int ret = 0; | ||||||
|     int constant_value; |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| typedef struct _IntConstantPair IntConstantPair; |     ret += PyModule_AddIntMacro(module, PARSE_DECLTYPES); | ||||||
| 
 |     ret += PyModule_AddIntMacro(module, PARSE_COLNAMES); | ||||||
| static const IntConstantPair _int_constants[] = { |     ret += PyModule_AddIntMacro(module, SQLITE_OK); | ||||||
|     {"PARSE_DECLTYPES", PARSE_DECLTYPES}, |     ret += PyModule_AddIntMacro(module, SQLITE_DENY); | ||||||
|     {"PARSE_COLNAMES", PARSE_COLNAMES}, |     ret += PyModule_AddIntMacro(module, SQLITE_IGNORE); | ||||||
| 
 |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_INDEX); | ||||||
|     {"SQLITE_OK", SQLITE_OK}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TABLE); | ||||||
|     {"SQLITE_DENY", SQLITE_DENY}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_INDEX); | ||||||
|     {"SQLITE_IGNORE", SQLITE_IGNORE}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TABLE); | ||||||
|     {"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TRIGGER); | ||||||
|     {"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_VIEW); | ||||||
|     {"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TRIGGER); | ||||||
|     {"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VIEW); | ||||||
|     {"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER}, |     ret += PyModule_AddIntMacro(module, SQLITE_DELETE); | ||||||
|     {"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_INDEX); | ||||||
|     {"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TABLE); | ||||||
|     {"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_INDEX); | ||||||
|     {"SQLITE_DELETE", SQLITE_DELETE}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TABLE); | ||||||
|     {"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TRIGGER); | ||||||
|     {"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_VIEW); | ||||||
|     {"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_TRIGGER); | ||||||
|     {"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_VIEW); | ||||||
|     {"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER}, |     ret += PyModule_AddIntMacro(module, SQLITE_INSERT); | ||||||
|     {"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW}, |     ret += PyModule_AddIntMacro(module, SQLITE_PRAGMA); | ||||||
|     {"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER}, |     ret += PyModule_AddIntMacro(module, SQLITE_READ); | ||||||
|     {"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW}, |     ret += PyModule_AddIntMacro(module, SQLITE_SELECT); | ||||||
|     {"SQLITE_INSERT", SQLITE_INSERT}, |     ret += PyModule_AddIntMacro(module, SQLITE_TRANSACTION); | ||||||
|     {"SQLITE_PRAGMA", SQLITE_PRAGMA}, |     ret += PyModule_AddIntMacro(module, SQLITE_UPDATE); | ||||||
|     {"SQLITE_READ", SQLITE_READ}, |     ret += PyModule_AddIntMacro(module, SQLITE_ATTACH); | ||||||
|     {"SQLITE_SELECT", SQLITE_SELECT}, |     ret += PyModule_AddIntMacro(module, SQLITE_DETACH); | ||||||
|     {"SQLITE_TRANSACTION", SQLITE_TRANSACTION}, |     ret += PyModule_AddIntMacro(module, SQLITE_ALTER_TABLE); | ||||||
|     {"SQLITE_UPDATE", SQLITE_UPDATE}, |     ret += PyModule_AddIntMacro(module, SQLITE_REINDEX); | ||||||
|     {"SQLITE_ATTACH", SQLITE_ATTACH}, |     ret += PyModule_AddIntMacro(module, SQLITE_ANALYZE); | ||||||
|     {"SQLITE_DETACH", SQLITE_DETACH}, |     ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VTABLE); | ||||||
|     {"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE}, |     ret += PyModule_AddIntMacro(module, SQLITE_DROP_VTABLE); | ||||||
|     {"SQLITE_REINDEX", SQLITE_REINDEX}, |     ret += PyModule_AddIntMacro(module, SQLITE_FUNCTION); | ||||||
|     {"SQLITE_ANALYZE", SQLITE_ANALYZE}, |     ret += PyModule_AddIntMacro(module, SQLITE_SAVEPOINT); | ||||||
|     {"SQLITE_CREATE_VTABLE", SQLITE_CREATE_VTABLE}, |  | ||||||
|     {"SQLITE_DROP_VTABLE", SQLITE_DROP_VTABLE}, |  | ||||||
|     {"SQLITE_FUNCTION", SQLITE_FUNCTION}, |  | ||||||
|     {"SQLITE_SAVEPOINT", SQLITE_SAVEPOINT}, |  | ||||||
| #if SQLITE_VERSION_NUMBER >= 3008003 | #if SQLITE_VERSION_NUMBER >= 3008003 | ||||||
|     {"SQLITE_RECURSIVE", SQLITE_RECURSIVE}, |     ret += PyModule_AddIntMacro(module, SQLITE_RECURSIVE); | ||||||
| #endif | #endif | ||||||
|     {"SQLITE_DONE", SQLITE_DONE}, |     ret += PyModule_AddIntMacro(module, SQLITE_DONE); | ||||||
|     {(char*)NULL, 0} |     return ret; | ||||||
| }; | } | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| static struct PyModuleDef _sqlite3module = { | static struct PyModuleDef _sqlite3module = { | ||||||
|         PyModuleDef_HEAD_INIT, |         PyModuleDef_HEAD_INIT, | ||||||
|  | @ -338,11 +334,21 @@ do {                                           \ | ||||||
|     }                                          \ |     }                                          \ | ||||||
| } while (0) | } while (0) | ||||||
| 
 | 
 | ||||||
|  | #define ADD_EXCEPTION(module, name, exc, base)                  \ | ||||||
|  | do {                                                            \ | ||||||
|  |     exc = PyErr_NewException(MODULE_NAME "." name, base, NULL); \ | ||||||
|  |     if (!exc) {                                                 \ | ||||||
|  |         goto error;                                             \ | ||||||
|  |     }                                                           \ | ||||||
|  |     if (PyModule_AddObject(module, name, exc) < 0) {            \ | ||||||
|  |         Py_DECREF(exc);                                         \ | ||||||
|  |         goto error;                                             \ | ||||||
|  |     }                                                           \ | ||||||
|  | } while (0) | ||||||
|  | 
 | ||||||
| PyMODINIT_FUNC PyInit__sqlite3(void) | PyMODINIT_FUNC PyInit__sqlite3(void) | ||||||
| { | { | ||||||
|     PyObject *module, *dict; |     PyObject *module; | ||||||
|     PyObject *tmp_obj; |  | ||||||
|     int i; |  | ||||||
| 
 | 
 | ||||||
|     if (sqlite3_libversion_number() < 3007003) { |     if (sqlite3_libversion_number() < 3007003) { | ||||||
|         PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.3 or higher required"); |         PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.3 or higher required"); | ||||||
|  | @ -368,65 +374,21 @@ PyMODINIT_FUNC PyInit__sqlite3(void) | ||||||
|     ADD_TYPE(module, *pysqlite_PrepareProtocolType); |     ADD_TYPE(module, *pysqlite_PrepareProtocolType); | ||||||
|     ADD_TYPE(module, *pysqlite_RowType); |     ADD_TYPE(module, *pysqlite_RowType); | ||||||
| 
 | 
 | ||||||
|     if (!(dict = PyModule_GetDict(module))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /*** Create DB-API Exception hierarchy */ |     /*** Create DB-API Exception hierarchy */ | ||||||
| 
 |     ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception); | ||||||
|     if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_Exception, NULL))) { |     ADD_EXCEPTION(module, "Warning", pysqlite_Warning, PyExc_Exception); | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "Error", pysqlite_Error); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_Exception, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "Warning", pysqlite_Warning); |  | ||||||
| 
 | 
 | ||||||
|     /* Error subclasses */ |     /* Error subclasses */ | ||||||
| 
 |     ADD_EXCEPTION(module, "InterfaceError", pysqlite_InterfaceError, pysqlite_Error); | ||||||
|     if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) { |     ADD_EXCEPTION(module, "DatabaseError", pysqlite_DatabaseError, pysqlite_Error); | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError); |  | ||||||
| 
 | 
 | ||||||
|     /* pysqlite_DatabaseError subclasses */ |     /* pysqlite_DatabaseError subclasses */ | ||||||
| 
 |     ADD_EXCEPTION(module, "InternalError", pysqlite_InternalError, pysqlite_DatabaseError); | ||||||
|     if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) { |     ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError, pysqlite_DatabaseError); | ||||||
|         goto error; |     ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError, pysqlite_DatabaseError); | ||||||
|     } |     ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError, pysqlite_DatabaseError); | ||||||
|     PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError); |     ADD_EXCEPTION(module, "DataError", pysqlite_DataError, pysqlite_DatabaseError); | ||||||
| 
 |     ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError, pysqlite_DatabaseError); | ||||||
|     if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "DataError", pysqlite_DataError); |  | ||||||
| 
 |  | ||||||
|     if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); |  | ||||||
| 
 | 
 | ||||||
|     /* In Python 2.x, setting Connection.text_factory to
 |     /* In Python 2.x, setting Connection.text_factory to
 | ||||||
|        OptimizedUnicode caused Unicode objects to be returned for |        OptimizedUnicode caused Unicode objects to be returned for | ||||||
|  | @ -434,35 +396,31 @@ PyMODINIT_FUNC PyInit__sqlite3(void) | ||||||
|        Now OptimizedUnicode is an alias for str, so it has no |        Now OptimizedUnicode is an alias for str, so it has no | ||||||
|        effect. */ |        effect. */ | ||||||
|     Py_INCREF((PyObject*)&PyUnicode_Type); |     Py_INCREF((PyObject*)&PyUnicode_Type); | ||||||
|     PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type); |     if (PyModule_AddObject(module, "OptimizedUnicode", (PyObject*)&PyUnicode_Type) < 0) { | ||||||
|  |         Py_DECREF((PyObject*)&PyUnicode_Type); | ||||||
|  |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* Set integer constants */ |     /* Set integer constants */ | ||||||
|     for (i = 0; _int_constants[i].constant_name != NULL; i++) { |     if (add_integer_constants(module) < 0) { | ||||||
|         tmp_obj = PyLong_FromLong(_int_constants[i].constant_value); |  | ||||||
|         if (!tmp_obj) { |  | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|         PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj); |  | ||||||
|         Py_DECREF(tmp_obj); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (!(tmp_obj = PyUnicode_FromString(PYSQLITE_VERSION))) { |     if (PyModule_AddStringConstant(module, "version", PYSQLITE_VERSION) < 0) { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|     PyDict_SetItemString(dict, "version", tmp_obj); |  | ||||||
|     Py_DECREF(tmp_obj); |  | ||||||
| 
 | 
 | ||||||
|     if (!(tmp_obj = PyUnicode_FromString(sqlite3_libversion()))) { |     if (PyModule_AddStringConstant(module, "sqlite_version", sqlite3_libversion())) { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|     PyDict_SetItemString(dict, "sqlite_version", tmp_obj); |  | ||||||
|     Py_DECREF(tmp_obj); |  | ||||||
| 
 | 
 | ||||||
|     /* initialize microprotocols layer */ |     /* initialize microprotocols layer */ | ||||||
|     pysqlite_microprotocols_init(dict); |     if (pysqlite_microprotocols_init(module) < 0) { | ||||||
|  |         goto error; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /* initialize the default converters */ |     /* initialize the default converters */ | ||||||
|     converters_init(dict); |     converters_init(module); | ||||||
| 
 | 
 | ||||||
| error: | error: | ||||||
|     if (PyErr_Occurred()) |     if (PyErr_Occurred()) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Erlend Egeberg Aasland
						Erlend Egeberg Aasland