Skip to content

jsonrpc@1: read any JSON spelling of a method name, write valid JSON, refuse non-UTF-8 frames - #28

Merged
Kinflou merged 2 commits into
mainfrom
fix/jsonrpc-strings
Oct 25, 2026
Merged

Kinflou merged 2 commits into
mainfrom
fix/jsonrpc-strings

Conversation

@Kinflou

@Kinflou Kinflou commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Bumps comline-runtime to 78320db (runtime main), which brings ComlineProject/runtime#45, and ports that PR's two fixes to the simulator's vendored JSON-RPC framing (src/framing.rs). The runtime keeps JsonRpcFraming behind std, and std doesn't build for wasm32, so the simulator still can't delegate to it. The vendored helpers (method_of, put_method, parse) now match the runtime's text, apart from core::str vs std::str.

Both bugs were present

The new tests carry runtime#45's framing-jsonrpc/found-* conformance cases byte for byte. Against the old code:

  • runtime#41, reading: a_method_name_reads_in_any_json_spelling fails because "app.Chat\/count" was refused (method: &str can't borrow an escaped string).
  • runtime#41, writing: a_method_name_is_written_as_serde_json_writes_it fails because a name containing ", \ or control characters was copied into the frame unescaped, which gave invalid JSON.
  • runtime#42: invalid_utf8_anywhere_refuses_the_frame fails because a request with 0xff inside "jsonrpc" was accepted. Requests and responses used serde_json::from_slice, which doesn't check skipped members. In the simulator this could actually happen: the corrupt fault flips a byte in the frame's back half with ^ 0xff, which can land in error.message and leave a frame that the simulator accepted and a real runtime refuses.

Changes

  • RequestCall::Name now holds a MethodName. Request decode reads method as a RawValue and passes it to MethodName::from_json. A method that isn't a string, or isn't valid JSON string text, is refused.
  • Encoding uses the runtime's put_method escaper.
  • Request and response decode check that the whole frame is UTF-8, then call serde_json::from_str.
  • generic.rs: tests updated for the new type, plus a case that resolves an escaped name (s\u0065nd).

Also: exact f64 reads (float_roundtrip)

The simulator's own serde_json now enables float_roundtrip, matching runtime's JSON format. The default parser is best-effort and reads some f64 values one ulp off. format::tests::an_f64_reads_back_exactly uses runtime's format-json/found-f64-exact-digits value, 4.520618856987477e-279. Before this change, the test failed: the value was read as bits 0x062483bf55de65f1 instead of ...f2.

WASM size

JSON-RPC fix only, wasm-bindgen output before wasm-opt, measured locally:

build before after delta
lean (--no-default-features) 1,032,675 1,036,377 +3,702 (+0.36%)
scripted 3,629,655 3,633,265 +3,610 (+0.10%)

Post-wasm-opt sizes, from CI logs:

build main (4e8e5e3) JSON-RPC fix (f3fbb6f) + float_roundtrip (3acd78c)
lean 570,813 572,719 (+1,906, +0.33%) 595,508 (+22,789, +4.0%)
scripted 2,179,493 2,181,484 (+1,991, +0.09%) 2,203,969 (+22,485, +1.0%)

float_roundtrip adds about 22 KB because it compiles in serde_json's exact (arbitrary-precision) float parser.

Follow-up

Once this merges, the playground (app/package.json, which pins 4e8e5e3) needs a bump.

Kinflou added 2 commits October 26, 2026 03:26
… refuse non-UTF-8 frames

Bump comline-runtime to 78320db (runtime main), which brings runtime#45,
and port its fixes to the simulator's vendored JSON-RPC framing:

- A request's `method` is read as raw JSON and becomes a
  `contract::MethodName`, so a name with escapes (`"app.Chat\/count"`)
  is accepted instead of refused (runtime#41).
- A method name is written escaped as serde_json escapes it, so a name
  with `"`, `\` or a control character makes valid JSON (runtime#41).
- Requests and responses are UTF-8-checked whole before parsing, so
  invalid UTF-8 in an ignored member (`jsonrpc`, `error.message`, an
  unknown member) refuses the frame (runtime#42). The `corrupt` fault
  flips a byte with `^ 0xff`, so it could produce such a frame.

The new tests carry runtime#45's `framing-jsonrpc/found-*` conformance
cases byte for byte; they fail against the old code.
Enable serde_json's `float_roundtrip`, as comline-runtime's JSON format
does. The default parser is best-effort and reads some f64s one ulp off;
the test carries runtime's `format-json/found-f64-exact-digits` value,
4.520618856987477e-279, which it read as bits 0x062483bf55de65f1 instead
of 0x062483bf55de65f2.
@Kinflou
Kinflou force-pushed the fix/jsonrpc-strings branch from 76daf2f to 3acd78c Compare October 25, 2026 19:32
@Kinflou
Kinflou merged commit 279a56c into main Oct 25, 2026
1 check passed
@Kinflou
Kinflou deleted the fix/jsonrpc-strings branch October 25, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant