From 92d72467a760663c5bf325bd2ef87b8f51ec2035 Mon Sep 17 00:00:00 2001 From: Falk David Date: Wed, 2 Jul 2025 17:16:50 +0200 Subject: [PATCH] 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 --- .../blenkernel/intern/curves_geometry.cc | 11 ++++++---- .../blender/blenkernel/intern/customdata.cc | 22 +++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 8ba626d04c0..7b23b1aff0b 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -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(); diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 29fe5df8856..75ee6ec0fcd 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -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();