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:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user