diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-08-08 05:49:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-08 05:49:44 (GMT) |
commit | 0eec6276fdcdde5221370d92b50ea95851760c72 (patch) | |
tree | 35fa0e56f83f404eb2120ec1963c6b5e15813d34 /Modules | |
parent | ebecffdb6d5fffa4249f9a813f1fc1915926feb5 (diff) | |
download | cpython-0eec6276fdcdde5221370d92b50ea95851760c72.zip cpython-0eec6276fdcdde5221370d92b50ea95851760c72.tar.gz cpython-0eec6276fdcdde5221370d92b50ea95851760c72.tar.bz2 |
bpo-44859: Improve error handling in sqlite3 and and raise more accurate exceptions. (GH-27654)
* MemoryError is now raised instead of sqlite3.Warning when
memory is not enough for encoding a statement to UTF-8
in Connection.__call__() and Cursor.execute().
* UnicodEncodeError is now raised instead of sqlite3.Warning when
the statement contains surrogate characters
in Connection.__call__() and Cursor.execute().
* TypeError is now raised instead of ValueError for non-string
script argument in Cursor.executescript().
* ValueError is now raised for script containing the null
character instead of truncating it in Cursor.executescript().
* Correctly handle exceptions raised when getting boolean value
of the result of the progress handler.
* Add many tests covering different corner cases.
Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_sqlite/clinic/cursor.c.h | 31 | ||||
-rw-r--r-- | Modules/_sqlite/connection.c | 14 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 37 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 3 |
4 files changed, 52 insertions, 33 deletions
diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h index d2c453b..07e1587 100644 --- a/Modules/_sqlite/clinic/cursor.c.h +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -119,6 +119,35 @@ PyDoc_STRVAR(pysqlite_cursor_executescript__doc__, #define PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF \ {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_O, pysqlite_cursor_executescript__doc__}, +static PyObject * +pysqlite_cursor_executescript_impl(pysqlite_Cursor *self, + const char *sql_script); + +static PyObject * +pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *sql_script; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("executescript", "argument", "str", arg); + goto exit; + } + Py_ssize_t sql_script_length; + sql_script = PyUnicode_AsUTF8AndSize(arg, &sql_script_length); + if (sql_script == NULL) { + goto exit; + } + if (strlen(sql_script) != (size_t)sql_script_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_cursor_executescript_impl(self, sql_script); + +exit: + return return_value; +} + PyDoc_STRVAR(pysqlite_cursor_fetchone__doc__, "fetchone($self, /)\n" "--\n" @@ -270,4 +299,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyTypeObject *cls, PyObject *const exit: return return_value; } -/*[clinic end generated code: output=7b216aba2439f5cf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ace31a7481aa3f41 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 0dab3e8..67160c4 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -997,6 +997,14 @@ static int _progress_handler(void* user_arg) ret = _PyObject_CallNoArg((PyObject*)user_arg); if (!ret) { + /* abort query if error occurred */ + rc = -1; + } + else { + rc = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + if (rc < 0) { pysqlite_state *state = pysqlite_get_state(NULL); if (state->enable_callback_tracebacks) { PyErr_Print(); @@ -1004,12 +1012,6 @@ static int _progress_handler(void* user_arg) else { PyErr_Clear(); } - - /* abort query if error occurred */ - rc = 1; - } else { - rc = (int)PyObject_IsTrue(ret); - Py_DECREF(ret); } PyGILState_Release(gilstate); diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 2f44946..7308f30 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -728,21 +728,21 @@ pysqlite_cursor_executemany_impl(pysqlite_Cursor *self, PyObject *sql, /*[clinic input] _sqlite3.Cursor.executescript as pysqlite_cursor_executescript - sql_script as script_obj: object + sql_script: str / Executes multiple SQL statements at once. Non-standard. [clinic start generated code]*/ static PyObject * -pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) -/*[clinic end generated code: output=115a8132b0f200fe input=ba3ec59df205e362]*/ +pysqlite_cursor_executescript_impl(pysqlite_Cursor *self, + const char *sql_script) +/*[clinic end generated code: output=8fd726dde1c65164 input=1ac0693dc8db02a8]*/ { _Py_IDENTIFIER(commit); - const char* script_cstr; sqlite3_stmt* statement; int rc; - Py_ssize_t sql_len; + size_t sql_len; PyObject* result; if (!check_cursor(self)) { @@ -751,21 +751,12 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) self->reset = 0; - if (PyUnicode_Check(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(self->connection->DataError, - "query string is too large"); - return NULL; - } - } else { - PyErr_SetString(PyExc_ValueError, "script argument must be unicode."); + sql_len = strlen(sql_script); + int max_length = sqlite3_limit(self->connection->db, + SQLITE_LIMIT_LENGTH, -1); + if (sql_len >= (unsigned)max_length) { + PyErr_SetString(self->connection->DataError, + "query string is too large"); return NULL; } @@ -782,7 +773,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) Py_BEGIN_ALLOW_THREADS rc = sqlite3_prepare_v2(self->connection->db, - script_cstr, + sql_script, (int)sql_len + 1, &statement, &tail); @@ -816,8 +807,8 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) if (*tail == (char)0) { break; } - sql_len -= (tail - script_cstr); - script_cstr = tail; + sql_len -= (tail - sql_script); + sql_script = tail; } error: diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 983df2d..2d5c72d 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -56,9 +56,6 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) Py_ssize_t size; const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size); if (sql_cstr == NULL) { - PyErr_Format(connection->Warning, - "SQL is of wrong type ('%s'). Must be string.", - Py_TYPE(sql)->tp_name); return NULL; } |