Skip to content

Fix parser silently accepting a lone trailing surrogate in string values - #1070

Open
elang2 wants to merge 1 commit into
ruby:masterfrom
elang2:fix-lone-trailing-surrogate-1069
Open

Fix parser silently accepting a lone trailing surrogate in string values#1070
elang2 wants to merge 1 commit into
ruby:masterfrom
elang2:fix-lone-trailing-surrogate-1069

Conversation

@elang2

@elang2 elang2 commented Sep 6, 2026

Copy link
Copy Markdown

Fixes #1069.

Adds the symmetric else if ((ch & 0xFC00) == 0xDC00) branch in json_string_unescape so a lone trailing surrogate escape raises JSON::ParserError at the parse boundary instead of writing ED B0 80 into the output buffer and returning a String that fails valid_encoding?.

The Java parser at java/src/json/ext/StringDecoder.java:104-105 already rejects lone trailing surrogates; this closes the CRuby/JRuby parity gap the minefield test file documents at lines 41-43.

The C parser guards leading-first surrogate pairs but silently accepts
a lone trailing surrogate, encoding U+DC00..U+DFFF as three UTF-8 bytes
into the output buffer. The returned Ruby String is tagged UTF-8 but
fails valid_encoding? and raises misleading errors from downstream
String operations (upcase, split, regex, encode, JSON.generate).

Add a symmetric branch alongside the leading-surrogate check to raise
JSON::ParserError at the parse boundary. Extend test_invalid_surogates
with the new cases and move the three JSONTestSuite fixtures that this
fix newly rejects from INVALID_ENCODING_TESTS into UNDEFINED_FAILING,
closing the CRuby/JRuby parser parity gap documented in the file.
@elang2

elang2 commented Sep 6, 2026

Copy link
Copy Markdown
Author

Thanks @byroot for the triage on #1069. You closed it as a duplicate of the broader #138 (invalid-UTF-8 acceptance, open since 2012). Would a narrow scoped fix like this PR (lone-trailing surrogate in \uXXXX escape decoding, mirroring the leading-first fix that landed in 5855f4f) be welcome as a partial step toward #138?

@byroot

byroot commented Sep 6, 2026

Copy link
Copy Markdown
Member

Yeah, the parser as gotten more strict over time, since the 3.0 is around the corner it may be an occasion to make it stricter again. I'll see.

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.

JSON.parse silently returns an invalid-UTF-8 String on a lone trailing surrogate in a string value

2 participants