From 6cd082f7f53821bbc2d6c59ee5ae812583f3067f Mon Sep 17 00:00:00 2001 From: youdie006 Date: Mon, 28 Sep 2026 00:58:09 +0900 Subject: [PATCH] JRuby: keep the whole character after an invalid escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With allow_invalid_escape, the JRuby decoder appended the code point read after a stray backslash with append(int), which writes only its low byte. "\\é" became "\xE9" and "\\あ" became "B", where the C extension keeps the character. Use writeUtf8Char, as the other code point paths do. --- java/src/json/ext/StringDecoder.java | 2 +- test/json/json_parser_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/java/src/json/ext/StringDecoder.java b/java/src/json/ext/StringDecoder.java index e35638a4b..362a0d685 100644 --- a/java/src/json/ext/StringDecoder.java +++ b/java/src/json/ext/StringDecoder.java @@ -155,7 +155,7 @@ private void handleEscapeSequence(ThreadContext context) throws IOException { break; default: if (allowInvalidEscape) { - append(character); + writeUtf8Char(character); } else { throw invalidEscape(context); } diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb index 2fd7e2745..025bf671c 100644 --- a/test/json/json_parser_test.rb +++ b/test/json/json_parser_test.rb @@ -223,6 +223,12 @@ def test_parse_invalid_escape assert_equal "foo", parse(%("fo\\o"), allow_invalid_escape: true) end + def test_parse_invalid_escape_non_ascii + assert_equal "caf\u00e9", parse(%("caf\\\u00e9"), allow_invalid_escape: true) + assert_equal "\u3042", parse(%("\\\u3042"), allow_invalid_escape: true) + assert_equal "\u{1F600}", parse(%("\\\u{1F600}"), allow_invalid_escape: true) + end + def test_parse_arrays assert_equal([1,2,3], parse('[1,2,3]')) assert_equal([1.2,2,3], parse('[1.2,2,3]'))