|
27 | 27 | import functools |
28 | 28 |
|
29 | 29 | from test import support |
| 30 | +from unittest.mock import patch |
30 | 31 | from test.test_sqlite3.test_dbapi import memory_database, managed_connect, cx_limit |
31 | 32 |
|
32 | 33 |
|
@@ -469,5 +470,43 @@ def test_executescript_step_through_select(self): |
469 | 470 | self.assertEqual(steps, values) |
470 | 471 |
|
471 | 472 |
|
| 473 | +class RecursiveUseOfCursors(unittest.TestCase): |
| 474 | + # GH-80254: sqlite3 should not segfault for recursive use of cursors. |
| 475 | + msg = "Recursive use of cursors not allowed" |
| 476 | + |
| 477 | + def setUp(self): |
| 478 | + self.con = sqlite.connect(":memory:", |
| 479 | + detect_types=sqlite.PARSE_COLNAMES) |
| 480 | + self.cur = self.con.cursor() |
| 481 | + self.cur.execute("create table test(x foo)") |
| 482 | + self.cur.executemany("insert into test(x) values (?)", |
| 483 | + [("foo",), ("bar",)]) |
| 484 | + |
| 485 | + def tearDown(self): |
| 486 | + self.cur.close() |
| 487 | + self.con.close() |
| 488 | + |
| 489 | + def test_recursive_cursor_init(self): |
| 490 | + conv = lambda x: self.cur.__init__(self.con) |
| 491 | + with patch.dict(sqlite.converters, {"INIT": conv}): |
| 492 | + self.cur.execute(f'select x as "x [INIT]", x from test') |
| 493 | + self.assertRaisesRegex(sqlite.ProgrammingError, self.msg, |
| 494 | + self.cur.fetchall) |
| 495 | + |
| 496 | + def test_recursive_cursor_close(self): |
| 497 | + conv = lambda x: self.cur.close() |
| 498 | + with patch.dict(sqlite.converters, {"CLOSE": conv}): |
| 499 | + self.cur.execute(f'select x as "x [CLOSE]", x from test') |
| 500 | + self.assertRaisesRegex(sqlite.ProgrammingError, self.msg, |
| 501 | + self.cur.fetchall) |
| 502 | + |
| 503 | + def test_recursive_cursor_iter(self): |
| 504 | + conv = lambda x, l=[]: self.cur.fetchone() if l else l.append(None) |
| 505 | + with patch.dict(sqlite.converters, {"ITER": conv}): |
| 506 | + self.cur.execute(f'select x as "x [ITER]", x from test') |
| 507 | + self.assertRaisesRegex(sqlite.ProgrammingError, self.msg, |
| 508 | + self.cur.fetchall) |
| 509 | + |
| 510 | + |
472 | 511 | if __name__ == "__main__": |
473 | 512 | unittest.main() |
0 commit comments