summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-08-08 05:49:44 (GMT)
committerGitHub <noreply@github.com>2021-08-08 05:49:44 (GMT)
commit0eec6276fdcdde5221370d92b50ea95851760c72 (patch)
tree35fa0e56f83f404eb2120ec1963c6b5e15813d34 /Modules
parentebecffdb6d5fffa4249f9a813f1fc1915926feb5 (diff)
downloadcpython-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.h31
-rw-r--r--Modules/_sqlite/connection.c14
-rw-r--r--Modules/_sqlite/cursor.c37
-rw-r--r--Modules/_sqlite/statement.c3
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;
}