Fix #141887: Crash/assert hit after reading Grease Pencil

Since 5.0 (subversion 33) `CurvesGeometry` data is read from and written
to the new attribute storage. See 68759af516.

For backwards compatibility, the `CustomData curve_data`
became `curve_data_legacy` and was only read and then converted in
the versioning code to the attribute storage format.

But since `CurvesGeometry::blend_read` is still reading
`curve_data_legacy`, we need to ensure that this data is valid.

When e.g. duplicating `CurvesGeometry`, the `curve_data_legacy` was left
uninitialized, so in an invalid state. Then the writing code would write
the embedded `CustomData` struct and the reading code would fail.

This could in theory also happen for other IDs that store legacy
custom data.

To ensure that the data is valid when reading, we do the following:
1) After the conversion code ran, we reset the legacy data. This makes
sure that we don't keep the legacy data around at runtime and
potentially when writing the embedded struct.
2) Before writing, we also reset the legacy data. This makes sure that
in case there is some garbage data in the unused struct (e.g. from
copying the ID), we don't write the garbage to file.

Pull Request: https://projects.blender.org/blender/blender/pulls/142327
This commit is contained in:
Falk David
2025-07-18 17:55:36 +02:00
committed by Falk David
parent e34f5a1d99
commit 11d2f48882
4 changed files with 9 additions and 1 deletions

View File

@@ -276,6 +276,7 @@ void curves_convert_customdata_to_storage(CurvesGeometry &curves)
{{AttrDomain::Point, {curves.point_data, curves.points_num()}},
{AttrDomain::Curve, {curves.curve_data_legacy, curves.curves_num()}}},
curves.attribute_storage.wrap());
CustomData_reset(&curves.curve_data_legacy);
/* Update the curve type count again (the first time was done on file-read, where
* #AttributeStorage data doesn't exist yet for older files). */
curves.update_curve_types();
@@ -286,6 +287,7 @@ void pointcloud_convert_customdata_to_storage(PointCloud &pointcloud)
attribute_legacy_convert_customdata_to_storage(
{{AttrDomain::Point, {pointcloud.pdata_legacy, pointcloud.totpoint}}},
pointcloud.attribute_storage.wrap());
CustomData_reset(&pointcloud.pdata_legacy);
}
void grease_pencil_convert_customdata_to_storage(GreasePencil &grease_pencil)
@@ -294,6 +296,7 @@ void grease_pencil_convert_customdata_to_storage(GreasePencil &grease_pencil)
{{AttrDomain::Layer,
{grease_pencil.layers_data_legacy, int(grease_pencil.layers().size())}}},
grease_pencil.attribute_storage.wrap());
CustomData_reset(&grease_pencil.layers_data_legacy);
}
} // namespace blender::bke

View File

@@ -1916,6 +1916,7 @@ CurvesGeometry::BlendWriteData::BlendWriteData(ResourceScope &scope)
void CurvesGeometry::blend_write_prepare(CurvesGeometry::BlendWriteData &write_data)
{
CustomData_reset(&this->curve_data_legacy);
attribute_storage_blend_write_prepare(this->attribute_storage.wrap(), write_data.attribute_data);
CustomData_blend_write_prepare(this->point_data,
AttrDomain::Point,

View File

@@ -288,6 +288,8 @@ static void grease_pencil_blend_write(BlendWriter *writer, ID *id, const void *i
grease_pencil->attribute_storage.dna_attributes = attribute_data.attributes.data();
grease_pencil->attribute_storage.dna_attributes_num = attribute_data.attributes.size();
CustomData_reset(&grease_pencil->layers_data_legacy);
/* Write LibData */
BLO_write_id_struct(writer, GreasePencil, id_address, &grease_pencil->id);
BKE_id_blend_write(writer, &grease_pencil->id);

View File

@@ -121,7 +121,7 @@ static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_a
ResourceScope scope;
bke::AttributeStorage::BlendWriteData attribute_data{scope};
attribute_storage_blend_write_prepare(pointcloud->attribute_storage.wrap(), attribute_data);
BLI_assert(pointcloud->pdata_legacy.totlayer == 0);
if (attribute_data.attributes.is_empty()) {
pointcloud->attribute_storage.dna_attributes = nullptr;
pointcloud->attribute_storage.dna_attributes_num = 0;
@@ -131,6 +131,8 @@ static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_a
pointcloud->attribute_storage.dna_attributes_num = attribute_data.attributes.size();
}
CustomData_reset(&pointcloud->pdata_legacy);
/* Write LibData */
BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id);
BKE_id_blend_write(writer, &pointcloud->id);