gh-100370: fix OverflowError in sqlite3.Connection.blobopen for 32-bit builds (#103902)

This commit is contained in:
Erlend E. Aasland 2023-05-07 12:55:31 +02:00 committed by GitHub
parent cab1298a60
commit a05bad3254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 9 deletions

View File

@ -1495,6 +1495,14 @@ class BlobTests(unittest.TestCase):
"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):

View File

@ -0,0 +1,2 @@
Fix potential :exc:`OverflowError` in :meth:`sqlite3.Connection.blobopen`
for 32-bit builds. Patch by Erlend E. Aasland.

View File

@ -228,7 +228,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)
@ -263,7 +263,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";
@ -297,8 +297,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) {
@ -1666,4 +1665,4 @@ exit:
#ifndef DESERIALIZE_METHODDEF
#define DESERIALIZE_METHODDEF
#endif /* !defined(DESERIALIZE_METHODDEF) */
/*[clinic end generated code: output=8b03149c115ee6da input=a9049054013a1b77]*/
/*[clinic end generated code: output=834a99827555bf1a input=a9049054013a1b77]*/

View File

@ -118,6 +118,20 @@ autocommit_converter(PyObject *val, enum autocommit_mode *result)
return 0;
}
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
@ -188,8 +202,12 @@ class Autocommit_converter(CConverter):
type = "enum autocommit_mode"
converter = "autocommit_converter"
class sqlite3_int64_converter(CConverter):
type = "sqlite3_int64"
converter = "sqlite3_int64_converter"
[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=bc2aa6c7ba0c5f8f]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=dff8760fb1eba6a1]*/
// NB: This needs to be in sync with the sqlite3.connect docstring
/*[clinic input]
@ -483,7 +501,7 @@ _sqlite3.Connection.blobopen as blobopen
Table name.
column as col: str
Column name.
row: int
row: sqlite3_int64
Row index.
/
*
@ -497,8 +515,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=fa73c83aa7a7ddee]*/
sqlite3_int64 row, int readonly, const char *name)
/*[clinic end generated code: output=6a02d43efb885d1c input=23576bd1108d8774]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;