From 9684cf69e32ae442c7be54521073ac78557f3bbf Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
 <31488909+miss-islington@users.noreply.github.com>
Date: Mon, 6 Nov 2017 16:44:23 -0800
Subject: bpo-31770: Prevent a crash and refleaks when calling
 sqlite3.Cursor.__init__() more than once (GH-3968) (#4301)

(cherry picked from commit e56ab746a965277ffcc4396d8a0902b6e072d049)
---
 Lib/sqlite3/test/regression.py                         | 18 ++++++++++++++++++
 .../Library/2017-10-12-18-45-38.bpo-31770.GV3MPx.rst   |  2 ++
 Modules/_sqlite/cursor.c                               | 15 +++++++--------
 3 files changed, 27 insertions(+), 8 deletions(-)
 create mode 100644 Misc/NEWS.d/next/Library/2017-10-12-18-45-38.bpo-31770.GV3MPx.rst

diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py
index 7dd0050..3ff9abd 100644
--- a/Lib/sqlite3/test/regression.py
+++ b/Lib/sqlite3/test/regression.py
@@ -24,6 +24,8 @@
 import datetime
 import unittest
 import sqlite3 as sqlite
+import weakref
+from test import support
 
 class RegressionTests(unittest.TestCase):
     def setUp(self):
@@ -376,6 +378,22 @@ class RegressionTests(unittest.TestCase):
                 counter += 1
         self.assertEqual(counter, 3, "should have returned exactly three rows")
 
+    def CheckBpo31770(self):
+        """
+        The interpreter shouldn't crash in case Cursor.__init__() is called
+        more than once.
+        """
+        def callback(*args):
+            pass
+        con = sqlite.connect(":memory:")
+        cur = sqlite.Cursor(con)
+        ref = weakref.ref(cur, callback)
+        cur.__init__(con)
+        del cur
+        # The interpreter shouldn't crash when ref is collected.
+        del ref
+        support.gc_collect()
+
 
 def suite():
     regression_suite = unittest.makeSuite(RegressionTests, "Check")
diff --git a/Misc/NEWS.d/next/Library/2017-10-12-18-45-38.bpo-31770.GV3MPx.rst b/Misc/NEWS.d/next/Library/2017-10-12-18-45-38.bpo-31770.GV3MPx.rst
new file mode 100644
index 0000000..86c7b80
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-10-12-18-45-38.bpo-31770.GV3MPx.rst
@@ -0,0 +1,2 @@
+Prevent a crash when calling the ``__init__()`` method of a
+``sqlite3.Cursor`` object more than once. Patch by Oren Milman.
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 8341fb8..b6257a0 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -39,21 +39,20 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
     }
 
     Py_INCREF(connection);
-    self->connection = connection;
-    self->statement = NULL;
-    self->next_row = NULL;
-    self->in_weakreflist = NULL;
+    Py_XSETREF(self->connection, connection);
+    Py_CLEAR(self->statement);
+    Py_CLEAR(self->next_row);
 
-    self->row_cast_map = PyList_New(0);
+    Py_XSETREF(self->row_cast_map, PyList_New(0));
     if (!self->row_cast_map) {
         return -1;
     }
 
     Py_INCREF(Py_None);
-    self->description = Py_None;
+    Py_XSETREF(self->description, Py_None);
 
     Py_INCREF(Py_None);
-    self->lastrowid= Py_None;
+    Py_XSETREF(self->lastrowid, Py_None);
 
     self->arraysize = 1;
     self->closed = 0;
@@ -62,7 +61,7 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
     self->rowcount = -1L;
 
     Py_INCREF(Py_None);
-    self->row_factory = Py_None;
+    Py_XSETREF(self->row_factory, Py_None);
 
     if (!pysqlite_check_thread(self->connection)) {
         return -1;
-- 
cgit v0.12