Fix: Various issues with attribute removal
There were logic errors and use-after-free errors with the attribute removal function. Because the custom data layers are reallocated, we can't reuse the name pointer after removing an attribute. And we can't return early on the first domain to fail for the edit mode implementation, because another domain might have the attribute. Also reorganize some of the code to make the logic clearer: only remove sub-attribuutes and change attribute names after actually removing the attribute,and assert if the attribute isn't removed after it is found.
This commit is contained in:
parent
f4416e36b9
commit
f23e3c7f04
|
@ -411,26 +411,24 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
if (BMEditMesh *em = mesh->edit_mesh) {
|
||||
for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
|
||||
if (CustomData *data = info[domain].customdata) {
|
||||
int layer_index = CustomData_get_named_layer_index_notype(data, name);
|
||||
if (layer_index >= 0) {
|
||||
if (data->layers[layer_index].type == CD_PROP_FLOAT2) {
|
||||
/* free associated UV map bool layers */
|
||||
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
BM_data_layer_free_named(
|
||||
em->bm, data, BKE_uv_map_vert_select_name_get(name, buffer_src));
|
||||
BM_data_layer_free_named(
|
||||
em->bm, data, BKE_uv_map_edge_select_name_get(name, buffer_src));
|
||||
BM_data_layer_free_named(em->bm, data, BKE_uv_map_pin_name_get(name, buffer_src));
|
||||
}
|
||||
const std::string name_copy = name;
|
||||
const int layer_index = CustomData_get_named_layer_index_notype(data, name_copy.c_str());
|
||||
if (layer_index == -1) {
|
||||
continue;
|
||||
}
|
||||
/* Update active and default color attributes. */
|
||||
const bool is_active_color_attribute = name == StringRef(mesh->active_color_attribute);
|
||||
const bool is_default_color_attribute = name == StringRef(mesh->default_color_attribute);
|
||||
|
||||
const eCustomDataType type = eCustomDataType(data->layers[layer_index].type);
|
||||
const bool is_active_color_attribute = name_copy.c_str() ==
|
||||
StringRef(mesh->active_color_attribute);
|
||||
const bool is_default_color_attribute = name_copy.c_str() ==
|
||||
StringRef(mesh->default_color_attribute);
|
||||
const int active_index = color_name_to_index(id, mesh->active_color_attribute);
|
||||
const int default_index = color_name_to_index(id, mesh->default_color_attribute);
|
||||
if (!BM_data_layer_free_named(em->bm, data, name)) {
|
||||
return false;
|
||||
|
||||
if (!BM_data_layer_free_named(em->bm, data, name_copy.c_str())) {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
if (is_active_color_attribute) {
|
||||
BKE_id_attributes_active_color_set(
|
||||
id, color_name_from_index(id, color_clamp_index(id, active_index)));
|
||||
|
@ -439,6 +437,17 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
BKE_id_attributes_default_color_set(
|
||||
id, color_name_from_index(id, color_clamp_index(id, default_index)));
|
||||
}
|
||||
|
||||
if (type == CD_PROP_FLOAT2) {
|
||||
/* free associated UV map bool layers */
|
||||
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
BM_data_layer_free_named(
|
||||
em->bm, data, BKE_uv_map_vert_select_name_get(name_copy.c_str(), buffer));
|
||||
BM_data_layer_free_named(
|
||||
em->bm, data, BKE_uv_map_edge_select_name_get(name_copy.c_str(), buffer));
|
||||
BM_data_layer_free_named(
|
||||
em->bm, data, BKE_uv_map_pin_name_get(name_copy.c_str(), buffer));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -453,23 +462,23 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
}
|
||||
|
||||
if (GS(id->name) == ID_ME) {
|
||||
std::optional<blender::bke::AttributeMetaData> metadata = attributes->lookup_meta_data(name);
|
||||
if (metadata->data_type == CD_PROP_FLOAT2) {
|
||||
/* remove UV sub-attributes. */
|
||||
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
BKE_id_attribute_remove(id, BKE_uv_map_vert_select_name_get(name, buffer_src), reports);
|
||||
BKE_id_attribute_remove(id, BKE_uv_map_edge_select_name_get(name, buffer_src), reports);
|
||||
BKE_id_attribute_remove(id, BKE_uv_map_pin_name_get(name, buffer_src), reports);
|
||||
const std::string name_copy = name;
|
||||
std::optional<blender::bke::AttributeMetaData> metadata = attributes->lookup_meta_data(
|
||||
name_copy);
|
||||
if (!metadata) {
|
||||
return false;
|
||||
}
|
||||
/* Update active and default color attributes. */
|
||||
Mesh *mesh = reinterpret_cast<Mesh *>(id);
|
||||
const bool is_active_color_attribute = name == StringRef(mesh->active_color_attribute);
|
||||
const bool is_default_color_attribute = name == StringRef(mesh->default_color_attribute);
|
||||
const bool is_active_color_attribute = name_copy == StringRef(mesh->active_color_attribute);
|
||||
const bool is_default_color_attribute = name_copy == StringRef(mesh->default_color_attribute);
|
||||
const int active_index = color_name_to_index(id, mesh->active_color_attribute);
|
||||
const int default_index = color_name_to_index(id, mesh->default_color_attribute);
|
||||
if (!attributes->remove(name)) {
|
||||
return false;
|
||||
|
||||
if (!attributes->remove(name_copy)) {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
if (is_active_color_attribute) {
|
||||
BKE_id_attributes_active_color_set(
|
||||
id, color_name_from_index(id, color_clamp_index(id, active_index)));
|
||||
|
@ -478,6 +487,15 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
BKE_id_attributes_default_color_set(
|
||||
id, color_name_from_index(id, color_clamp_index(id, default_index)));
|
||||
}
|
||||
if (metadata->data_type == CD_PROP_FLOAT2) {
|
||||
/* remove UV sub-attributes. */
|
||||
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
BKE_id_attribute_remove(
|
||||
id, BKE_uv_map_vert_select_name_get(name_copy.c_str(), buffer), reports);
|
||||
BKE_id_attribute_remove(
|
||||
id, BKE_uv_map_edge_select_name_get(name_copy.c_str(), buffer), reports);
|
||||
BKE_id_attribute_remove(id, BKE_uv_map_pin_name_get(name_copy.c_str(), buffer), reports);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue