-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<charconv>
: Fix from_chars()
float
tiebreaking
#2366
<charconv>
: Fix from_chars()
float
tiebreaking
#2366
Conversation
Lines 881 to 885 in 3c2fd04
Is .NET affected by the issue? |
tests/std/tests/P0067R5_charconv/float_from_chars_test_cases.hpp
Outdated
Show resolved
Hide resolved
Lines 439 to 463 in 369619f
_Make_big_integer_flt_u32 and _Make_big_integer_flt_u64 don't properly set _Myused to 0 when _Value is 0.
These functions are not used anywhere in the repo. Should we fix the bug or just remove them? |
I'd prefer 🔥, with "fix and |
@AlexGuteniev I don't think so, as this was specific to how we were testing for "is the remainder zero", and our @statementreply Great catch! They were originally used in the fallback codepath to print large integers exactly - I constructed a |
I was the original poster of the bug on developer community. I have a set of tests that can test each individual floats rounding boundary. With this change, I could no longer find any issues. |
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Fixes #2363.
from_chars()
is complicated, but this root cause was simple, in isolation. It involved our only call to bignum division:STL/stl/inc/charconv
Lines 1582 to 1584 in 3c2fd04
This is trying to check if the remainder is zero:
STL/stl/inc/charconv
Lines 881 to 885 in 3c2fd04
And it was assuming that
_Big_integer_flt
is "trimmed", i.e. that "represents zero" is equivalent to_Myused == 0
(indicating no active elements).However, one codepath in
_Divide
can result in a_Big_integer_flt
where_Myused
is1
and_Mydata[0]
is0
:STL/stl/inc/charconv
Lines 933 to 936 in 3c2fd04
In the bug scenario, this leads to
_Has_zero_tail
becoming mistakenlyfalse
, so when tiebreaker scenarios want to round to Even and Even happens to be Down, they instead round Up (as a non-zero tail would indicate that we're just above the exact midpoint).The fix is to perform trimming in this codepath. I checked all of
_Divide
's other paths toreturn
, and they all appear to be properly trimmed.This bug was present in the UCRT's original sources (i.e. in VS 2015
strtof
), carefully preserved during my distillation process. I'll send the fix to them, and we'll have to figure out how to get the compiler fixed too.Here's my exhaustive test:
I've taken the exhaustive test's output of sample bugs and unaffected examples, and added test cases accordingly. I believe that this is more than enough, and that we don't need to add randomized coverage of this space. I mechanically transformed the output into test cases, with manual adjustment for the subnormal example (since it's printed as
0x1.MEOW
as adouble
, but we want to see0x0.PURR
to match thefloat
representation). I also verified that the final test cases fail without the fix, and pass with the fix.Finally, this removes
_Make_big_integer_flt_u32()
,_Make_big_integer_flt_u64()
, and_Make_big_integer_flt_power_of_two()
which were unused. Thanks to @statementreply for noticing them.