Repository navigation
Reject incomplete JSON numbers instead of coercing them via strtod - #351
Merged
Merged
Conversation
json_parse treated 1., 1e, 1e+, and -.5 as valid because the tokenizer consumed the incomplete token and strtod parsed a prefix (1e → 1.0). Require digits after a decimal point or exponent marker, and require strtod to consume the whole token. Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
This was referenced Sep 17, 2026
…umber # Conflicts: # CHANGELOG.md
tylerreckart
marked this pull request as ready for review
September 21, 2026 12:58
tylerreckart
enabled auto-merge (squash)
September 21, 2026 12:58
…umber # Conflicts: # CHANGELOG.md
…umber # Conflicts: # CHANGELOG.md # CMakeLists.txt
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
json_parsetokenized1.,1e,1e+, and-.5as numbers. RFC 8259 requires at least one digit after a decimal point and after an exponent marker, and an integer part before a fraction.strtodthen parsed a prefix of that capture ("1e"→ 1.0, end pointer on'e'), so the document was accepted.MCP tool payloads, A2A envelopes, HTTP JSON bodies, and TUI session blobs all share this parser. A malformed number was silently coerced instead of rejected, which can shift later tokens in arrays/objects (
[1.,2]became[1, 2]).Distinct from #342 (UTF-16 surrogate pairs in
parse_string).Fix
parse_numbernow follows the JSON grammar for frac/exp completeness: a present.ore/Emust be followed by at least one digit, and the integer part cannot be empty (-.5fails).strtodmust consume the whole token;ERANGEstill fails closed. Leading zeros (01) are unchanged.Tests
unit_json_numbers— well-formed ints/fracs/exponents still parse; incomplete frac/exp (bare, nested in arrays/objects) throw; overflow1e9999still throws. Suite 4/4 locally (56 assertions), including ASan and ASan+UBSan.arbitercompiles.Independently mergeable against
main(0456350). Code hunks (parse_number+ newtests/test_json_numbers.cpp+ CMake target afterunit_remote_connect) auto-merge with #342 (parse_stringsurrogates +tests/test_json.cppafterunit_logger). CHANGELOG[Unreleased]sibling-conflicts as usual after the first of #321–#350 merges.Note
Medium Risk
Stricter parsing may reject payloads that previously parsed successfully, but that is intentional fail-closed behavior on shared ingress JSON for MCP/A2A/HTTP.
Overview
json_parsenow enforces RFC 8259 number shape instead of accepting truncated tokens thatstrtodcould partially parse (e.g.1.→1,1e→1.0,-.5accepted without an integer part). Fraction and exponent segments must include at least one digit when present, andstrtodmust consume the entire token (plus existingERANGEhandling).Because MCP, A2A, and HTTP JSON all use this parser, malformed numbers fail the document rather than shifting later tokens (e.g.
[1.,2]no longer becomes[1, 2]).Adds
unit_json_numbers(tests/test_json_numbers.cpp) covering valid ints/fracs/exponents, incomplete tokens in isolation and inside arrays/objects, and overflow. Documents the fix under[Unreleased]inCHANGELOG.md.Reviewed by Cursor Bugbot for commit 5e1525d. Bugbot is set up for automated code reviews on this repo. Configure here.