diff options
author | Bastien Montagne <bastien@blender.org> | 2020-05-13 19:42:10 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-05-13 19:47:44 +0300 |
commit | 2b5e301ea4612c576a5934d1e1a79d5452f6792a (patch) | |
tree | 749f2ef8168d7436f91177108c08e286e7aa677d /source/blender/editors/mesh/editmesh_tools.c | |
parent | c7f74863dde1a417e2742d3dadb4f5fd8bfc36af (diff) |
Fix T75574: Instant crash: averaging custom normals on model.
Fairly critical code mistake actually, since it uses malloca,
BLI_smallstack should *never* be declared inside a loop...
Also optimized handling of the `loop_weight` heapsimple, we can also
only create and use a single one for all edited objects...
Found two other operators potentially affected by same issue (split
normals, and weld edges into faces).
Diffstat (limited to 'source/blender/editors/mesh/editmesh_tools.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 1d724d0b9a7..5c7c95b59d7 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -8312,6 +8312,8 @@ static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr) BM_normals_loops_edges_tag(bm, false); for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + BLI_assert(BLI_SMALLSTACK_IS_EMPTY(clnors)); + if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) { continue; } @@ -8354,8 +8356,12 @@ static void normals_split(BMesh *bm) BM_normals_loops_edges_tag(bm, true); + BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *); + const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack)); + l_curr = l_first = BM_FACE_FIRST_LOOP(f); do { if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) && @@ -8377,7 +8383,6 @@ static void normals_split(BMesh *bm) lfan_pivot = l_curr; e_next = lfan_pivot->e; - BLI_SMALLSTACK_DECLARE(loops, BMLoop *); float avg_normal[3] = {0.0f}; while (true) { @@ -8389,7 +8394,7 @@ static void normals_split(BMesh *bm) e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e; } - BLI_SMALLSTACK_PUSH(loops, lfan_pivot); + BLI_SMALLSTACK_PUSH(loop_stack, lfan_pivot); add_v3_v3(avg_normal, lfan_pivot->f->no); if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) { @@ -8401,7 +8406,7 @@ static void normals_split(BMesh *bm) /* If avg normal is nearly 0, set clnor to default value. */ zero_v3(avg_normal); } - while ((l = BLI_SMALLSTACK_POP(loops))) { + while ((l = BLI_SMALLSTACK_POP(loop_stack))) { const int l_index = BM_elem_index_get(l); short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset); BKE_lnor_space_custom_normal_to_data( @@ -8543,7 +8548,13 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) const float absweight = (float)RNA_int_get(op->ptr, "weight"); const float threshold = RNA_float_get(op->ptr, "threshold"); + HeapSimple *loop_weight = BLI_heapsimple_new(); + BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack)); + BLI_assert(BLI_heapsimple_is_empty(loop_weight)); + Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; @@ -8570,8 +8581,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) BM_normals_loops_edges_tag(bm, true); - HeapSimple *loop_weight = BLI_heapsimple_new(); - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { l_curr = l_first = BM_FACE_FIRST_LOOP(f); do { @@ -8621,7 +8630,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) lfan_pivot = lfan_pivot_next; } - BLI_SMALLSTACK_DECLARE(loops, BMLoop *); float wnor[3], avg_normal[3] = {0.0f}, count = 0; float val = BLI_heapsimple_top_value(loop_weight); @@ -8632,7 +8640,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) val = cur_val; } l = BLI_heapsimple_pop_min(loop_weight); - BLI_SMALLSTACK_PUSH(loops, l); + BLI_SMALLSTACK_PUSH(loop_stack, l); const float n_weight = pow(weight, count); @@ -8653,7 +8661,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) /* If avg normal is nearly 0, set clnor to default value. */ zero_v3(avg_normal); } - while ((l = BLI_SMALLSTACK_POP(loops))) { + while ((l = BLI_SMALLSTACK_POP(loop_stack))) { const int l_index = BM_elem_index_get(l); short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset); BKE_lnor_space_custom_normal_to_data( @@ -8664,10 +8672,11 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) } while ((l_curr = l_curr->next) != l_first); } - BLI_heapsimple_free(loop_weight, NULL); EDBM_update_generic(obedit->data, true, false); } + BLI_heapsimple_free(loop_weight, NULL); + MEM_freeN(objects); return OPERATOR_FINISHED; } |