diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-05-18 14:06:45 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-05-18 14:09:06 +0300 |
commit | 208462e424d319b3590d0b09cacf0b3807239972 (patch) | |
tree | e5c1ec37818cf16d0125ce0f590cfb0b198c83a2 /source/blender/bmesh/intern/bmesh_polygon_edgenet.c | |
parent | 102394a323bd3d6cfe5166380f6ab74c8c693024 (diff) |
Fix T51539: BMesh boolean crash
In some cases the vertex visit queue would exceed its max length,
visiting the same vertex multiple times.
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_polygon_edgenet.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_polygon_edgenet.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 0cd38f24165..64233151b04 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -512,13 +512,21 @@ bool BM_face_split_edgenet( } while ((l_iter = l_iter->next) != l_first); #endif + /* Note: 'VERT_VISIT' is often not needed at all, + * however in rare cases verts are added multiple times to the queue, + * that on it's own is harmless but in _very_ rare cases, + * the queue will overflow its maximum size, + * so we better be strict about this! see: T51539 */ for (i = 0; i < edge_net_len; i++) { BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT); } l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT); } while ((l_iter = l_iter->next) != l_first); float face_normal_matrix[3][3]; @@ -527,8 +535,10 @@ bool BM_face_split_edgenet( /* any vert can be used to begin with */ STACK_PUSH(vert_queue, l_first->v); + BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_VISIT); while ((v = STACK_POP(vert_queue))) { + BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT); if (bm_face_split_edgenet_find_loop( v, f->no, face_normal_matrix, edge_order, edge_order_len, face_verts, &face_verts_len)) @@ -558,8 +568,12 @@ bool BM_face_split_edgenet( * (verts between boundary and manifold edges) */ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { - if (bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) { + /* Avoid adding to queue multiple times (not common but happens). */ + if (BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_VISIT) && + bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) + { STACK_PUSH(vert_queue, l_iter->v); + BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT); } } while ((l_iter = l_iter->next) != l_first); } |