Repository navigation
jsonrpc: normalize decimal and exponent integer IDs exactly - #1493
Closed
Shanmukh-l33t wants to merge 1 commit into
Closed
Shanmukh-l33t wants to merge 1 commit into
Shanmukh-l33t wants to merge 1 commit into
Conversation
Numeric request IDs that spell an integer in decimal or exponent form, such as 9007199254740993.0 or 90071992547409930e-1, still went through the float64 fallback in MakeID and lost precision above 2^53, even though modelcontextprotocol#1401 made integer-literal IDs exact. The same loss affected responses, which must echo the request ID exactly, and the matching of notifications/cancelled, whose requestId also travels through MakeID. MakeID now normalizes a json.Number whose value is an integer in the int64 range exactly, whatever its spelling: the integer-literal fast path stays, and other integral forms are parsed digit by digit into their exact value, with no exponent-sized allocations. Values that are genuinely fractional or out of the int64 range keep the existing float64 fallback, and the float64 input behavior is unchanged. Fixes modelcontextprotocol#1404
Contributor
|
This PR has been closed automatically. This repo only keeps pull requests open when they come from a maintainer, or from a contributor a maintainer has assigned to the linked issue, and you aren't currently assigned to #1404. You're welcome to keep pushing commits here (just avoid force-pushing, since GitHub can't reopen a rewritten branch), but that on its own won't get the PR reviewed or the issue assigned. There's no need to open a new PR either way. Maintainers: reopen, remove |
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
After #1401, integer-literal request IDs retain their precision, but equivalent decimal and exponent spellings still fall through
MakeID'sfloat64fallback and lose precision above 2^53, as reported in #1404:9007199254740993900719925474099390071992547409939007199254740993.09007199254740993900719925474099290071992547409930e-190071992547409939007199254740992-9007199254740993.0-9007199254740993-9007199254740992This affects message decoding (a decoded
Request.ID/Response.IDcarries the wrong value, and a response echoes the wrong ID), and cancellation: an in-flight request with ID9007199254740993does not matchnotifications/cancelledwhoserequestIdis spelled9007199254740993.0, because both sides resolve their IDs throughMakeID.Solution
MakeIDnow normalizes ajson.Numberwhose value is exactly an integer in theint64range, whatever its spelling: the integer-literal fast path is kept, and decimal/exponent forms are parsed digit by digit into their exact value (9007199254740993.0,90071992547409930e-1,1.5e2, …). The exponent is handled arithmetically with a bound relative to the input length, so even absurd inputs like0e1000000cost no exponent-sized allocation and still resolve exactly. Only the numeric value is preserved, not the original spelling, so a response echoes the request ID's value exactly as JSON-RPC requires.Per the scope proposed in #1404, values that are genuinely fractional (
1.5) or out of theint64range keep the existingfloat64fallback, and thefloat64input behavior is unchanged. This also restores ID equality fornotifications/cancelledmatching across spellings, since the canceller resolves both the request ID andrequestIdthroughMakeID.Testing
TestIntegralNumberIDsininternal/jsonrpc2/wire_test.gocovering the exact cases from jsonrpc: decimal and exponent integer IDs still lose precision after #1401 #1404 plus boundary (9223372036854775807.0,-9223372036854775808.0e0), huge-exponent (0e1000000), and fractional-fallback (1.5) cases. It round-trips each ID throughDecodeMessage/EncodeMessage(both request and response forms) and checksMakeID(json.Number(...))yields the same ID, which is the cancellation matching invariant. It fails before the fix with exactly the values from the issue table and passes after.gofmt -l .clean,go vet ./...clean,go test ./...passes (14 packages).Fixes #1404
AI assistance: developed with an AI coding agent; the change and its reasoning are reviewed and owned by me.