summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlend Egeberg Aasland <erlend.aasland@protonmail.com>2022-05-03 18:18:11 (GMT)
committerGitHub <noreply@github.com>2022-05-03 18:18:11 (GMT)
commitc278474df97de310535425c207136bf26c663e0b (patch)
treef86f382dac8be2ff7b96ecf232a9cdb51d613c46
parent2eca5dad0a783153318e91e3e25f16a38a632bfd (diff)
downloadcpython-c278474df97de310535425c207136bf26c663e0b.zip
cpython-c278474df97de310535425c207136bf26c663e0b.tar.gz
cpython-c278474df97de310535425c207136bf26c663e0b.tar.bz2
gh-89289: Harden sqlite3.Connection init (#92214)
- Make sure SQLite resources are freed if database open fails - Remove unneeded branches if init is aborted
-rw-r--r--Modules/_sqlite/connection.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 75d2970..793bc0b 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -226,27 +226,27 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
if (rc != SQLITE_OK) {
_pysqlite_seterror(state, db);
- return -1;
+ goto error;
}
// Create LRU statement cache; returns a new reference.
PyObject *statement_cache = new_statement_cache(self, state, cache_size);
if (statement_cache == NULL) {
- return -1;
+ goto error;
}
/* Create lists of weak references to cursors and blobs */
PyObject *cursors = PyList_New(0);
if (cursors == NULL) {
- Py_XDECREF(statement_cache);
- return -1;
+ Py_DECREF(statement_cache);
+ goto error;
}
PyObject *blobs = PyList_New(0);
if (blobs == NULL) {
- Py_XDECREF(statement_cache);
- Py_XDECREF(cursors);
- return -1;
+ Py_DECREF(statement_cache);
+ Py_DECREF(cursors);
+ goto error;
}
// Init connection state members.
@@ -279,11 +279,18 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
self->NotSupportedError = state->NotSupportedError;
if (PySys_Audit("sqlite3.connect/handle", "O", self) < 0) {
- return -1;
+ return -1; // Don't goto error; at this point, dealloc will clean up.
}
self->initialized = 1;
return 0;
+
+error:
+ // There are no statements or other SQLite objects attached to the
+ // database, so sqlite3_close() should always return SQLITE_OK.
+ rc = sqlite3_close(db);
+ assert(rc == SQLITE_OK), rc;
+ return -1;
}
#define VISIT_CALLBACK_CONTEXT(ctx) \