]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-99886: Fix crash when freeing objects with managed dictionaries (#99902)
authorKen Jin <kenjin@python.org>
Sun, 4 Dec 2022 06:41:23 +0000 (14:41 +0800)
committerGitHub <noreply@github.com>
Sun, 4 Dec 2022 06:41:23 +0000 (14:41 +0800)
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
Lib/test/test_sqlite3/test_regression.py
Misc/NEWS.d/next/Core and Builtins/2022-11-30-15-29-08.gh-issue-99886.feJkSv.rst [new file with mode: 0644]
Objects/dictobject.c

index 0b727cecb0e8cb8a9ae0f3aa2ce1f0ce292583b8..9a07e02ae1197e2a8cf8a816c4b103fbf7b1de4b 100644 (file)
@@ -469,6 +469,18 @@ class RegressionTests(unittest.TestCase):
             con.executescript("select step(t) from t")
             self.assertEqual(steps, values)
 
+    def test_custom_cursor_object_crash_gh_99886(self):
+        # This test segfaults on GH-99886
+        class MyCursor(sqlite.Cursor):
+            def __init__(self, *args, **kwargs):
+                super().__init__(*args, **kwargs)
+                # this can go before or after the super call; doesn't matter
+                self.some_attr = None
+
+        with memory_database() as con:
+            cur = con.cursor(MyCursor)
+            cur.close()
+            del cur
 
 class RecursiveUseOfCursors(unittest.TestCase):
     # GH-80254: sqlite3 should not segfault for recursive use of cursors.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-30-15-29-08.gh-issue-99886.feJkSv.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-30-15-29-08.gh-issue-99886.feJkSv.rst
new file mode 100644 (file)
index 0000000..8bdaa94
--- /dev/null
@@ -0,0 +1 @@
+Fix a crash when an object which does not have a dictionary frees its instance values.
index ebbd22ee7c145ead02dd50741df1e5ce1908d348..4a214f8cf5b751e46d55373c42921f56dc9911d3 100644 (file)
@@ -5573,14 +5573,16 @@ _PyObject_FreeInstanceAttributes(PyObject *self)
     PyTypeObject *tp = Py_TYPE(self);
     assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
     PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
-    if (*values_ptr == NULL) {
+    PyDictValues *values = *values_ptr;
+    if (values == NULL) {
         return;
     }
+    *values_ptr = NULL;
     PyDictKeysObject *keys = CACHED_KEYS(tp);
     for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
-        Py_XDECREF((*values_ptr)->values[i]);
+        Py_XDECREF(values->values[i]);
     }
-    free_values(*values_ptr);
+    free_values(values);
 }
 
 PyObject *