| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -165,6 +165,14 @@ def test_delete_connection_text_factory(self): | |||
| 165 | 165 | with self.assertRaises(AttributeError): | |
| 166 | 166 | del self.con.text_factory | |
| 167 | 167 | ||
| 168 | + def test_delete_cursor_row_factory(self): | ||
| 169 | + # gh-149738: deleting row_factory should raise an exception | ||
| 170 | + cur = self.con.cursor() | ||
| 171 | + with self.assertRaises(AttributeError): | ||
| 172 | + del cur.row_factory | ||
| 173 | + # Executing a query here should succeed. | ||
| 174 | + self.assertEqual(tuple(cur.execute("select 1").fetchone()), (1,)) | ||
| 175 | + | ||
| 168 | 176 | def test_sqlite_row_index_unicode(self): | |
| 169 | 177 | row = self.con.execute("select 1 as \xff").fetchone() | |
| 170 | 178 | self.assertEqual(row["\xff"], 1) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + :mod:`sqlite3`: Disallow removing the ``row_factory`` attribute of a cursor | ||
| 2 | + to prevent a crash on a query. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1357,13 +1357,33 @@ static struct PyMemberDef cursor_members[] = | |||
| 1357 | 1357 | {"description", _Py_T_OBJECT, offsetof(pysqlite_Cursor, description), Py_READONLY}, | |
| 1358 | 1358 | {"lastrowid", _Py_T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), Py_READONLY}, | |
| 1359 | 1359 | {"rowcount", Py_T_LONG, offsetof(pysqlite_Cursor, rowcount), Py_READONLY}, | |
| 1360 | - {"row_factory", _Py_T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, | ||
| 1361 | 1360 | {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), Py_READONLY}, | |
| 1362 | 1361 | {NULL} | |
| 1363 | 1362 | }; | |
| 1364 | 1363 | ||
| 1364 | + static PyObject * | ||
| 1365 | + cursor_get_row_factory(PyObject *op, void *Py_UNUSED(closure)) | ||
| 1366 | + { | ||
| 1367 | + pysqlite_Cursor *self = (pysqlite_Cursor *)op; | ||
| 1368 | + return Py_NewRef(self->row_factory); | ||
| 1369 | + } | ||
| 1370 | + | ||
| 1371 | + static int | ||
| 1372 | + cursor_set_row_factory(PyObject *op, PyObject *value, void *Py_UNUSED(closure)) | ||
| 1373 | + { | ||
| 1374 | + pysqlite_Cursor *self = (pysqlite_Cursor *)op; | ||
| 1375 | + if (value == NULL) { | ||
| 1376 | + PyErr_SetString(PyExc_AttributeError, | ||
| 1377 | + "cannot delete row_factory attribute"); | ||
| 1378 | + return -1; | ||
| 1379 | + } | ||
| 1380 | + Py_XSETREF(self->row_factory, Py_NewRef(value)); | ||
| 1381 | + return 0; | ||
| 1382 | + } | ||
| 1383 | + | ||
| 1365 | 1384 | static struct PyGetSetDef cursor_getsets[] = { | |
| 1366 | 1385 | _SQLITE3_CURSOR_ARRAYSIZE_GETSETDEF | |
| 1386 | + {"row_factory", cursor_get_row_factory, cursor_set_row_factory}, | ||
| 1367 | 1387 | {NULL}, | |
| 1368 | 1388 | }; | |
| 1369 | 1389 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments