[Bf-blender-cvs] [376e4c9] master: Fix leak in BPy_BMElem_PySeq_As_Array

Campbell Barton noreply at git.blender.org
Wed Jul 29 02:54:33 CEST 2015


Commit: 376e4c945ee862bb7cd7d22d677a5e59b8eeeb36
Author: Campbell Barton
Date:   Wed Jul 29 09:55:34 2015 +1000
Branches: master
https://developer.blender.org/rB376e4c945ee862bb7cd7d22d677a5e59b8eeeb36

Fix leak in BPy_BMElem_PySeq_As_Array

Also add BPy_BMElem_PySeq_As_Array_FAST

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

M	source/blender/python/bmesh/bmesh_py_types.c
M	source/blender/python/bmesh/bmesh_py_types.h

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

diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index f63381d..1b23828 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 630afcb..e6f0976 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,




More information about the Bf-blender-cvs mailing list