fix: accept subnormal and underflowing doubles when parsing (#1427)#1695
Merged
Conversation
Coverage Report for CI Build 27653693840Coverage remained the same at 89.959%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
04e7d25 to
d6a5e5d
Compare
decodeDouble parsed numbers via `istringstream >> double`. For a subnormal value such as `3.2114e-312`, operator>> sets failbit (the result underflowed) even though it produced the correctly-rounded value. The failure path only special-cased overflow, so subnormals were rejected as "not a number" -- meaning a value jsoncpp had just serialized could fail to parse back. In the failure path, accept the value when it is a subnormal (std::fpclassify(value) == FP_SUBNORMAL). This keys off the value operator>> produces, which is the correctly-rounded subnormal on libstdc++, libc++, and MSVC, so it needs no errno/eof heuristics. It deliberately does not accept results that round to zero, so malformed numbers like "0e" / "0e+" (jsonchecker fail29/fail30) and other junk are still rejected. Applied to both Reader and OurReader. Adds CharReaderTest/parseSubnormal covering subnormals, a writer round-trip, and continued rejection of malformed numbers.
d6a5e5d to
30ac06a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1427.
Problem
decodeDoubleparses numbers withistringstream >> double. For a subnormal value such as3.2114e-312,operator>>setsfailbit(the result underflowed) even though it produced the correctly-rounded value. The failure path only handled overflow, so subnormals fell through to"… is not a number."— meaning a value jsoncpp just serialized could fail to parse back:Fix
In the
operator>>failure path, accept the value when it is a subnormal (std::fpclassify(value) == FP_SUBNORMAL). This keys off the valueoperator>>produces — which is the correctly-rounded subnormal on libstdc++, libc++, and MSVC — so it needs noerrno/eofheuristics (both of which proved non-portable: MSVC doesn't reliably seterrno == ERANGE, andeof()also accepts malformed-but-complete tokens).It deliberately does not accept results that round to zero, so malformed numbers like
0e/0e+(jsoncheckerfail29/fail30) and other junk remain rejected. Applied to bothReaderandOurReader. Locale-independence from #1662 is preserved.Tests
New
CharReaderTest/parseSubnormalcovers subnormals (3.2114e-312,-1e-320, smallest subnormal4.9e-324), a writer round-trip, and continued rejection of1abc/0e/0e+. Verified locally against the JSON conformance suite (all 96 pass) and across the full CI matrix incl. MSVC. Targets the 1.10.0 line.