Skip to content

Fix NaN regression in double parameter validation#11731

Open
wnvko-msft wants to merge 3 commits into
dotnet:mainfrom
wnvko-msft:mvenkov/fix-nan-values
Open

Fix NaN regression in double parameter validation#11731
wnvko-msft wants to merge 3 commits into
dotnet:mainfrom
wnvko-msft:mvenkov/fix-nan-values

Conversation

@wnvko-msft

@wnvko-msft wnvko-msft commented Jun 24, 2026

Copy link
Copy Markdown

Fixes #11317

Description

Reverts ArgumentOutOfRangeException.ThrowIfNegative/ThrowIfNegativeOrZero usage on double parameters introduced in PR #8408. The ThrowIfNegative helper internally uses double.IsNegative() which returns true for NaN (because NaN has the sign bit set), while the original value < 0 check returns false per IEEE 754 semantics. This caused properties like FormattedText.LineHeight to reject NaN values that were previously valid (e.g., the default TextBox.LineHeight is NaN).

Affected files:

  • FormattedText.cs - ValidateFontSize, LineHeight setter, MaxTextWidth setter
  • D3DImage.cs - dpiX, dpiY constructor parameters
  • TextFormatterImp.cs - FontRenderingEmSize, DefaultIncrementalTab validation

Also restores removed resource strings (ParameterCannotBeNegative, ParameterMustBeBetween, ParameterMustBeGreaterThanZero) and their xlf translation entries.

Customer Impact

Applications that pass NaN to double properties (most commonly FormattedText.LineHeight = textBox.LineHeight where the default is NaN) now throw ArgumentOutOfRangeException unexpectedly. This breaks existing code that worked in .NET Framework and up to .NET 8.

Regression

Yes. This is a regression introduced in .NET 9 by PR #8408. The behavior worked correctly in .NET Framework and all versions through .NET 8.

Testing

Added unit tests in PresentationCore.Tests covering the NaN regression:

  • FormattedTextTests: Verifies LineHeight and MaxTextWidth accept double.NaN and 0.0 without throwing, while negative values still throw ArgumentOutOfRangeException.
  • D3DImageTests: Verifies constructor accepts double.NaN for DPI parameters without throwing, while negative values still throw ArgumentOutOfRangeException.

Risk

Low. This is a targeted revert of the specific ThrowIfNegative calls on double parameters back to the original manual comparison pattern. Integer-parameter usages of ThrowIfNegative (which have no NaN concern) are left unchanged. The fix restores the exact validation semantics from .NET 8 and earlier.

Microsoft Reviewers: Open in CodeFlow

Copilot AI review requested due to automatic review settings June 24, 2026 13:54
@wnvko-msft wnvko-msft requested review from a team as code owners June 24, 2026 13:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a .NET 9 regression in WPF where double-typed parameters/properties began rejecting NaN due to ArgumentOutOfRangeException.ThrowIfNegative* using floating-point sign-bit semantics that differ from the historical value < 0 checks. It restores the pre-.NET 9 validation behavior (notably allowing NaN where it previously flowed through), reintroduces the prior localized resource strings used by WPF’s custom exceptions, and adds targeted unit tests to prevent regressions.

Changes:

  • Revert double validation from ThrowIfNegative* helpers back to manual comparisons (e.g., < 0, <= 0) to preserve historical NaN behavior.
  • Restore WPF resource strings (ParameterCannotBeNegative, ParameterMustBeBetween, ParameterMustBeGreaterThanZero) and corresponding XLF entries.
  • Add new unit tests validating NaN acceptance and negative-value rejection for FormattedText and D3DImage.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Microsoft.DotNet.Wpf/tests/UnitTests/PresentationCore.Tests/System/Windows/Media/FormattedText.Tests.cs Adds unit tests for FormattedText.LineHeight / MaxTextWidth NaN/zero acceptance and negative rejection.
src/Microsoft.DotNet.Wpf/tests/UnitTests/PresentationCore.Tests/System/Windows/Interop/D3DImage.Tests.cs Adds unit tests ensuring D3DImage constructor accepts NaN DPI and rejects negative DPI.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/textformatting/TextCharacters.cs Restores manual validation for FontRenderingEmSize to avoid NaN being treated as negative/zero by throw helpers.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/FormattedText.cs Restores manual double validation for ValidateFontSize, LineHeight, and MaxTextWidth to preserve NaN behavior.
src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/D3DImage.cs Restores manual validation for DPI parameters to preserve NaN behavior.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/Strings.resx Reintroduces removed resource strings used for validation error messages.
src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/TextFormatting/TextFormatterImp.cs Restores manual range checks for FontRenderingEmSize and DefaultIncrementalTab with WPF resource-based messages.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.cs.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.de.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.es.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.fr.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.it.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.ja.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.ko.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.pl.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.pt-BR.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.ru.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.tr.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.zh-Hans.xlf Restores XLF entries for reintroduced resource strings.
src/Microsoft.DotNet.Wpf/src/PresentationCore/Resources/xlf/Strings.zh-Hant.xlf Restores XLF entries for reintroduced resource strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Included in test pass PR metadata: Label to tag PRs, to facilitate with triage Status:Completed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression in double properties and NaN

3 participants