From d503f2ac33b1c990400b219e5e2cc668dec4034f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 1 Nov 2023 10:55:37 +0100 Subject: [PATCH] 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. --- .../geometry/nodes/node_geo_extrude_mesh.cc | 64 ++++++++++++++----- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index ca861f09e4e..e6709ce5870 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -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 point_ids; Set 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(),