26
26
#include "util.h"
27
27
#include "clinic/cursor.c.h"
28
28
29
+ static inline int
30
+ check_cursor_locked (pysqlite_Cursor * cur )
31
+ {
32
+ if (cur -> locked ) {
33
+ PyErr_SetString (pysqlite_ProgrammingError ,
34
+ "Recursive use of cursors not allowed." );
35
+ return 0 ;
36
+ }
37
+ return 1 ;
38
+ }
39
+
29
40
/*[clinic input]
30
41
module _sqlite3
31
42
class _sqlite3.Cursor "pysqlite_Cursor *" "pysqlite_CursorType"
@@ -47,6 +58,10 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
47
58
pysqlite_Connection * connection )
48
59
/*[clinic end generated code: output=ac59dce49a809ca8 input=a8a4f75ac90999b2]*/
49
60
{
61
+ if (!check_cursor_locked (self )) {
62
+ return -1 ;
63
+ }
64
+
50
65
Py_INCREF (connection );
51
66
Py_XSETREF (self -> connection , connection );
52
67
Py_CLEAR (self -> statement );
@@ -407,12 +422,9 @@ static int check_cursor(pysqlite_Cursor* cur)
407
422
return 0 ;
408
423
}
409
424
410
- if (cur -> locked ) {
411
- PyErr_SetString (pysqlite_ProgrammingError , "Recursive use of cursors not allowed." );
412
- return 0 ;
413
- }
414
-
415
- return pysqlite_check_thread (cur -> connection ) && pysqlite_check_connection (cur -> connection );
425
+ return (pysqlite_check_thread (cur -> connection )
426
+ && pysqlite_check_connection (cur -> connection )
427
+ && check_cursor_locked (cur ));
416
428
}
417
429
418
430
static PyObject *
@@ -810,27 +822,29 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
810
822
if (self -> statement ) {
811
823
rc = pysqlite_step (self -> statement -> st , self -> connection );
812
824
if (PyErr_Occurred ()) {
813
- (void )pysqlite_statement_reset (self -> statement );
814
- Py_DECREF (next_row );
815
- return NULL ;
825
+ goto error ;
816
826
}
817
827
if (rc != SQLITE_DONE && rc != SQLITE_ROW ) {
818
- (void )pysqlite_statement_reset (self -> statement );
819
- Py_DECREF (next_row );
820
828
_pysqlite_seterror (self -> connection -> db , NULL );
821
- return NULL ;
829
+ goto error ;
822
830
}
823
831
824
832
if (rc == SQLITE_ROW ) {
833
+ self -> locked = 1 ; // GH-80254: Prevent recursive use of cursors.
825
834
self -> next_row = _pysqlite_fetch_one_row (self );
835
+ self -> locked = 0 ;
826
836
if (self -> next_row == NULL ) {
827
- (void )pysqlite_statement_reset (self -> statement );
828
- return NULL ;
837
+ goto error ;
829
838
}
830
839
}
831
840
}
832
841
833
842
return next_row ;
843
+
844
+ error :
845
+ (void )pysqlite_statement_reset (self -> statement );
846
+ Py_DECREF (next_row );
847
+ return NULL ;
834
848
}
835
849
836
850
/*[clinic input]
@@ -973,6 +987,10 @@ static PyObject *
973
987
pysqlite_cursor_close_impl (pysqlite_Cursor * self )
974
988
/*[clinic end generated code: output=b6055e4ec6fe63b6 input=08b36552dbb9a986]*/
975
989
{
990
+ if (!check_cursor_locked (self )) {
991
+ return NULL ;
992
+ }
993
+
976
994
if (!self -> connection ) {
977
995
PyErr_SetString (pysqlite_ProgrammingError ,
978
996
"Base Cursor.__init__ not called." );
0 commit comments