diff --git a/src/Avalonia.Base/Layout/Layoutable.cs b/src/Avalonia.Base/Layout/Layoutable.cs index fedea332b6..e0c316c60a 100644 --- a/src/Avalonia.Base/Layout/Layoutable.cs +++ b/src/Avalonia.Base/Layout/Layoutable.cs @@ -113,7 +113,7 @@ namespace Avalonia.Layout /// Defines the property. /// public static readonly StyledProperty MarginProperty = - AvaloniaProperty.Register(nameof(Margin)); + AvaloniaProperty.Register(nameof(Margin), validate: ValidateThickness); /// /// Defines the property. @@ -161,6 +161,8 @@ namespace Avalonia.Layout private static bool ValidateMinimumDimension(double value) => !double.IsPositiveInfinity(value) && ValidateMaximumDimension(value); private static bool ValidateMaximumDimension(double value) => value >= 0; + private static bool ValidateThickness(Thickness value) => double.IsFinite(value.Left) && double.IsFinite(value.Top) && double.IsFinite(value.Right) && double.IsFinite(value.Bottom); + /// /// Occurs when the element's effective viewport changes. /// diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index b816858632..29a31d8070 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -38,7 +38,7 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly StyledProperty BorderThicknessProperty = - AvaloniaProperty.Register(nameof(BorderThickness)); + AvaloniaProperty.Register(nameof(BorderThickness), validate: MarginProperty.ValidateValue); /// /// Defines the property. diff --git a/src/Avalonia.Controls/Chrome/WindowDrawnDecorations.cs b/src/Avalonia.Controls/Chrome/WindowDrawnDecorations.cs index ae279d6ab3..48847b5f59 100644 --- a/src/Avalonia.Controls/Chrome/WindowDrawnDecorations.cs +++ b/src/Avalonia.Controls/Chrome/WindowDrawnDecorations.cs @@ -58,13 +58,13 @@ public class WindowDrawnDecorations : StyledElement /// Defines the property. /// public static readonly StyledProperty DefaultFrameThicknessProperty = - AvaloniaProperty.Register(nameof(DefaultFrameThickness)); + AvaloniaProperty.Register(nameof(DefaultFrameThickness), validate: Border.BorderThicknessProperty.ValidateValue); /// /// Defines the property. /// public static readonly StyledProperty DefaultShadowThicknessProperty = - AvaloniaProperty.Register(nameof(DefaultShadowThickness)); + AvaloniaProperty.Register(nameof(DefaultShadowThickness), validate: Border.BorderThicknessProperty.ValidateValue); /// /// Defines the property. diff --git a/src/Avalonia.Controls/Decorator.cs b/src/Avalonia.Controls/Decorator.cs index e62ca0000b..8cd1916718 100644 --- a/src/Avalonia.Controls/Decorator.cs +++ b/src/Avalonia.Controls/Decorator.cs @@ -20,7 +20,7 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly StyledProperty PaddingProperty = - AvaloniaProperty.Register(nameof(Padding)); + AvaloniaProperty.Register(nameof(Padding), validate: MarginProperty.ValidateValue); /// /// Initializes static members of the class. diff --git a/src/Avalonia.Controls/Page/Page.cs b/src/Avalonia.Controls/Page/Page.cs index 601af92580..48b7bd1b0c 100644 --- a/src/Avalonia.Controls/Page/Page.cs +++ b/src/Avalonia.Controls/Page/Page.cs @@ -17,7 +17,7 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly StyledProperty SafeAreaPaddingProperty = - AvaloniaProperty.Register(nameof(SafeAreaPadding)); + AvaloniaProperty.Register(nameof(SafeAreaPadding), validate: PaddingProperty.ValidateValue); /// /// Defines the property. diff --git a/tests/Avalonia.Controls.UnitTests/BorderTests.cs b/tests/Avalonia.Controls.UnitTests/BorderTests.cs index e31eb08964..df80998b05 100644 --- a/tests/Avalonia.Controls.UnitTests/BorderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/BorderTests.cs @@ -1,9 +1,6 @@ +using System; using Avalonia.Layout; -using Avalonia.Media; -using Avalonia.Rendering; using Avalonia.UnitTests; -using Avalonia.VisualTree; -using Moq; using Xunit; namespace Avalonia.Controls.UnitTests @@ -45,14 +42,31 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Rect(6, 6, 0, 0), content.Bounds); } - + + [Fact] + public void Should_Reject_NaN_Or_Infinite_Thicknesses() + { + var target = new Border(); + + SetValues(target, Layoutable.MarginProperty); + SetValues(target, Decorator.PaddingProperty); + SetValues(target, Border.BorderThicknessProperty); + + static void SetValues(Border target, AvaloniaProperty property) + { + Assert.Throws(() => target.SetValue(property, new Thickness(0, 0, 0, double.NaN))); + Assert.Throws(() => target.SetValue(property, new Thickness(0, 0, 0, double.PositiveInfinity))); + Assert.Throws(() => target.SetValue(property, new Thickness(0, 0, 0, double.NegativeInfinity))); + } + } + public class UseLayoutRounding : ScopedTestBase { [Fact] public void Measure_Rounds_Padding() { - var target = new Border - { + var target = new Border + { Padding = new Thickness(1), Child = new Canvas {