Fix #114177: Crash in extrude mesh vertex mode with unsupported data
Unsupported data can be removed, which reallocated the custom data layer array. Since the temporary ID vectors referenced memory in that array directly, this could lead to a use-after-free. Instead remove unsupported data before collecting the referenced attribute IDs.
This commit is contained in:
@@ -108,6 +108,35 @@ static void remove_non_propagated_attributes(
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_unsupported_vert_data(Mesh &mesh)
|
||||
{
|
||||
CustomData_free_layers(&mesh.vert_data, CD_ORCO, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_SHAPEKEY, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_CLOTH_ORCO, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_MVERT_SKIN, mesh.totvert);
|
||||
}
|
||||
|
||||
static void remove_unsupported_edge_data(Mesh &mesh)
|
||||
{
|
||||
CustomData_free_layers(&mesh.edge_data, CD_FREESTYLE_EDGE, mesh.totedge);
|
||||
}
|
||||
|
||||
static void remove_unsupported_face_data(Mesh &mesh)
|
||||
{
|
||||
CustomData_free_layers(&mesh.face_data, CD_FREESTYLE_FACE, mesh.faces_num);
|
||||
}
|
||||
|
||||
static void remove_unsupported_corner_data(Mesh &mesh)
|
||||
{
|
||||
CustomData_free_layers(&mesh.loop_data, CD_NORMAL, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_MDISPS, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_TANGENT, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_PAINT_MASK, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_MLOOPTANGENT, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_GRID_PAINT_MASK, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_CUSTOMLOOPNORMAL, mesh.totloop);
|
||||
}
|
||||
|
||||
static void expand_mesh(Mesh &mesh,
|
||||
const int vert_expand,
|
||||
const int edge_expand,
|
||||
@@ -116,10 +145,6 @@ static void expand_mesh(Mesh &mesh,
|
||||
{
|
||||
/* Remove types that aren't supported for interpolation in this node. */
|
||||
if (vert_expand != 0) {
|
||||
CustomData_free_layers(&mesh.vert_data, CD_ORCO, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_SHAPEKEY, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_CLOTH_ORCO, mesh.totvert);
|
||||
CustomData_free_layers(&mesh.vert_data, CD_MVERT_SKIN, mesh.totvert);
|
||||
const int old_verts_num = mesh.totvert;
|
||||
mesh.totvert += vert_expand;
|
||||
CustomData_realloc(&mesh.vert_data, old_verts_num, mesh.totvert);
|
||||
@@ -129,13 +154,11 @@ static void expand_mesh(Mesh &mesh,
|
||||
mesh.attributes_for_write().add(
|
||||
".edge_verts", ATTR_DOMAIN_EDGE, CD_PROP_INT32_2D, bke::AttributeInitConstruct());
|
||||
}
|
||||
CustomData_free_layers(&mesh.edge_data, CD_FREESTYLE_EDGE, mesh.totedge);
|
||||
const int old_edges_num = mesh.totedge;
|
||||
mesh.totedge += edge_expand;
|
||||
CustomData_realloc(&mesh.edge_data, old_edges_num, mesh.totedge);
|
||||
}
|
||||
if (face_expand != 0) {
|
||||
CustomData_free_layers(&mesh.face_data, CD_FREESTYLE_FACE, mesh.faces_num);
|
||||
const int old_faces_num = mesh.faces_num;
|
||||
mesh.faces_num += face_expand;
|
||||
CustomData_realloc(&mesh.face_data, old_faces_num, mesh.faces_num);
|
||||
@@ -148,13 +171,6 @@ static void expand_mesh(Mesh &mesh,
|
||||
mesh.face_offset_indices[mesh.faces_num] = mesh.totloop + loop_expand;
|
||||
}
|
||||
if (loop_expand != 0) {
|
||||
CustomData_free_layers(&mesh.loop_data, CD_NORMAL, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_MDISPS, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_TANGENT, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_PAINT_MASK, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_MLOOPTANGENT, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_GRID_PAINT_MASK, mesh.totloop);
|
||||
CustomData_free_layers(&mesh.loop_data, CD_CUSTOMLOOPNORMAL, mesh.totloop);
|
||||
const int old_loops_num = mesh.totloop;
|
||||
mesh.totloop += loop_expand;
|
||||
CustomData_realloc(&mesh.loop_data, old_loops_num, mesh.totloop);
|
||||
@@ -254,8 +270,14 @@ static void extrude_mesh_vertices(Mesh &mesh,
|
||||
evaluator.set_selection(selection_field);
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
if (selection.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||
remove_non_propagated_attributes(attributes, propagation_info);
|
||||
remove_unsupported_vert_data(mesh);
|
||||
remove_unsupported_edge_data(mesh);
|
||||
|
||||
Set<AttributeIDRef> point_ids;
|
||||
Set<AttributeIDRef> edge_ids;
|
||||
@@ -292,8 +314,6 @@ static void extrude_mesh_vertices(Mesh &mesh,
|
||||
new_edges[i_selection] = int2(index, new_vert_range[i_selection]);
|
||||
});
|
||||
|
||||
MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||
|
||||
/* New vertices copy the attribute values from their source vertex. */
|
||||
for (const AttributeIDRef &id : point_ids) {
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
@@ -475,6 +495,10 @@ static void extrude_mesh_edges(Mesh &mesh,
|
||||
const IndexRange new_loop_range{orig_loop_size, new_face_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
remove_unsupported_vert_data(mesh);
|
||||
remove_unsupported_edge_data(mesh);
|
||||
remove_unsupported_face_data(mesh);
|
||||
remove_unsupported_corner_data(mesh);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + duplicate_edge_range.size(),
|
||||
@@ -831,6 +855,10 @@ static void extrude_mesh_face_regions(Mesh &mesh,
|
||||
const IndexRange side_loop_range{orig_corner_verts.size(), side_face_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
remove_unsupported_vert_data(mesh);
|
||||
remove_unsupported_edge_data(mesh);
|
||||
remove_unsupported_face_data(mesh);
|
||||
remove_unsupported_corner_data(mesh);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + boundary_edge_range.size() + new_inner_edge_range.size(),
|
||||
@@ -1155,6 +1183,10 @@ static void extrude_individual_mesh_faces(
|
||||
const IndexRange side_loop_range{orig_loop_size, side_face_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
remove_unsupported_vert_data(mesh);
|
||||
remove_unsupported_edge_data(mesh);
|
||||
remove_unsupported_face_data(mesh);
|
||||
remove_unsupported_corner_data(mesh);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + duplicate_edge_range.size(),
|
||||
|
||||
Reference in New Issue
Block a user