Commit: 6e5eb46d733959195c0a9716358253f75974599a
Author: Jacques Lucke
Date:   Wed Jul 27 18:20:22 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rB6e5eb46d733959195c0a9716358253f75974599a

Fix T100026: crash with zero-sized attributes

The problem was that zero-sized and non-existant attributes were
handled the same in some parts of the attribute API, which led to
unexpected behavior.

The solution is to properly differentiate the case when an attribute
does not exist and when it is just empty (because the geometry
is empty).

Differential Revision: https://developer.blender.org/D15557

===================================================================

M       source/blender/blenkernel/intern/attribute_access.cc

===================================================================

diff --git a/source/blender/blenkernel/intern/attribute_access.cc 
b/source/blender/blenkernel/intern/attribute_access.cc
index 8d21c6fe792..1af3cde1821 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -214,36 +214,33 @@ static bool 
add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
                                                       const int domain_num,
                                                       const AttributeInit 
&initializer)
 {
+  const int old_layer_num = custom_data.totlayer;
   switch (initializer.type) {
     case AttributeInit::Type::Default: {
-      void *data = add_generic_custom_data_layer(
+      add_generic_custom_data_layer(
           custom_data, data_type, CD_DEFAULT, nullptr, domain_num, 
attribute_id);
-      return data != nullptr;
+      break;
     }
     case AttributeInit::Type::VArray: {
       void *data = add_generic_custom_data_layer(
           custom_data, data_type, CD_DEFAULT, nullptr, domain_num, 
attribute_id);
-      if (data == nullptr) {
-        return false;
+      if (data != nullptr) {
+        const GVArray &varray = static_cast<const AttributeInitVArray 
&>(initializer).varray;
+        varray.materialize_to_uninitialized(varray.index_range(), data);
       }
-      const GVArray &varray = static_cast<const AttributeInitVArray 
&>(initializer).varray;
-      varray.materialize_to_uninitialized(varray.index_range(), data);
-      return true;
+      break;
     }
     case AttributeInit::Type::MoveArray: {
       void *source_data = static_cast<const AttributeInitMove 
&>(initializer).data;
       void *data = add_generic_custom_data_layer(
           custom_data, data_type, CD_ASSIGN, source_data, domain_num, 
attribute_id);
-      if (data == nullptr) {
+      if (source_data != nullptr && data == nullptr) {
         MEM_freeN(source_data);
-        return false;
       }
-      return true;
+      break;
     }
   }
-
-  BLI_assert_unreachable();
-  return false;
+  return old_layer_num < custom_data.totlayer;
 }
 
 static bool custom_data_layer_matches_attribute_id(const CustomDataLayer 
&layer,
@@ -265,17 +262,25 @@ GVArray 
BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) cons
     return {};
   }
 
-  const void *data;
-  if (stored_as_named_attribute_) {
-    data = CustomData_get_layer_named(custom_data, stored_type_, 
name_.c_str());
-  }
-  else {
-    data = CustomData_get_layer(custom_data, stored_type_);
+  const void *data = nullptr;
+  bool found_attribute = false;
+  for (const CustomDataLayer &layer : Span(custom_data->layers, 
custom_data->totlayer)) {
+    if (stored_as_named_attribute_) {
+      if (layer.name == name_) {
+        data = layer.data;
+        found_attribute = true;
+        break;
+      }
+    }
+    else if (layer.type == stored_type_) {
+      data = layer.data;
+      found_attribute = true;
+      break;
+    }
   }
-  if (data == nullptr) {
+  if (!found_attribute) {
     return {};
   }
-
   const int element_num = custom_data_access_.get_element_num(owner);
   return as_read_attribute_(data, element_num);
 }
@@ -291,31 +296,42 @@ GAttributeWriter 
BuiltinCustomDataLayerProvider::try_get_for_write(void *owner)
   }
   const int element_num = custom_data_access_.get_element_num(owner);
 
-  void *data;
-  if (stored_as_named_attribute_) {
-    data = CustomData_get_layer_named(custom_data, stored_type_, 
name_.c_str());
-  }
-  else {
-    data = CustomData_get_layer(custom_data, stored_type_);
+  void *data = nullptr;
+  bool found_attribute = false;
+  for (const CustomDataLayer &layer : Span(custom_data->layers, 
custom_data->totlayer)) {
+    if (stored_as_named_attribute_) {
+      if (layer.name == name_) {
+        data = layer.data;
+        found_attribute = true;
+        break;
+      }
+    }
+    else if (layer.type == stored_type_) {
+      data = layer.data;
+      found_attribute = true;
+      break;
+    }
   }
-  if (data == nullptr) {
+  if (!found_attribute) {
     return {};
   }
 
-  void *new_data;
-  if (stored_as_named_attribute_) {
-    new_data = CustomData_duplicate_referenced_layer_named(
-        custom_data, stored_type_, name_.c_str(), element_num);
-  }
-  else {
-    new_data = CustomData_duplicate_referenced_layer(custom_data, 
stored_type_, element_num);
-  }
+  if (data != nullptr) {
+    void *new_data;
+    if (stored_as_named_attribute_) {
+      new_data = CustomData_duplicate_referenced_layer_named(
+          custom_data, stored_type_, name_.c_str(), element_num);
+    }
+    else {
+      new_data = CustomData_duplicate_referenced_layer(custom_data, 
stored_type_, element_num);
+    }
 
-  if (data != new_data) {
-    if (custom_data_access_.update_custom_data_pointers) {
-      custom_data_access_.update_custom_data_pointers(owner);
+    if (data != new_data) {
+      if (custom_data_access_.update_custom_data_pointers) {
+        custom_data_access_.update_custom_data_pointers(owner);
+      }
+      data = new_data;
     }
-    data = new_data;
   }
 
   std::function<void()> tag_modified_fn;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to