fix [#33792] Accessing a bmesh object created by from_object crashes blender
authorCampbell Barton <ideasman42@gmail.com>
Tue, 8 Jan 2013 14:25:17 +0000 (14:25 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 8 Jan 2013 14:25:17 +0000 (14:25 +0000)
Issue was customdata wasnt being initialized for layers in the destination BMesh but not in the source data.

source/blender/blenkernel/BKE_customdata.h
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/modifiers_bmesh.c
source/blender/bmesh/intern/bmesh_mesh_conv.c

index 4736e7b7312657970753264637874f35dc44dd14..70532384643672d6cfa6f8788007b4a51b0c91fa 100644 (file)
@@ -39,6 +39,7 @@ extern "C" {
 #endif
 
 #include "../blenloader/BLO_sys_types.h" /* XXX, should have a more generic include for this */
+#include "BLI_utildefines.h"
 
 struct BMesh;
 struct ID;
@@ -304,7 +305,7 @@ void CustomData_bmesh_free_block(struct CustomData *data, void **block);
 /* copy custom data to/from layers as in mesh/derivedmesh, to editmesh
  * blocks of data. the CustomData's must not be compatible */
 void CustomData_to_bmesh_block(const struct CustomData *source, 
-                               struct CustomData *dest, int src_index, void **dest_block);
+                               struct CustomData *dest, int src_index, void **dest_block, bool use_default_init);
 void CustomData_from_bmesh_block(const struct CustomData *source, 
                                  struct CustomData *dest, void *src_block, int dest_index);
 
index 832c1979a51820d14d8c6de46b9538fca443d4fa..19624e8a2b94b263d5432ae696109e4b7118f088 100644 (file)
@@ -2660,27 +2660,40 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *w
        if (count > SOURCE_BUF_SIZE) MEM_freeN(sources);
 }
 
-void CustomData_bmesh_set_default(CustomData *data, void **block)
+static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
 {
        const LayerTypeInfo *typeInfo;
+       int offset = data->layers[n].offset;
+
+       typeInfo = layerType_getInfo(data->layers[n].type);
+
+       if (typeInfo->set_default) {
+               typeInfo->set_default((char *)*block + offset, 1);
+       }
+       else {
+               memset((char *)*block + offset, 0, typeInfo->size);
+       }
+}
+
+void CustomData_bmesh_set_default(CustomData *data, void **block)
+{
        int i;
 
        if (*block == NULL)
                CustomData_bmesh_alloc_block(data, block);
 
        for (i = 0; i < data->totlayer; ++i) {
-               int offset = data->layers[i].offset;
-
-               typeInfo = layerType_getInfo(data->layers[i].type);
-
-               if (typeInfo->set_default)
-                       typeInfo->set_default((char *)*block + offset, 1);
-               else memset((char *)*block + offset, 0, typeInfo->size);
+               CustomData_bmesh_set_default_n(data, block, i);
        }
 }
 
+/**
+ * \param use_default_init initializes data which can't be copied,
+ * typically you'll want to use this if the BM_xxx create function
+ * is called with BM_CREATE_SKIP_CD flag
+ */
 void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
-                               int src_index, void **dest_block)
+                               int src_index, void **dest_block, bool use_default_init)
 {
        const LayerTypeInfo *typeInfo;
        int dest_i, src_i, src_offset;
@@ -2696,11 +2709,14 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
                 * (this should work because layers are ordered by type)
                 */
                while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
+                       if (use_default_init) {
+                               CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
+                       }
                        dest_i++;
                }
 
                /* if there are no more dest layers, we're done */
-               if (dest_i >= dest->totlayer) return;
+               if (dest_i >= dest->totlayer) break;
 
                /* if we found a matching layer, copy the data */
                if (dest->layers[dest_i].type == source->layers[src_i].type) {
@@ -2723,6 +2739,13 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
                        dest_i++;
                }
        }
+
+       if (use_default_init) {
+               while (dest_i < dest->totlayer) {
+                       CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
+                       dest_i++;
+               }
+       }
 }
 
 void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
index 9b5cf443bcf580b7e51454aa5860c2a1343d5b46..3939c45a436936b4ba11bb8c9807e942bc462aaf 100644 (file)
@@ -96,7 +96,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
                v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
                BM_elem_index_set(v, i); /* set_inline */
 
-               CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
+               CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data, true);
                vtable[i] = v;
 
                /* add bevel weight */
@@ -118,7 +118,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
                e->head.hflag = BM_edge_flag_from_mflag(me->flag);
                BM_elem_index_set(e, i); /* set_inline */
 
-               CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data);
+               CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data, true);
                etable[i] = e;
 
                /* add crease */
@@ -168,10 +168,10 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
                l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
 
                for (k = mp->loopstart; l; l = BM_iter_step(&liter), k++) {
-                       CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data);
+                       CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data, true);
                }
 
-               CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data);
+               CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data, true);
 
                if (face_normals) {
                        copy_v3_v3(f->no, face_normals[i]);
index 388d148377a3967a9d53b697ed41c5ed5d14fbfd..53b29a4ce7491461b47e8875f88480ef80b4c95d 100644 (file)
@@ -221,7 +221,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
                normal_short_to_float_v3(v->no, mvert->no);
 
                /* Copy Custom Data */
-               CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+               CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
 
                BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f);
 
@@ -267,7 +267,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
                }
 
                /* Copy Custom Data */
-               CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
+               CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);
 
                BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (float)medge->crease / 255.0f);
                BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (float)medge->bweight / 255.0f);
@@ -338,11 +338,11 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
                j = 0;
                BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) {
                        /* Save index of correspsonding MLoop */
-                       CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data);
+                       CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data, true);
                }
 
                /* Copy Custom Data */
-               CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
+               CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);
        }
 
        bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */