Skip to content

Commit 5855f4f

Browse files
committed
parser: Reject invalid surogate pairs more consistently.
1 parent 618ab68 commit 5855f4f

File tree

3 files changed

+13
-1
lines changed

3 files changed

+13
-1
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* Fix `JSON.generate` `strict: true` mode to also restrict hash keys.
1717
* Fix `JSON::Coder` to also invoke block for hash keys that aren't strings nor symbols.
1818
* Fix `JSON.unsafe_load` usage with proc
19+
* Fix the parser to more consistently reject invalid UTF-16 surogate pairs.
1920

2021
### 2025-07-28 (2.13.2)
2122

ext/json/ext/parser/parser.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,11 +713,16 @@ static VALUE json_string_unescape(JSON_ParserState *state, const char *string, c
713713
}
714714
if (pe[0] == '\\' && pe[1] == 'u') {
715715
uint32_t sur = unescape_unicode(state, (unsigned char *) pe + 2);
716+
717+
if ((sur & 0xFC00) != 0xDC00) {
718+
raise_parse_error_at("invalid surrogate pair at %s", state, p);
719+
}
720+
716721
ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
717722
| (sur & 0x3FF));
718723
pe += 5;
719724
} else {
720-
unescape = (char *) "?";
725+
raise_parse_error_at("incomplete surrogate pair at %s", state, p);
721726
break;
722727
}
723728
}

test/json/json_parser_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,12 @@ def test_invalid_unicode_escape
319319
assert_raise(JSON::ParserError) { parse('"\u111___"') }
320320
end
321321

322+
def test_invalid_surogates
323+
assert_raise(JSON::ParserError) { parse('"\\uD800"') }
324+
assert_raise(JSON::ParserError) { parse('"\\uD800_________________"') }
325+
assert_raise(JSON::ParserError) { parse('"\\uD800\\u0041"') }
326+
end
327+
322328
def test_parse_big_integers
323329
json1 = JSON(orig = (1 << 31) - 1)
324330
assert_equal orig, parse(json1)

0 commit comments

Comments
 (0)