[Python-checkins] [3.11] gh-100370: fix OverflowError in sqlite3.Connection.blobopen for 32-bit builds (#103902) (#104285)
erlend-aasland
webhook-mailer at python.org
Mon May 8 04:42:19 EDT 2023
https://github.com/python/cpython/commit/681d5028bda41fb0755da443cea6be24bd2a0fdd
commit: 681d5028bda41fb0755da443cea6be24bd2a0fdd
branch: 3.11
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-05-08T08:41:34Z
summary:
[3.11] gh-100370: fix OverflowError in sqlite3.Connection.blobopen for 32-bit builds (#103902) (#104285)
files:
A Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst
M Lib/test/test_sqlite3/test_dbapi.py
M Modules/_sqlite/clinic/connection.c.h
M Modules/_sqlite/connection.c
diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py
index 9d94ddda95bd..899f5cfbd319 100644
--- a/Lib/test/test_sqlite3/test_dbapi.py
+++ b/Lib/test/test_sqlite3/test_dbapi.py
@@ -1461,6 +1461,14 @@ def test_blob_closed_db_read(self):
"Cannot operate on a closed database",
blob.read)
+ def test_blob_32bit_rowid(self):
+ # gh-100370: we should not get an OverflowError for 32-bit rowids
+ with memory_database() as cx:
+ rowid = 2**32
+ cx.execute("create table t(t blob)")
+ cx.execute("insert into t(rowid, t) values (?, zeroblob(1))", (rowid,))
+ cx.blobopen('t', 't', rowid)
+
@threading_helper.requires_working_threading()
class ThreadTests(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst b/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst
new file mode 100644
index 000000000000..9022d55c48cb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst
@@ -0,0 +1,2 @@
+Fix potential :exc:`OverflowError` in :meth:`sqlite3.Connection.blobopen`
+for 32-bit builds. Patch by Erlend E. Aasland.
diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h
index 62d31b787ad7..4bdf98b6933e 100644
--- a/Modules/_sqlite/clinic/connection.c.h
+++ b/Modules/_sqlite/clinic/connection.c.h
@@ -162,7 +162,7 @@ PyDoc_STRVAR(blobopen__doc__,
static PyObject *
blobopen_impl(pysqlite_Connection *self, const char *table, const char *col,
- int row, int readonly, const char *name);
+ sqlite3_int64 row, int readonly, const char *name);
static PyObject *
blobopen(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -174,7 +174,7 @@ blobopen(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyO
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;
const char *table;
const char *col;
- int row;
+ sqlite3_int64 row;
int readonly = 0;
const char *name = "main";
@@ -208,8 +208,7 @@ blobopen(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyO
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
- row = _PyLong_AsInt(args[2]);
- if (row == -1 && PyErr_Occurred()) {
+ if (!sqlite3_int64_converter(args[2], &row)) {
goto exit;
}
if (!noptargs) {
@@ -1237,4 +1236,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg)
#ifndef DESERIALIZE_METHODDEF
#define DESERIALIZE_METHODDEF
#endif /* !defined(DESERIALIZE_METHODDEF) */
-/*[clinic end generated code: output=8818c1c3ec9425aa input=a9049054013a1b77]*/
+/*[clinic end generated code: output=67e5b3dbade4a15b input=a9049054013a1b77]*/
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 20982558840b..9c7eb85df3b7 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -92,6 +92,20 @@ isolation_level_converter(PyObject *str_or_none, const char **result)
return 1;
}
+static int
+sqlite3_int64_converter(PyObject *obj, sqlite3_int64 *result)
+{
+ if (!PyLong_Check(obj)) {
+ PyErr_SetString(PyExc_TypeError, "expected 'int'");
+ return 0;
+ }
+ *result = _pysqlite_long_as_int64(obj);
+ if (PyErr_Occurred()) {
+ return 0;
+ }
+ return 1;
+}
+
#define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
#include "clinic/connection.c.h"
#undef clinic_state
@@ -137,8 +151,12 @@ class IsolationLevel_converter(CConverter):
type = "const char *"
converter = "isolation_level_converter"
+class sqlite3_int64_converter(CConverter):
+ type = "sqlite3_int64"
+ converter = "sqlite3_int64_converter"
+
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=cbcfe85b253061c2]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=e9bee126e0500e61]*/
// NB: This needs to be in sync with the sqlite3.connect docstring
/*[clinic input]
@@ -401,7 +419,7 @@ _sqlite3.Connection.blobopen as blobopen
Table name.
column as col: str
Column name.
- row: int
+ row: sqlite3_int64
Row index.
/
*
@@ -415,8 +433,8 @@ Open and return a BLOB object.
static PyObject *
blobopen_impl(pysqlite_Connection *self, const char *table, const char *col,
- int row, int readonly, const char *name)
-/*[clinic end generated code: output=0c8e2e58516d0b5c input=1e7052516acfc94d]*/
+ sqlite3_int64 row, int readonly, const char *name)
+/*[clinic end generated code: output=6a02d43efb885d1c input=4180b11a0591d80d]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
More information about the Python-checkins
mailing list