From b3a4decda677012b8f7cfea39b7741d707c82693 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Wed, 2 Aug 2023 19:18:13 -0500 Subject: [PATCH] Assert against infinite values of control points in CatmullRomSpline (#131820) When providing infinite values for the control points of CatmullRomSpline, a StackOverflowError occurs. This asserts against that and provides a helpful error message. Fixes https://github.com/flutter/flutter/issues/131246 --- .../flutter/lib/src/animation/curves.dart | 21 ++++++++++ .../flutter/test/animation/curves_test.dart | 40 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/packages/flutter/lib/src/animation/curves.dart b/packages/flutter/lib/src/animation/curves.dart index d824c8221ac..0c54a653f03 100644 --- a/packages/flutter/lib/src/animation/curves.dart +++ b/packages/flutter/lib/src/animation/curves.dart @@ -705,6 +705,27 @@ class CatmullRomSpline extends Curve2D { Offset? startHandle, Offset? endHandle, }) { + assert( + startHandle == null || startHandle.isFinite, + 'The provided startHandle of CatmullRomSpline must be finite. The ' + 'startHandle given was $startHandle.' + ); + assert( + endHandle == null || endHandle.isFinite, + 'The provided endHandle of CatmullRomSpline must be finite. The endHandle ' + 'given was $endHandle.' + ); + assert(() { + for (int index = 0; index < controlPoints.length; index++) { + if (!controlPoints[index].isFinite) { + throw FlutterError( + 'The provided CatmullRomSpline control point at index $index is not ' + 'finite. The control point given was ${controlPoints[index]}.' + ); + } + } + return true; + }()); // If not specified, select the first and last control points (which are // handles: they are not intersected by the resulting curve) so that they // extend the first and last segments, respectively. diff --git a/packages/flutter/test/animation/curves_test.dart b/packages/flutter/test/animation/curves_test.dart index 62f426870f5..f7b0757fd5d 100644 --- a/packages/flutter/test/animation/curves_test.dart +++ b/packages/flutter/test/animation/curves_test.dart @@ -305,6 +305,28 @@ void main() { expect(() { CatmullRomSpline(const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], tension: 2.0); }, throwsAssertionError); + expect(() { + CatmullRomSpline( + const [Offset(double.infinity, 0.0), Offset.zero, Offset.zero, Offset.zero], + ).generateSamples(); + }, throwsAssertionError); + expect(() { + CatmullRomSpline( + const [Offset(0.0, double.infinity), Offset.zero, Offset.zero, Offset.zero], + ).generateSamples(); + }, throwsAssertionError); + expect(() { + CatmullRomSpline( + startHandle: const Offset(0.0, double.infinity), + const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], + ).generateSamples(); + }, throwsAssertionError); + expect(() { + CatmullRomSpline( + endHandle: const Offset(0.0, double.infinity), + const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], + ).generateSamples(); + }, throwsAssertionError); }); test('CatmullRomSpline interpolates values properly when precomputed', () { @@ -353,6 +375,24 @@ void main() { expect(() { CatmullRomSpline.precompute(const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], tension: 2.0); }, throwsAssertionError); + expect(() { + CatmullRomSpline.precompute(const [Offset(double.infinity, 0.0), Offset.zero, Offset.zero, Offset.zero]); + }, throwsAssertionError); + expect(() { + CatmullRomSpline.precompute(const [Offset(0.0, double.infinity), Offset.zero, Offset.zero, Offset.zero]); + }, throwsAssertionError); + expect(() { + CatmullRomSpline.precompute( + startHandle: const Offset(0.0, double.infinity), + const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], + ); + }, throwsAssertionError); + expect(() { + CatmullRomSpline.precompute( + endHandle: const Offset(0.0, double.infinity), + const [Offset.zero, Offset.zero, Offset.zero, Offset.zero], + ); + }, throwsAssertionError); }); test('CatmullRomCurve interpolates given points correctly', () {