From 376e4c945ee862bb7cd7d22d677a5e59b8eeeb36 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Jul 2015 09:55:34 +1000 Subject: Fix leak in BPy_BMElem_PySeq_As_Array Also add BPy_BMElem_PySeq_As_Array_FAST --- source/blender/python/bmesh/bmesh_py_types.c | 152 +++++++++++++++------------ source/blender/python/bmesh/bmesh_py_types.h | 5 + 2 files changed, 88 insertions(+), 69 deletions(-) (limited to 'source') diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index f63381d7a7d..1b2382831b1 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3759,106 +3759,120 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self) * * The 'bm_r' value is assigned when empty, and used when set. */ -void *BPy_BMElem_PySeq_As_Array( - BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, +void *BPy_BMElem_PySeq_As_Array_FAST( + BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, const bool do_unique_check, const bool do_bm_check, const char *error_prefix) { BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL; - PyObject *seq_fast; + const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast); + Py_ssize_t i; + + BPy_BMElem *item; + BMElem **alloc; + *r_size = 0; - if (!(seq_fast = PySequence_Fast(seq, error_prefix))) { + if (seq_len < min || seq_len > max) { + PyErr_Format(PyExc_TypeError, + "%s: sequence incorrect size, expected [%d - %d], given %d", + error_prefix, min, max, seq_len); return NULL; } - else { - Py_ssize_t seq_len; - Py_ssize_t i; - BPy_BMElem *item; - BMElem **alloc; + /* from now on, use goto */ + alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **)); - seq_len = PySequence_Fast_GET_SIZE(seq_fast); + for (i = 0; i < seq_len; i++) { + item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i); - if (seq_len < min || seq_len > max) { + if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) { PyErr_Format(PyExc_TypeError, - "%s: sequence incorrect size, expected [%d - %d], given %d", - error_prefix, min, max, seq_len); - return NULL; + "%s: expected %.200s, not '%.200s'", + error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name); + goto err_cleanup; + } + else if (!BPY_BM_IS_VALID(item)) { + PyErr_Format(PyExc_TypeError, + "%s: %d %s has been removed", + error_prefix, i, Py_TYPE(item)->tp_name); + goto err_cleanup; + } + /* trick so we can ensure all items have the same mesh, + * and allows us to pass the 'bm' as NULL. */ + else if (do_bm_check && (bm && bm != item->bm)) { + PyErr_Format(PyExc_ValueError, + "%s: %d %s is from another mesh", + error_prefix, i, BPy_BMElem_StringFromHType(htype)); + goto err_cleanup; } + if (bm == NULL) { + bm = item->bm; + } - /* from now on, use goto */ - alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **)); - - for (i = 0; i < seq_len; i++) { - item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i); + alloc[i] = item->ele; - if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) { - PyErr_Format(PyExc_TypeError, - "%s: expected %.200s, not '%.200s'", - error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name); - goto err_cleanup; - } - else if (!BPY_BM_IS_VALID(item)) { - PyErr_Format(PyExc_TypeError, - "%s: %d %s has been removed", - error_prefix, i, Py_TYPE(item)->tp_name); - goto err_cleanup; - } - /* trick so we can ensure all items have the same mesh, - * and allows us to pass the 'bm' as NULL. */ - else if (do_bm_check && (bm && bm != item->bm)) { - PyErr_Format(PyExc_ValueError, - "%s: %d %s is from another mesh", - error_prefix, i, BPy_BMElem_StringFromHType(htype)); - goto err_cleanup; - } + if (do_unique_check) { + BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG); + } + } - if (bm == NULL) { - bm = item->bm; + if (do_unique_check) { + /* check for double verts! */ + bool ok = true; + for (i = 0; i < seq_len; i++) { + if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) { + ok = false; } - alloc[i] = item->ele; + /* ensure we don't leave this enabled */ + BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG); + } - if (do_unique_check) { - BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG); - } + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "%s: found the same %.200s used multiple times", + error_prefix, BPy_BMElem_StringFromHType(htype)); + goto err_cleanup; } + } - if (do_unique_check) { - /* check for double verts! */ - bool ok = true; - for (i = 0; i < seq_len; i++) { - if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) { - ok = false; - } + *r_size = seq_len; + if (r_bm) *r_bm = bm; + return alloc; - /* ensure we don't leave this enabled */ - BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG); - } +err_cleanup: + PyMem_FREE(alloc); + return NULL; - if (ok == false) { - PyErr_Format(PyExc_ValueError, - "%s: found the same %.200s used multiple times", - error_prefix, BPy_BMElem_StringFromHType(htype)); - goto err_cleanup; - } - } +} - Py_DECREF(seq_fast); - *r_size = seq_len; - if (r_bm) *r_bm = bm; - return alloc; +void *BPy_BMElem_PySeq_As_Array( + BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix) +{ + PyObject *seq_fast; + PyObject *ret; -err_cleanup: - Py_DECREF(seq_fast); - PyMem_FREE(alloc); + if (!(seq_fast = PySequence_Fast(seq, error_prefix))) { return NULL; } + + ret = BPy_BMElem_PySeq_As_Array_FAST( + r_bm, seq_fast, min, max, r_size, + htype, + do_unique_check, do_bm_check, + error_prefix); + + Py_DECREF(seq_fast); + return ret; } + PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len) { Py_ssize_t i; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 630afcb32c0..e6f0976965c 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -158,6 +158,11 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm); PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */ +void *BPy_BMElem_PySeq_As_Array_FAST( + BMesh **r_bm, PyObject *seq_fast, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix); void *BPy_BMElem_PySeq_As_Array( BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, -- cgit v1.2.3