Fix #136608: ASAN crash when texture painting
**Problem** When using Sculpt Texture Paint to paint objects in a debug build, Blender will crash due to an Address Sanitizer exception, `stack-use-after-free`. This makes development for Sculpt Texture Paint harder since the feature can't be used in debug builds without turning off Address Sanitizer. Code-wise, the issue here happens when extending UV island borders. When creating and adding UV primitives to extend the UV border, the primitives are allocated locally and then added to a list. This means that when these primitives are accessed later from the list, the ASAN error is triggered since the primitives have been freed. Freed primitives are generally accessed when checking if a primitive has already been added to the primitive list belonging to its connected UV Edges. **Solution** The solution here is to change UV Edges to store the index of a UV primitive, and not use a pointer to the object itself. This is the best solution since it makes it fast and simple to check if an UV Edge already has a reference to its connected primitives, while still allowing access to the primitive objects since primitives can be accessed using indexes from mesh data objects. Co-authored-by: T0MIS0N <50230774+T0MIS0N@users.noreply.github.com> Pull Request: https://projects.blender.org/blender/blender/pulls/137032
This commit is contained in:
@@ -27,7 +27,7 @@ static void uv_edge_append_to_uv_vertices(UVEdge &uv_edge)
|
||||
static void uv_primitive_append_to_uv_edges(UVPrimitive &uv_primitive)
|
||||
{
|
||||
for (UVEdge *uv_edge : uv_primitive.edges) {
|
||||
uv_edge->uv_primitives.append_non_duplicates(&uv_primitive);
|
||||
uv_edge->uv_primitive_indices.append_non_duplicates(uv_primitive.primitive_i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +247,8 @@ static Vector<int> connecting_mesh_primitive_indices(const UVVertex &uv_vertex)
|
||||
{
|
||||
Vector<int> primitives_around_uv_vertex;
|
||||
for (const UVEdge *uv_edge : uv_vertex.uv_edges) {
|
||||
for (const UVPrimitive *uv_primitive : uv_edge->uv_primitives) {
|
||||
primitives_around_uv_vertex.append_non_duplicates(uv_primitive->primitive_i);
|
||||
for (const int uv_primitive_index : uv_edge->uv_primitive_indices) {
|
||||
primitives_around_uv_vertex.append_non_duplicates(uv_primitive_index);
|
||||
}
|
||||
}
|
||||
return primitives_around_uv_vertex;
|
||||
@@ -296,7 +296,7 @@ bool UVEdge::has_same_vertices(const int2 &edge) const
|
||||
|
||||
bool UVEdge::is_border_edge() const
|
||||
{
|
||||
return uv_primitives.size() == 1;
|
||||
return uv_primitive_indices.size() == 1;
|
||||
}
|
||||
|
||||
UVVertex *UVEdge::get_other_uv_vertex(const int vertex)
|
||||
@@ -365,7 +365,7 @@ UVEdge *UVIsland::lookup_or_create(const UVEdge &edge)
|
||||
|
||||
uv_edges.append(edge);
|
||||
UVEdge *result = &uv_edges.last();
|
||||
result->uv_primitives.clear();
|
||||
result->uv_primitive_indices.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ void UVIsland::append(const UVPrimitive &primitive)
|
||||
uv_edge_template.vertices[1] = lookup_or_create(*other_edge->vertices[1]);
|
||||
new_prim_ptr->edges[i] = lookup_or_create(uv_edge_template);
|
||||
uv_edge_append_to_uv_vertices(*new_prim_ptr->edges[i]);
|
||||
new_prim_ptr->edges[i]->uv_primitives.append(new_prim_ptr);
|
||||
new_prim_ptr->edges[i]->uv_primitive_indices.append(new_prim_ptr->primitive_i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ static UVPrimitive *add_primitive(const MeshData &mesh_data,
|
||||
UVEdge *uv_edge = uv_island.lookup_or_create(uv_edge_template);
|
||||
uv_primitive_ptr->edges.append(uv_edge);
|
||||
uv_edge_append_to_uv_vertices(*uv_edge);
|
||||
uv_edge->uv_primitives.append(uv_primitive_ptr);
|
||||
uv_edge->uv_primitive_indices.append(uv_primitive_ptr->primitive_i);
|
||||
}
|
||||
return uv_primitive_ptr;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ struct UVVertex {
|
||||
|
||||
struct UVEdge {
|
||||
std::array<UVVertex *, 2> vertices;
|
||||
Vector<UVPrimitive *, 2> uv_primitives;
|
||||
Vector<int, 2> uv_primitive_indices;
|
||||
|
||||
UVVertex *get_other_uv_vertex(const int vertex_index);
|
||||
bool has_shared_edge(Span<float2> uv_map, const int loop_1, const int loop_2) const;
|
||||
|
||||
Reference in New Issue
Block a user