summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/sqlite3/test/types.py23
-rw-r--r--Misc/NEWS.d/next/Library/2021-03-02-15-25-28.bpo-43369.F4knlQ.rst3
-rw-r--r--Modules/_sqlite/cursor.c33
3 files changed, 48 insertions, 11 deletions
diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py
index 92ec634..2370dd1 100644
--- a/Lib/sqlite3/test/types.py
+++ b/Lib/sqlite3/test/types.py
@@ -110,7 +110,20 @@ class DeclTypesTests(unittest.TestCase):
def setUp(self):
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
self.cur = self.con.cursor()
- self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob, n1 number, n2 number(5), bad bad)")
+ self.cur.execute("""
+ create table test(
+ i int,
+ s str,
+ f float,
+ b bool,
+ u unicode,
+ foo foo,
+ bin blob,
+ n1 number,
+ n2 number(5),
+ bad bad,
+ cbin cblob)
+ """)
# override float, make them always return the same number
sqlite.converters["FLOAT"] = lambda x: 47.2
@@ -121,6 +134,7 @@ class DeclTypesTests(unittest.TestCase):
sqlite.converters["BAD"] = DeclTypesTests.BadConform
sqlite.converters["WRONG"] = lambda x: "WRONG"
sqlite.converters["NUMBER"] = float
+ sqlite.converters["CBLOB"] = lambda x: b"blobish"
def tearDown(self):
del sqlite.converters["FLOAT"]
@@ -129,6 +143,7 @@ class DeclTypesTests(unittest.TestCase):
del sqlite.converters["BAD"]
del sqlite.converters["WRONG"]
del sqlite.converters["NUMBER"]
+ del sqlite.converters["CBLOB"]
self.cur.close()
self.con.close()
@@ -237,6 +252,12 @@ class DeclTypesTests(unittest.TestCase):
# if the converter is not used, it's an int instead of a float
self.assertEqual(type(value), float)
+ def test_convert_zero_sized_blob(self):
+ self.con.execute("insert into test(cbin) values (?)", (b"",))
+ cur = self.con.execute("select cbin from test")
+ self.assertEqual(cur.fetchone()[0], b"blobish")
+
+
class ColNamesTests(unittest.TestCase):
def setUp(self):
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
diff --git a/Misc/NEWS.d/next/Library/2021-03-02-15-25-28.bpo-43369.F4knlQ.rst b/Misc/NEWS.d/next/Library/2021-03-02-15-25-28.bpo-43369.F4knlQ.rst
new file mode 100644
index 0000000..f88a707
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-03-02-15-25-28.bpo-43369.F4knlQ.rst
@@ -0,0 +1,3 @@
+Improve :mod:`sqlite3` error handling: If ``sqlite3_column_text()`` and
+``sqlite3_column_blob()`` set ``SQLITE_NOMEM``, :exc:`MemoryError` is now
+raised. Patch by Erlend E. Aasland.
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 764eec5..dfaa557 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -262,6 +262,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
if (!row)
return NULL;
+ sqlite3 *db = self->connection->db;
for (i = 0; i < numcols; i++) {
if (self->connection->detect_types
&& self->row_cast_map != NULL
@@ -280,17 +281,19 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
* See https://sqlite.org/c3ref/column_blob.html for details.
*/
if (converter != Py_None) {
- const char *blob = (const char*)sqlite3_column_blob(self->statement->st, i);
+ const void *blob = sqlite3_column_blob(self->statement->st, i);
+ if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
nbytes = sqlite3_column_bytes(self->statement->st, i);
- if (!blob) {
- converted = Py_NewRef(Py_None);
- } else {
- item = PyBytes_FromStringAndSize(blob, nbytes);
- if (!item)
- goto error;
- converted = PyObject_CallOneArg(converter, item);
- Py_DECREF(item);
+ item = PyBytes_FromStringAndSize(blob, nbytes);
+ if (item == NULL) {
+ goto error;
}
+ converted = PyObject_CallOneArg(converter, item);
+ Py_DECREF(item);
} else {
Py_BEGIN_ALLOW_THREADS
coltype = sqlite3_column_type(self->statement->st, i);
@@ -303,6 +306,11 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
} else if (coltype == SQLITE_TEXT) {
const char *text = (const char*)sqlite3_column_text(self->statement->st, i);
+ if (text == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
nbytes = sqlite3_column_bytes(self->statement->st, i);
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
converted = PyUnicode_FromStringAndSize(text, nbytes);
@@ -332,7 +340,12 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
}
} else {
/* coltype == SQLITE_BLOB */
- const char *blob = sqlite3_column_blob(self->statement->st, i);
+ const void *blob = sqlite3_column_blob(self->statement->st, i);
+ if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
nbytes = sqlite3_column_bytes(self->statement->st, i);
converted = PyBytes_FromStringAndSize(blob, nbytes);
}