Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked
cursor type.
diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py
index 0813a13..f4b8428 100644
--- a/Lib/sqlite3/test/factory.py
+++ b/Lib/sqlite3/test/factory.py
@@ -170,6 +170,14 @@
         self.assertEqual(list(reversed(row)), list(reversed(as_tuple)))
         self.assertIsInstance(row, Sequence)
 
+    def CheckFakeCursorClass(self):
+        # Issue #24257: Incorrect use of PyObject_IsInstance() caused
+        # segmentation fault.
+        class FakeCursor(str):
+            __class__ = sqlite.Cursor
+        cur = self.con.cursor(factory=FakeCursor)
+        self.assertRaises(TypeError, sqlite.Row, cur, ())
+
     def tearDown(self):
         self.con.close()
 
diff --git a/Misc/NEWS b/Misc/NEWS
index cdcaff2..65943de 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,9 @@
 Library
 -------
 
+- Issue #24257: Fixed segmentation fault in sqlite3.Row constructor with faked
+  cursor type.
+
 - Issue #22107: tempfile.gettempdir() and tempfile.mkdtemp() now try again
   when a directory with the chosen name already exists on Windows as well as
   on Unix.  tempfile.mkstemp() now fails early if parent directory is not
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c
index 02373f0..9ebe7b7 100644
--- a/Modules/_sqlite/row.c
+++ b/Modules/_sqlite/row.c
@@ -47,7 +47,7 @@
     if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
         return NULL;
 
-    if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) {
+    if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) {
         PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
         return NULL;
     }