]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-89289: Harden sqlite3.Connection init (#92214)
authorErlend Egeberg Aasland <erlend.aasland@protonmail.com>
Tue, 3 May 2022 18:18:11 +0000 (12:18 -0600)
committerGitHub <noreply@github.com>
Tue, 3 May 2022 18:18:11 +0000 (12:18 -0600)
- Make sure SQLite resources are freed if database open fails
- Remove unneeded branches if init is aborted

Modules/_sqlite/connection.c

index 75d29704695c63d918584cfaaad13e999f3c73f0..793bc0b6aef0dbfad432d2289f338ab4222a4857 100644 (file)
@@ -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) \