Skip to content

Commit e161ec5

Browse files
author
Erlend Egeberg Aasland
authored
bpo-43369: sqlite3_column_{text,blob} failures now raise MemoryError (GH-24723)
1 parent c61ec7e commit e161ec5

File tree

3 files changed

+48
-11
lines changed

3 files changed

+48
-11
lines changed

Lib/sqlite3/test/types.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,20 @@ def __conform__(self, protocol):
110110
def setUp(self):
111111
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
112112
self.cur = self.con.cursor()
113-
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)")
113+
self.cur.execute("""
114+
create table test(
115+
i int,
116+
s str,
117+
f float,
118+
b bool,
119+
u unicode,
120+
foo foo,
121+
bin blob,
122+
n1 number,
123+
n2 number(5),
124+
bad bad,
125+
cbin cblob)
126+
""")
114127

115128
# override float, make them always return the same number
116129
sqlite.converters["FLOAT"] = lambda x: 47.2
@@ -121,6 +134,7 @@ def setUp(self):
121134
sqlite.converters["BAD"] = DeclTypesTests.BadConform
122135
sqlite.converters["WRONG"] = lambda x: "WRONG"
123136
sqlite.converters["NUMBER"] = float
137+
sqlite.converters["CBLOB"] = lambda x: b"blobish"
124138

125139
def tearDown(self):
126140
del sqlite.converters["FLOAT"]
@@ -129,6 +143,7 @@ def tearDown(self):
129143
del sqlite.converters["BAD"]
130144
del sqlite.converters["WRONG"]
131145
del sqlite.converters["NUMBER"]
146+
del sqlite.converters["CBLOB"]
132147
self.cur.close()
133148
self.con.close()
134149

@@ -237,6 +252,12 @@ def test_number2(self):
237252
# if the converter is not used, it's an int instead of a float
238253
self.assertEqual(type(value), float)
239254

255+
def test_convert_zero_sized_blob(self):
256+
self.con.execute("insert into test(cbin) values (?)", (b"",))
257+
cur = self.con.execute("select cbin from test")
258+
self.assertEqual(cur.fetchone()[0], b"blobish")
259+
260+
240261
class ColNamesTests(unittest.TestCase):
241262
def setUp(self):
242263
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve :mod:`sqlite3` error handling: If ``sqlite3_column_text()`` and
2+
``sqlite3_column_blob()`` set ``SQLITE_NOMEM``, :exc:`MemoryError` is now
3+
raised. Patch by Erlend E. Aasland.

Modules/_sqlite/cursor.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
262262
if (!row)
263263
return NULL;
264264

265+
sqlite3 *db = self->connection->db;
265266
for (i = 0; i < numcols; i++) {
266267
if (self->connection->detect_types
267268
&& self->row_cast_map != NULL
@@ -280,17 +281,19 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
280281
* See https://sqlite.org/c3ref/column_blob.html for details.
281282
*/
282283
if (converter != Py_None) {
283-
const char *blob = (const char*)sqlite3_column_blob(self->statement->st, i);
284+
const void *blob = sqlite3_column_blob(self->statement->st, i);
285+
if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
286+
PyErr_NoMemory();
287+
goto error;
288+
}
289+
284290
nbytes = sqlite3_column_bytes(self->statement->st, i);
285-
if (!blob) {
286-
converted = Py_NewRef(Py_None);
287-
} else {
288-
item = PyBytes_FromStringAndSize(blob, nbytes);
289-
if (!item)
290-
goto error;
291-
converted = PyObject_CallOneArg(converter, item);
292-
Py_DECREF(item);
291+
item = PyBytes_FromStringAndSize(blob, nbytes);
292+
if (item == NULL) {
293+
goto error;
293294
}
295+
converted = PyObject_CallOneArg(converter, item);
296+
Py_DECREF(item);
294297
} else {
295298
Py_BEGIN_ALLOW_THREADS
296299
coltype = sqlite3_column_type(self->statement->st, i);
@@ -303,6 +306,11 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
303306
converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
304307
} else if (coltype == SQLITE_TEXT) {
305308
const char *text = (const char*)sqlite3_column_text(self->statement->st, i);
309+
if (text == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
310+
PyErr_NoMemory();
311+
goto error;
312+
}
313+
306314
nbytes = sqlite3_column_bytes(self->statement->st, i);
307315
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
308316
converted = PyUnicode_FromStringAndSize(text, nbytes);
@@ -332,7 +340,12 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
332340
}
333341
} else {
334342
/* coltype == SQLITE_BLOB */
335-
const char *blob = sqlite3_column_blob(self->statement->st, i);
343+
const void *blob = sqlite3_column_blob(self->statement->st, i);
344+
if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
345+
PyErr_NoMemory();
346+
goto error;
347+
}
348+
336349
nbytes = sqlite3_column_bytes(self->statement->st, i);
337350
converted = PyBytes_FromStringAndSize(blob, nbytes);
338351
}

0 commit comments

Comments
 (0)