https://github.com/python/cpython/commit/3a2e7aacf6f414bbbedaf072e7cb1b48e3d402fa commit: 3a2e7aacf6f414bbbedaf072e7cb1b48e3d402fa branch: main author: Erlend E. Aasland <erl...@python.org> committer: erlend-aasland <erlend.aasl...@protonmail.com> date: 2025-02-11T08:26:01+01:00 summary:
gh-129928: Raise more accurate exception for incorrect sqlite3 UDF creation (#129941) Consistently raise ProgrammingError if the user tries to create an UDF with an invalid number of parameters. files: A Misc/NEWS.d/next/Library/2025-02-10-08-44-11.gh-issue-129928.QuiZEz.rst M Lib/test/test_sqlite3/test_userfunctions.py M Modules/_sqlite/connection.c diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 5bb2eff55ebc8f..3abc43a3b1afde 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -171,7 +171,7 @@ def tearDown(self): self.con.close() def test_func_error_on_create(self): - with self.assertRaises(sqlite.OperationalError): + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): self.con.create_function("bla", -100, lambda x: 2*x) def test_func_too_many_args(self): @@ -507,9 +507,8 @@ def test_win_sum_int(self): self.assertEqual(self.cur.fetchall(), self.expected) def test_win_error_on_create(self): - self.assertRaises(sqlite.ProgrammingError, - self.con.create_window_function, - "shouldfail", -100, WindowSumInt) + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): + self.con.create_window_function("shouldfail", -100, WindowSumInt) @with_tracebacks(BadWindow) def test_win_exception_in_method(self): @@ -638,7 +637,7 @@ def tearDown(self): self.con.close() def test_aggr_error_on_create(self): - with self.assertRaises(sqlite.OperationalError): + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): self.con.create_function("bla", -100, AggrSum) @with_tracebacks(AttributeError, msg_regex="AggrNoStep") diff --git a/Misc/NEWS.d/next/Library/2025-02-10-08-44-11.gh-issue-129928.QuiZEz.rst b/Misc/NEWS.d/next/Library/2025-02-10-08-44-11.gh-issue-129928.QuiZEz.rst new file mode 100644 index 00000000000000..9c24eb3992c907 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-10-08-44-11.gh-issue-129928.QuiZEz.rst @@ -0,0 +1,2 @@ +Raise :exc:`sqlite3.ProgrammingError` if a user-defined SQL function with +invalid number of parameters is created. Patch by Erlend Aasland. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 16afd7eada113f..a4191dd0a1cb2c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1139,6 +1139,20 @@ destructor_callback(void *ctx) } } +static int +check_num_params(pysqlite_Connection *self, const int n, const char *name) +{ + int limit = sqlite3_limit(self->db, SQLITE_LIMIT_FUNCTION_ARG, -1); + assert(limit >= 0); + if (n < -1 || n > limit) { + PyErr_Format(self->ProgrammingError, + "'%s' must be between -1 and %d, not %d", + name, limit, n); + return -1; + } + return 0; +} + /*[clinic input] _sqlite3.Connection.create_function as pysqlite_connection_create_function @@ -1167,6 +1181,9 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, narg, "narg") < 0) { + return NULL; + } if (deterministic) { flags |= SQLITE_DETERMINISTIC; @@ -1307,10 +1324,12 @@ create_window_function_impl(pysqlite_Connection *self, PyTypeObject *cls, "SQLite 3.25.0 or higher"); return NULL; } - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, num_params, "num_params") < 0) { + return NULL; + } int flags = SQLITE_UTF8; int rc; @@ -1367,6 +1386,9 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, n_arg, "n_arg") < 0) { + return NULL; + } callback_context *ctx = create_callback_context(cls, aggregate_class); if (ctx == NULL) { _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com