mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
bpo-43369: sqlite3_column_{text,blob} failures now raise MemoryError (GH-24723)
This commit is contained in:
parent
c61ec7e6b8
commit
e161ec5dd7
3 changed files with 49 additions and 12 deletions
|
@ -110,7 +110,20 @@ class DeclTypesTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
|
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
|
||||||
self.cur = self.con.cursor()
|
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
|
# override float, make them always return the same number
|
||||||
sqlite.converters["FLOAT"] = lambda x: 47.2
|
sqlite.converters["FLOAT"] = lambda x: 47.2
|
||||||
|
@ -121,6 +134,7 @@ class DeclTypesTests(unittest.TestCase):
|
||||||
sqlite.converters["BAD"] = DeclTypesTests.BadConform
|
sqlite.converters["BAD"] = DeclTypesTests.BadConform
|
||||||
sqlite.converters["WRONG"] = lambda x: "WRONG"
|
sqlite.converters["WRONG"] = lambda x: "WRONG"
|
||||||
sqlite.converters["NUMBER"] = float
|
sqlite.converters["NUMBER"] = float
|
||||||
|
sqlite.converters["CBLOB"] = lambda x: b"blobish"
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
del sqlite.converters["FLOAT"]
|
del sqlite.converters["FLOAT"]
|
||||||
|
@ -129,6 +143,7 @@ class DeclTypesTests(unittest.TestCase):
|
||||||
del sqlite.converters["BAD"]
|
del sqlite.converters["BAD"]
|
||||||
del sqlite.converters["WRONG"]
|
del sqlite.converters["WRONG"]
|
||||||
del sqlite.converters["NUMBER"]
|
del sqlite.converters["NUMBER"]
|
||||||
|
del sqlite.converters["CBLOB"]
|
||||||
self.cur.close()
|
self.cur.close()
|
||||||
self.con.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
|
# if the converter is not used, it's an int instead of a float
|
||||||
self.assertEqual(type(value), 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):
|
class ColNamesTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
|
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
|
||||||
|
|
|
@ -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.
|
|
@ -262,6 +262,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
|
||||||
if (!row)
|
if (!row)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
sqlite3 *db = self->connection->db;
|
||||||
for (i = 0; i < numcols; i++) {
|
for (i = 0; i < numcols; i++) {
|
||||||
if (self->connection->detect_types
|
if (self->connection->detect_types
|
||||||
&& self->row_cast_map != NULL
|
&& 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.
|
* See https://sqlite.org/c3ref/column_blob.html for details.
|
||||||
*/
|
*/
|
||||||
if (converter != Py_None) {
|
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);
|
||||||
nbytes = sqlite3_column_bytes(self->statement->st, i);
|
if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) {
|
||||||
if (!blob) {
|
PyErr_NoMemory();
|
||||||
converted = Py_NewRef(Py_None);
|
goto error;
|
||||||
} else {
|
|
||||||
item = PyBytes_FromStringAndSize(blob, nbytes);
|
|
||||||
if (!item)
|
|
||||||
goto error;
|
|
||||||
converted = PyObject_CallOneArg(converter, item);
|
|
||||||
Py_DECREF(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nbytes = sqlite3_column_bytes(self->statement->st, i);
|
||||||
|
item = PyBytes_FromStringAndSize(blob, nbytes);
|
||||||
|
if (item == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
converted = PyObject_CallOneArg(converter, item);
|
||||||
|
Py_DECREF(item);
|
||||||
} else {
|
} else {
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
coltype = sqlite3_column_type(self->statement->st, i);
|
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));
|
converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
|
||||||
} else if (coltype == SQLITE_TEXT) {
|
} else if (coltype == SQLITE_TEXT) {
|
||||||
const char *text = (const char*)sqlite3_column_text(self->statement->st, i);
|
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);
|
nbytes = sqlite3_column_bytes(self->statement->st, i);
|
||||||
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
|
if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) {
|
||||||
converted = PyUnicode_FromStringAndSize(text, nbytes);
|
converted = PyUnicode_FromStringAndSize(text, nbytes);
|
||||||
|
@ -332,7 +340,12 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* coltype == SQLITE_BLOB */
|
/* 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);
|
nbytes = sqlite3_column_bytes(self->statement->st, i);
|
||||||
converted = PyBytes_FromStringAndSize(blob, nbytes);
|
converted = PyBytes_FromStringAndSize(blob, nbytes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue