]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44165: Optimise sqlite3 statement preparation by passing string size (GH-26206)
authorErlend Egeberg Aasland <erlend.aasland@innova.no>
Wed, 2 Jun 2021 12:26:06 +0000 (14:26 +0200)
committerGitHub <noreply@github.com>
Wed, 2 Jun 2021 12:26:06 +0000 (13:26 +0100)
Modules/_sqlite/connection.c
Modules/_sqlite/cursor.c
Modules/_sqlite/statement.c

index 7252ccab10b4bc2035221a09cf89493b786c5e98..e15629c8aba245aef208a157bf7922262dd83936 100644 (file)
@@ -451,7 +451,7 @@ pysqlite_connection_commit_impl(pysqlite_Connection *self)
     if (!sqlite3_get_autocommit(self->db)) {
 
         Py_BEGIN_ALLOW_THREADS
-        rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, NULL);
+        rc = sqlite3_prepare_v2(self->db, "COMMIT", 7, &statement, NULL);
         Py_END_ALLOW_THREADS
         if (rc != SQLITE_OK) {
             _pysqlite_seterror(self->db);
@@ -501,7 +501,7 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self)
         pysqlite_do_all_statements(self, ACTION_RESET, 1);
 
         Py_BEGIN_ALLOW_THREADS
-        rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, NULL);
+        rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL);
         Py_END_ALLOW_THREADS
         if (rc != SQLITE_OK) {
             _pysqlite_seterror(self->db);
index 7656c903a4acffc55a690be3e8f88cf2a3d89b0e..757c389c6a44ba73b9f14bb0d6e9b40dd28feaa7 100644 (file)
@@ -696,6 +696,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
     const char* script_cstr;
     sqlite3_stmt* statement;
     int rc;
+    Py_ssize_t sql_len;
     PyObject* result;
 
     if (!check_cursor(self)) {
@@ -705,10 +706,17 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
     self->reset = 0;
 
     if (PyUnicode_Check(script_obj)) {
-        script_cstr = PyUnicode_AsUTF8(script_obj);
+        script_cstr = PyUnicode_AsUTF8AndSize(script_obj, &sql_len);
         if (!script_cstr) {
             return NULL;
         }
+
+        int max_length = sqlite3_limit(self->connection->db,
+                                       SQLITE_LIMIT_LENGTH, -1);
+        if (sql_len >= max_length) {
+            PyErr_SetString(pysqlite_DataError, "query string is too large");
+            return NULL;
+        }
     } else {
         PyErr_SetString(PyExc_ValueError, "script argument must be unicode.");
         return NULL;
@@ -722,12 +730,14 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
     Py_DECREF(result);
 
     while (1) {
+        const char *tail;
+
         Py_BEGIN_ALLOW_THREADS
         rc = sqlite3_prepare_v2(self->connection->db,
                                 script_cstr,
-                                -1,
+                                (int)sql_len + 1,
                                 &statement,
-                                &script_cstr);
+                                &tail);
         Py_END_ALLOW_THREADS
         if (rc != SQLITE_OK) {
             _pysqlite_seterror(self->connection->db);
@@ -755,9 +765,11 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj)
             goto error;
         }
 
-        if (*script_cstr == (char)0) {
+        if (*tail == (char)0) {
             break;
         }
+        sql_len -= (tail - script_cstr);
+        script_cstr = tail;
     }
 
 error:
index 3a18ad8331f69f1fb61e8a1f915c2864de169f2f..c4a790c424e35a75d6a7857bf856244df6cb7668 100644 (file)
@@ -66,6 +66,12 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
                      Py_TYPE(sql)->tp_name);
         return NULL;
     }
+
+    int max_length = sqlite3_limit(connection->db, SQLITE_LIMIT_LENGTH, -1);
+    if (sql_cstr_len >= max_length) {
+        PyErr_SetString(pysqlite_DataError, "query string is too large");
+        return PYSQLITE_TOO_MUCH_SQL;
+    }
     if (strlen(sql_cstr) != (size_t)sql_cstr_len) {
         PyErr_SetString(PyExc_ValueError,
                         "the query contains a null character");
@@ -106,7 +112,7 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
     Py_BEGIN_ALLOW_THREADS
     rc = sqlite3_prepare_v2(self->db,
                             sql_cstr,
-                            -1,
+                            (int)sql_cstr_len + 1,
                             &self->st,
                             &tail);
     Py_END_ALLOW_THREADS