fix: preserve out-of-float64-range numbers when decoding into json.Number (#555) - #599
Open
hdimer wants to merge 1 commit into
Open
fix: preserve out-of-float64-range numbers when decoding into json.Number (#555)#599hdimer wants to merge 1 commit into
hdimer wants to merge 1 commit into
Conversation
…mber numberDecoder validated every literal with strconv.ParseFloat and rejected any error, so a number whose magnitude overflows float64 (e.g. 1e999, a 400-digit integer) was rejected with "value out of range" when decoding into a json.Number field or via Decoder.UseNumber(). json.Number keeps the literal verbatim and encoding/json accepts these, so this was a silent divergence. Ignore ParseFloat's ErrRange (the literal is still a syntactically valid number) while still rejecting genuine syntax errors. Scoped to json.Number; float64/int overflow handling is unchanged. Fixes goccy#555
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.
Problem
numberDecoder(the decoder used forjson.Numberfields andDecoder.UseNumber()) validated every literal withstrconv.ParseFloatand rejected any error it returned. Becausejson.Numberkeeps the literal verbatim, a number whose magnitude overflowsfloat64is still a perfectly validjson.Number, andencoding/jsonaccepts it. go-json instead rejected it withstrconv.ParseFloat: ... value out of range.Same for a 400-digit integer,
1.7976931348623157e400, etc. This is a silent compatibility break: the caller asked for the raw literal and got an error instead. Reported in #555 (originating from an OpenTelemetry payload with an oversized number).Fix
Ignore
ParseFloat'sErrRange(the literal is syntactically valid, just out offloat64range) and keep rejecting all other errors. Both call sites (DecodeandDecodeStream) go through a sharedvalidateNumberhelper.numberDecoderonly ever writes ajson.Number, sofloat64/intdecoding (which should still reject overflow) is untouched.Tests
Test_Decoder_Number_OutOfFloat64Rangecovers theUnmarshal, streamingDecoder, andjson.Numberstruct-field paths. It asserts overflow/underflow literals are preserved verbatim and that malformed numbers (1e2e3,1e+-2,1.2.3) are still rejected. Verified byte-for-byte againstencoding/json; full suite green.One note
The check still leans on
ParseFloat, so two oddly-formatted overflow literals (1.e999,01e999) are now accepted where stdlib rejects them. That is consistent with the leading-zero / trailing-dot leniency already tolerated for their in-range twins (1.e1,01, commented out ininvalidTestsinnumber_test.go). Making those strict would mean replacingParseFloatwith a full JSON-number grammar check and dropping that intentional leniency, so I kept this change scoped to the reported bug.Used AI assistance on this; I reviewed and tested it.