diff options
author | Erlend Egeberg Aasland <erlend.aasland@innova.no> | 2021-06-02 12:26:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-02 12:26:06 (GMT) |
commit | a384b6c04054a2c5050a99059836175cf73e2016 (patch) | |
tree | e55ca9e7067504c22ae77a5ba6df21e4312cd5b3 /Modules/_sqlite | |
parent | ee7637596d8de25f54261bbeabc602d31e74f482 (diff) | |
download | cpython-a384b6c04054a2c5050a99059836175cf73e2016.zip cpython-a384b6c04054a2c5050a99059836175cf73e2016.tar.gz cpython-a384b6c04054a2c5050a99059836175cf73e2016.tar.bz2 |
bpo-44165: Optimise sqlite3 statement preparation by passing string size (GH-26206)
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r-- | Modules/_sqlite/connection.c | 4 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 20 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 8 |
3 files changed, 25 insertions, 7 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 7252cca..e15629c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -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); diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 7656c90..757c389 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -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: diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 3a18ad8..c4a790c 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -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 |