[Bf-blender-cvs] [3f973791fbf] blender-v2.83-release: Fix T88190: Freed memory use when iterating over id-properties

Campbell Barton noreply at git.blender.org
Fri May 21 08:14:29 CEST 2021


Commit: 3f973791fbf4f05147723903075ce8b6c960c0c6
Author: Campbell Barton
Date:   Tue May 11 12:08:26 2021 +1000
Branches: blender-v2.83-release
https://developer.blender.org/rB3f973791fbf4f05147723903075ce8b6c960c0c6

Fix T88190: Freed memory use when iterating over id-properties

The id-property iterator referenced a PyObject pointer without
increasing it's user count - allowing for errors if the value
goes out of scope during iteration.

===================================================================

M	source/blender/python/generic/idprop_py_api.c

===================================================================

diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index a183de6623f..bd86df80e52 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -760,10 +760,12 @@ static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject
 
 static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self)
 {
-  BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
+  BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
   iter->group = self;
+  Py_INCREF(self);
   iter->mode = IDPROP_ITER_KEYS;
   iter->cur = self->prop->data.group.first;
+  PyObject_GC_Track(iter);
   return (PyObject *)iter;
 }
 
@@ -932,10 +934,12 @@ PyDoc_STRVAR(
     "   Iterate through the items in the dict; behaves like dictionary method iteritems.\n");
 static PyObject *BPy_IDGroup_iter_items(BPy_IDProperty *self)
 {
-  BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
+  BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
   iter->group = self;
+  Py_INCREF(self);
   iter->mode = IDPROP_ITER_ITEMS;
   iter->cur = self->prop->data.group.first;
+  PyObject_GC_Track(iter);
   return (PyObject *)iter;
 }
 
@@ -1690,6 +1694,25 @@ static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
   return PyUnicode_FromFormat("(ID Property Group Iter \"%s\")", self->group->prop->name);
 }
 
+static void BPy_IDGroup_Iter_dealloc(BPy_IDGroup_Iter *self)
+{
+  PyObject_GC_UnTrack(self);
+  Py_CLEAR(self->group);
+  PyObject_GC_Del(self);
+}
+
+static int BPy_IDGroup_Iter_traverse(BPy_IDGroup_Iter *self, visitproc visit, void *arg)
+{
+  Py_VISIT(self->group);
+  return 0;
+}
+
+static int BPy_IDGroup_Iter_clear(BPy_IDGroup_Iter *self)
+{
+  Py_CLEAR(self->group);
+  return 0;
+}
+
 static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
 {
 
@@ -1726,12 +1749,12 @@ PyTypeObject BPy_IDGroup_Iter_Type = {
 
     /* Methods to implement standard operations */
 
-    NULL,                        /* destructor tp_dealloc; */
-    (printfunc)NULL,             /* printfunc tp_print; */
-    NULL,                        /* getattrfunc tp_getattr; */
-    NULL,                        /* setattrfunc tp_setattr; */
-    NULL,                        /* cmpfunc tp_compare; */
-    (reprfunc)IDGroup_Iter_repr, /* reprfunc tp_repr; */
+    (destructor)BPy_IDGroup_Iter_dealloc, /* tp_dealloc */
+    (printfunc)NULL,                      /* printfunc tp_print; */
+    NULL,                                 /* getattrfunc tp_getattr; */
+    NULL,                                 /* setattrfunc tp_setattr; */
+    NULL,                                 /* cmpfunc tp_compare; */
+    (reprfunc)IDGroup_Iter_repr,          /* reprfunc tp_repr; */
 
     /* Method suites for standard classes */
 
@@ -1751,15 +1774,15 @@ PyTypeObject BPy_IDGroup_Iter_Type = {
     NULL, /* PyBufferProcs *tp_as_buffer; */
 
     /*** Flags to define presence of optional/expanded features ***/
-    Py_TPFLAGS_DEFAULT, /* long tp_flags; */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */
 
     NULL, /*  char *tp_doc;  Documentation string */
     /*** Assigned meaning in release 2.0 ***/
     /* call function for all accessible objects */
-    NULL, /* traverseproc tp_traverse; */
+    (traverseproc)BPy_IDGroup_Iter_traverse, /* traverseproc tp_traverse; */
 
     /* delete references to contained objects */
-    NULL, /* inquiry tp_clear; */
+    (inquiry)BPy_IDGroup_Iter_clear, /* inquiry tp_clear; */
 
     /***  Assigned meaning in release 2.1 ***/
     /*** rich comparisons ***/



More information about the Bf-blender-cvs mailing list