Skip to content

Debug builds crash converting decimals like 10.0m or 100.00m: Debug.Assert in ParseRenderedFloat fires on valid input #112

Description

@matt-edmondson

What's wrong

ParseRenderedFloat (PreciseNumber/PreciseNumber.cs, ~lines 655-670) removes trailing zeros from the rendered text and then asserts on the result:

while (text.Length > 2 && text[^1] == '0') { text = text[..^1]; ... }
...
ReadOnlySpan<char> fractionalComponent = decimalIndex < 0 ? "0".AsSpan() : text[(decimalIndex + 1)..];
...
Debug.Assert(fractionalComponent.Length != 0 || integerComponent.TrimStart("-").Length == 1, $"Unexpected format: {text}");

A decimal with more than one integer digit and only zeros after the point shows the problem. 10.0m renders as "10.0", and trimming turns that into "10.". The fractional part is now empty and the integer part is "10", which has two digits, so the assert fails even though the input is valid. 100.00m, -20.0m, and similar values do the same.

Why it matters

  • Debug builds. A failed Debug.Assert on .NET ends the process ("Assertion failed. Unexpected format: 10."). That hits anyone who consumes the library by project reference or source, and anyone running its tests in the default Debug configuration.
  • Release builds. The assert is compiled out and the code after it returns the correct value, 10. The failure therefore only shows up while developing, which is when people are least likely to expect a crash from a number conversion.
  • The rule itself is wrong. The assert encodes a format invariant that the trimming loop just above it does not guarantee.

Suggested fix

Remove the assert. Alternatively, make the trimming loop stop at the decimal point, for example text[^1] == '0' && text[^2] != '.', so that the fraction always keeps at least one digit.

Acceptance criteria

  • In a Debug build, 10.0m.ToPreciseNumber(), 100.00m.ToPreciseNumber(), and (-20.0m).ToPreciseNumber() return 10, 100, and -20 without an assertion failure.
  • A regression test runs in the Debug test configuration.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions