Fix #141222: Assert hit when resizing CurvesGeometry to 0

The `CurvesGeometry::resize` function would not work properly when
passing a new size of zero.
1) The `CustomData_realloc` would allocate an array with zero size.
2) A new size of 1 is passed to `implicit_sharing::resize_trivial_array`
   for the curve offsets when it should pass 0.
3) A value is written out-of-bounds to `curve_offsets`

This fixes the issues in the following ways:
1) `CustomData_realloc` now doesn't allocate any data when the new
    size is 0 and sets the `layer->data` to `nullptr`.
2) When the new number of curves is 0, resize the `curve_offsets` to 0
  not to 1. This also ensures that the data pointer is `nullptr`.
3) Make sure to only write the first and last curve offset when the
  number of curves is greater than 0.

Pull Request: https://projects.blender.org/blender/blender/pulls/141333
This commit is contained in:
Falk David
2025-07-02 17:16:50 +02:00
committed by Falk David
parent 37a8e5c06a
commit 92d72467a7
2 changed files with 20 additions and 13 deletions

View File

@@ -1170,6 +1170,7 @@ void CurvesGeometry::ensure_can_interpolate_to_evaluated() const
void CurvesGeometry::resize(const int points_num, const int curves_num)
{
BLI_assert(curves_num >= 0 && points_num >= 0);
if (points_num != this->point_num) {
CustomData_realloc(&this->point_data, this->points_num(), points_num);
this->point_num = points_num;
@@ -1179,10 +1180,12 @@ void CurvesGeometry::resize(const int points_num, const int curves_num)
implicit_sharing::resize_trivial_array(&this->curve_offsets,
&this->runtime->curve_offsets_sharing_info,
this->curve_num == 0 ? 0 : (this->curve_num + 1),
curves_num + 1);
/* Set common values for convenience. */
this->curve_offsets[0] = 0;
this->curve_offsets[curves_num] = this->point_num;
curves_num == 0 ? 0 : (curves_num + 1));
if (curves_num > 0) {
/* Set common values for convenience. */
this->curve_offsets[0] = 0;
this->curve_offsets[curves_num] = this->point_num;
}
this->curve_num = curves_num;
}
this->tag_topology_changed();

View File

@@ -2604,15 +2604,19 @@ void CustomData_realloc(CustomData *data,
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
void *new_layer_data = MEM_mallocN_aligned(new_size_in_bytes, typeInfo->alignment, __func__);
/* Copy data to new array. */
if (old_size_in_bytes) {
if (typeInfo->copy) {
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
}
else {
BLI_assert(layer->data != nullptr);
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
void *new_layer_data = (new_size > 0) ? MEM_mallocN_aligned(
new_size_in_bytes, typeInfo->alignment, __func__) :
nullptr;
if (old_size_in_bytes > 0) {
if (new_layer_data != nullptr) {
/* Copy data to new array. */
if (typeInfo->copy) {
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
}
else {
BLI_assert(layer->data != nullptr);
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
}
}
BLI_assert(layer->sharing_info != nullptr);
layer->sharing_info->remove_user_and_delete_if_last();