diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-05-11 05:08:26 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2021-05-21 09:12:15 +0300 |
commit | 3f973791fbf4f05147723903075ce8b6c960c0c6 (patch) | |
tree | e4716a3a40c9399ccd5da54f6bd29bd63d9a50b7 | |
parent | 1555809480304b0790f22512b363619d302ec007 (diff) |
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.
-rw-r--r-- | source/blender/python/generic/idprop_py_api.c | 45 |
1 files changed, 34 insertions, 11 deletions
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 ***/ |