Fix #104690: Evaluated positions user-after-free for copied poly curves
The evaluated positions cache can live longer than a specific `CurvesGeometry`, but for only-poly curves, it pointed to the positions, which are freed when the curves are. Instead, use the same pattern as the evaluated offsets and don't store the positions span, just return it when retrieving evaluated positions.
This commit is contained in:
@@ -71,16 +71,11 @@ class CurvesGeometryRuntime {
|
||||
|
||||
mutable SharedCache<Vector<curves::nurbs::BasisCache>> nurbs_basis_cache;
|
||||
|
||||
/** Cache of evaluated positions. */
|
||||
struct EvaluatedPositions {
|
||||
Vector<float3> vector;
|
||||
/**
|
||||
* The evaluated positions result, using a separate span in case all curves are poly curves,
|
||||
* in which case a separate array of evaluated positions is unnecessary.
|
||||
*/
|
||||
Span<float3> span;
|
||||
};
|
||||
mutable SharedCache<EvaluatedPositions> evaluated_position_cache;
|
||||
/**
|
||||
* Cache of evaluated positions for all curves. The positions span will
|
||||
* be used directly rather than the cache when all curves are poly type.
|
||||
*/
|
||||
mutable SharedCache<Vector<float3>> evaluated_position_cache;
|
||||
|
||||
/**
|
||||
* A cache of bounds shared between data-blocks with unchanged positions and radii.
|
||||
|
||||
@@ -605,17 +605,15 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
|
||||
Span<float3> CurvesGeometry::evaluated_positions() const
|
||||
{
|
||||
const bke::CurvesGeometryRuntime &runtime = *this->runtime;
|
||||
if (this->is_single_type(CURVE_TYPE_POLY)) {
|
||||
runtime.evaluated_position_cache.ensure(
|
||||
[&](Vector<float3> &r_data) { r_data.clear_and_shrink(); });
|
||||
return this->positions();
|
||||
}
|
||||
this->ensure_nurbs_basis_cache();
|
||||
runtime.evaluated_position_cache.ensure([&](CurvesGeometryRuntime::EvaluatedPositions &r_data) {
|
||||
if (this->is_single_type(CURVE_TYPE_POLY)) {
|
||||
r_data.span = this->positions();
|
||||
r_data.vector.clear_and_shrink();
|
||||
return;
|
||||
}
|
||||
|
||||
r_data.vector.resize(this->evaluated_points_num());
|
||||
r_data.span = r_data.vector;
|
||||
MutableSpan<float3> evaluated_positions = r_data.vector;
|
||||
runtime.evaluated_position_cache.ensure([&](Vector<float3> &r_data) {
|
||||
r_data.resize(this->evaluated_points_num());
|
||||
MutableSpan<float3> evaluated_positions = r_data;
|
||||
|
||||
const OffsetIndices<int> points_by_curve = this->points_by_curve();
|
||||
const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
|
||||
@@ -672,7 +670,7 @@ Span<float3> CurvesGeometry::evaluated_positions() const
|
||||
}
|
||||
});
|
||||
});
|
||||
return runtime.evaluated_position_cache.data().span;
|
||||
return runtime.evaluated_position_cache.data();
|
||||
}
|
||||
|
||||
Span<float3> CurvesGeometry::evaluated_tangents() const
|
||||
@@ -781,6 +779,7 @@ static void evaluate_generic_data_for_curve(
|
||||
Span<float3> CurvesGeometry::evaluated_normals() const
|
||||
{
|
||||
const bke::CurvesGeometryRuntime &runtime = *this->runtime;
|
||||
this->ensure_nurbs_basis_cache();
|
||||
runtime.evaluated_normal_cache.ensure([&](Vector<float3> &r_data) {
|
||||
const OffsetIndices<int> points_by_curve = this->points_by_curve();
|
||||
const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
|
||||
|
||||
Reference in New Issue
Block a user