fix for crash dissolving faces, bmesh walkers were using freed mempool elements.
use a convention for freeing walker-states where freed-dangling pointers aren't left assigned to prevent errors like this happening in future.
This commit is contained in:
@@ -26,6 +26,8 @@
|
|||||||
* BMesh Walker Code.
|
* BMesh Walker Code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "BKE_customdata.h"
|
#include "BKE_customdata.h"
|
||||||
@@ -34,6 +36,12 @@
|
|||||||
#include "intern/bmesh_private.h"
|
#include "intern/bmesh_private.h"
|
||||||
#include "intern/bmesh_walkers_private.h"
|
#include "intern/bmesh_walkers_private.h"
|
||||||
|
|
||||||
|
/* pop into stack memory (common operation) */
|
||||||
|
#define BMW_state_remove_r(walker, owalk) { \
|
||||||
|
memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
|
||||||
|
BMW_state_remove(walker); \
|
||||||
|
} (void)0
|
||||||
|
|
||||||
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
|
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
|
||||||
{
|
{
|
||||||
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
|
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
|
||||||
@@ -140,14 +148,16 @@ static void *bmw_ShellWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_ShellWalker_step(BMWalker *walker)
|
static void *bmw_ShellWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwShellWalker *swalk = BMW_current_state(walker);
|
BMwShellWalker *swalk, owalk;
|
||||||
BMEdge *e, *e2;
|
BMEdge *e, *e2;
|
||||||
BMVert *v;
|
BMVert *v;
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
swalk = &owalk;
|
||||||
|
|
||||||
e = swalk->curedge;
|
e = swalk->curedge;
|
||||||
BMW_state_remove(walker);
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
v = i ? e->v2 : e->v1;
|
v = i ? e->v2 : e->v1;
|
||||||
@@ -240,14 +250,15 @@ static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
|
static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwConnectedVertexWalker *vwalk = BMW_current_state(walker);
|
BMwConnectedVertexWalker *vwalk, owalk;
|
||||||
BMVert *v, *v2;
|
BMVert *v, *v2;
|
||||||
BMEdge *e;
|
BMEdge *e;
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
|
|
||||||
v = vwalk->curvert;
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
vwalk = &owalk;
|
||||||
|
|
||||||
BMW_state_remove(walker);
|
v = vwalk->curvert;
|
||||||
|
|
||||||
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
|
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
|
||||||
v2 = BM_edge_other_vert(e, v);
|
v2 = BM_edge_other_vert(e, v);
|
||||||
@@ -289,14 +300,19 @@ static void *bmw_IslandboundWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_IslandboundWalker_step(BMWalker *walker)
|
static void *bmw_IslandboundWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwIslandboundWalker *iwalk = BMW_current_state(walker), owalk;
|
BMwIslandboundWalker *iwalk, owalk;
|
||||||
BMVert *v;
|
BMVert *v;
|
||||||
BMEdge *e = iwalk->curloop->e;
|
BMEdge *e;
|
||||||
BMFace *f;
|
BMFace *f;
|
||||||
BMLoop *l = iwalk->curloop;
|
BMLoop *l;
|
||||||
/* int found = 0; */
|
/* int found = 0; */
|
||||||
|
|
||||||
owalk = *iwalk;
|
memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
|
||||||
|
/* normally we'd remove here, but delay until after error checking */
|
||||||
|
iwalk = &owalk;
|
||||||
|
|
||||||
|
l = iwalk->curloop;
|
||||||
|
e = l->e;
|
||||||
|
|
||||||
v = BM_edge_other_vert(e, iwalk->lastv);
|
v = BM_edge_other_vert(e, iwalk->lastv);
|
||||||
|
|
||||||
@@ -307,7 +323,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pop off current stat */
|
/* pop off current state */
|
||||||
BMW_state_remove(walker);
|
BMW_state_remove(walker);
|
||||||
|
|
||||||
f = l->f;
|
f = l->f;
|
||||||
@@ -381,13 +397,13 @@ static void *bmw_IslandWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_IslandWalker_step(BMWalker *walker)
|
static void *bmw_IslandWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwIslandWalker *iwalk = BMW_current_state(walker);
|
BMwIslandWalker *iwalk, owalk;
|
||||||
/* BMwIslandWalker *owalk = iwalk; */ /* UNUSED */
|
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
BMFace *f, *curf = iwalk->cur;
|
BMFace *f;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
|
|
||||||
BMW_state_remove(walker);
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
iwalk = &owalk;
|
||||||
|
|
||||||
l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
|
l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
|
||||||
for ( ; l; l = BM_iter_step(&liter)) {
|
for ( ; l; l = BM_iter_step(&liter)) {
|
||||||
@@ -419,7 +435,7 @@ static void *bmw_IslandWalker_step(BMWalker *walker)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return curf;
|
return owalk.cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -507,15 +523,16 @@ static void *bmw_LoopWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_LoopWalker_step(BMWalker *walker)
|
static void *bmw_LoopWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwLoopWalker *lwalk = BMW_current_state(walker), owalk;
|
BMwLoopWalker *lwalk, owalk;
|
||||||
BMEdge *e = lwalk->cur, *nexte = NULL;
|
BMEdge *e, *nexte = NULL;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMVert *v;
|
BMVert *v;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
owalk = *lwalk;
|
BMW_state_remove_r(walker, &owalk);
|
||||||
BMW_state_remove(walker);
|
lwalk = &owalk;
|
||||||
|
|
||||||
|
e = lwalk->cur;
|
||||||
l = e->l;
|
l = e->l;
|
||||||
|
|
||||||
if (owalk.f_hub) { /* NGON EDGE */
|
if (owalk.f_hub) { /* NGON EDGE */
|
||||||
@@ -770,13 +787,15 @@ static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_FaceLoopWalker_step(BMWalker *walker)
|
static void *bmw_FaceLoopWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
|
BMwFaceLoopWalker *lwalk, owalk;
|
||||||
BMFace *f = lwalk->l->f;
|
BMFace *f;
|
||||||
BMLoop *l = lwalk->l, *origl = lwalk->l;
|
BMLoop *l;
|
||||||
|
|
||||||
BMW_state_remove(walker);
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
lwalk = &owalk;
|
||||||
|
|
||||||
l = l->radial_next;
|
f = lwalk->l->f;
|
||||||
|
l = lwalk->l->radial_next;
|
||||||
|
|
||||||
if (lwalk->no_calc) {
|
if (lwalk->no_calc) {
|
||||||
return f;
|
return f;
|
||||||
@@ -797,7 +816,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
|
|||||||
|
|
||||||
if (l->f->len != 4) {
|
if (l->f->len != 4) {
|
||||||
lwalk->no_calc = true;
|
lwalk->no_calc = true;
|
||||||
lwalk->l = origl;
|
lwalk->l = owalk.l;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lwalk->no_calc = false;
|
lwalk->no_calc = false;
|
||||||
@@ -878,19 +897,21 @@ static void *bmw_EdgeringWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_EdgeringWalker_step(BMWalker *walker)
|
static void *bmw_EdgeringWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwEdgeringWalker *lwalk = BMW_current_state(walker);
|
BMwEdgeringWalker *lwalk, owalk;
|
||||||
BMEdge *e, *wireedge = lwalk->wireedge;
|
BMEdge *e;
|
||||||
BMLoop *l = lwalk->l, *origl = lwalk->l;
|
BMLoop *l;
|
||||||
#ifdef BMW_EDGERING_NGON
|
#ifdef BMW_EDGERING_NGON
|
||||||
int i, len;
|
int i, len;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
|
#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
|
||||||
|
|
||||||
BMW_state_remove(walker);
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
lwalk = &owalk;
|
||||||
|
|
||||||
|
l = lwalk->l;
|
||||||
if (!l)
|
if (!l)
|
||||||
return wireedge;
|
return lwalk->wireedge;
|
||||||
|
|
||||||
e = l->e;
|
e = l->e;
|
||||||
if (!EDGE_CHECK(e)) {
|
if (!EDGE_CHECK(e)) {
|
||||||
@@ -913,7 +934,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
|
|||||||
if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) ||
|
if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) ||
|
||||||
!bmw_mask_check_face(walker, l->f))
|
!bmw_mask_check_face(walker, l->f))
|
||||||
{
|
{
|
||||||
l = origl;
|
l = owalk.l;
|
||||||
i = len;
|
i = len;
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
l = l->next;
|
l = l->next;
|
||||||
@@ -930,7 +951,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
|
|||||||
l = l->next->next;
|
l = l->next->next;
|
||||||
|
|
||||||
if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
|
if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
|
||||||
l = origl->next->next;
|
l = owalk.l->next->next;
|
||||||
}
|
}
|
||||||
/* only walk to manifold edge */
|
/* only walk to manifold edge */
|
||||||
if ((l->f->len == 4) && EDGE_CHECK(l->e) &&
|
if ((l->f->len == 4) && EDGE_CHECK(l->e) &&
|
||||||
@@ -975,17 +996,18 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
|
|||||||
|
|
||||||
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
|
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
|
||||||
{
|
{
|
||||||
BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
|
const int type = walker->bm->ldata.layers[walker->layer].type;
|
||||||
|
BMwUVEdgeWalker *lwalk, owalk;
|
||||||
BMLoop *l, *l2, *l3, *nl, *cl;
|
BMLoop *l, *l2, *l3, *nl, *cl;
|
||||||
BMIter liter;
|
BMIter liter;
|
||||||
void *d1, *d2;
|
void *d1, *d2;
|
||||||
int i, j, rlen, type;
|
int i, j, rlen;
|
||||||
|
|
||||||
|
BMW_state_remove_r(walker, &owalk);
|
||||||
|
lwalk = &owalk;
|
||||||
|
|
||||||
l = lwalk->l;
|
l = lwalk->l;
|
||||||
nl = l->next;
|
nl = l->next;
|
||||||
type = walker->bm->ldata.layers[walker->layer].type;
|
|
||||||
|
|
||||||
BMW_state_remove(walker);
|
|
||||||
|
|
||||||
if (!bmw_mask_check_edge(walker, l->e)) {
|
if (!bmw_mask_check_edge(walker, l->e)) {
|
||||||
return l;
|
return l;
|
||||||
|
Reference in New Issue
Block a user