Fix: Avoid accessing face set with invalid index

When the PBVH is rebuilt, the `active_face_index` and
`active_grid_index` fields are initialized to -1. This results in a
possible segmentation fault if the `active_face_set_get` method is
called without these fields being populated.

This commit switches the raw `int` usage for `std::optional` to
better communicate the intent of these fields.

Pull Request: https://projects.blender.org/blender/blender/pulls/127959
This commit is contained in:
Sean Kim
2024-09-25 19:19:21 +02:00
committed by Sean Kim
parent 5cfe733f84
commit df251784cd
3 changed files with 18 additions and 12 deletions

View File

@@ -407,8 +407,8 @@ struct SculptSession : blender::NonCopyable, blender::NonMovable {
blender::ed::sculpt_paint::expand::Cache *expand_cache = nullptr;
/* Cursor data and active vertex for tools */
int active_face_index = -1;
int active_grid_index = -1;
std::optional<int> active_face_index;
std::optional<int> active_grid_index;
/* When active, the cursor draws with faded colors, indicating that there is an action
* enabled.

View File

@@ -203,20 +203,20 @@ int active_face_set_get(const Object &object)
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const bke::AttributeAccessor attributes = mesh.attributes();
const VArray face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
if (!face_sets) {
if (!face_sets || !ss.active_face_index) {
return SCULPT_FACE_SET_NONE;
}
return face_sets[ss.active_face_index];
return face_sets[*ss.active_face_index];
}
case bke::pbvh::Type::Grids: {
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
const bke::AttributeAccessor attributes = mesh.attributes();
const VArray face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
if (!face_sets) {
if (!face_sets || !ss.active_grid_index) {
return SCULPT_FACE_SET_NONE;
}
const int face_index = BKE_subdiv_ccg_grid_to_face_index(*ss.subdiv_ccg,
ss.active_grid_index);
*ss.active_grid_index);
return face_sets[face_index];
}
case bke::pbvh::Type::BMesh:
@@ -4645,15 +4645,15 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
switch (pbvh->type()) {
case bke::pbvh::Type::Mesh:
ss.active_face_index = srd.active_face_grid_index;
ss.active_grid_index = 0;
ss.active_grid_index = std::nullopt;
break;
case bke::pbvh::Type::Grids:
ss.active_face_index = 0;
ss.active_face_index = std::nullopt;
ss.active_grid_index = srd.active_face_grid_index;
break;
case bke::pbvh::Type::BMesh:
ss.active_face_index = 0;
ss.active_grid_index = 0;
ss.active_face_index = std::nullopt;
ss.active_grid_index = std::nullopt;
break;
}

View File

@@ -2273,10 +2273,16 @@ static int active_face_set_id_get(Object &object, Cache &expand_cache)
SculptSession &ss = *object.sculpt;
switch (bke::object::pbvh_get(object)->type()) {
case bke::pbvh::Type::Mesh:
return expand_cache.original_face_sets[ss.active_face_index];
if (!ss.active_face_index) {
return SCULPT_FACE_SET_NONE;
}
return expand_cache.original_face_sets[*ss.active_face_index];
case bke::pbvh::Type::Grids: {
if (!ss.active_grid_index) {
return SCULPT_FACE_SET_NONE;
}
const int face_index = BKE_subdiv_ccg_grid_to_face_index(*ss.subdiv_ccg,
ss.active_grid_index);
*ss.active_grid_index);
return expand_cache.original_face_sets[face_index];
}
case bke::pbvh::Type::BMesh: {