Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/lib_json/json_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,13 +678,21 @@ bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
if (*(current++) == '\\' && *(current++) == 'u') {
unsigned int surrogatePair;
if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
if (surrogatePair < 0xDC00 || surrogatePair > 0xDFFF)
return addError("expecting a low surrogate (DC00-DFFF) to complete "
"the unicode surrogate pair",
token, current);
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
return addError("expecting another \\u token to begin the second half of "
"a unicode surrogate pair",
token, current);
} else if (unicode >= 0xDC00 && unicode <= 0xDFFF) {
return addError("unexpected low surrogate (DC00-DFFF); a high surrogate "
"(D800-DBFF) must come first",
token, current);
}
return true;
}
Expand Down Expand Up @@ -1759,13 +1767,21 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
if (*(current++) == '\\' && *(current++) == 'u') {
unsigned int surrogatePair;
if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
if (surrogatePair < 0xDC00 || surrogatePair > 0xDFFF)
return addError("expecting a low surrogate (DC00-DFFF) to complete "
"the unicode surrogate pair",
token, current);
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
return addError("expecting another \\u token to begin the second half of "
"a unicode surrogate pair",
token, current);
} else if (unicode >= 0xDC00 && unicode <= 0xDFFF) {
return addError("unexpected low surrogate (DC00-DFFF); a high surrogate "
"(D800-DBFF) must come first",
token, current);
}
return true;
}
Expand Down
18 changes: 18 additions & 0 deletions src/test_lib_json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3322,6 +3322,24 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
"second half of a unicode surrogate pair\n"
"See Line 1, Column 12 for detail.\n");
}
{
char const doc[] = R"([ "\uD801\u0041" ])";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tests for the legacy reader change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the legacy Reader change entirely, so there's no behavior change left there to test. It has no Features knob to gate this on, and keeping it lenient avoids breaking input that parsed before. The validation now lives only in OurReader behind the rejectInvalidSurrogates setting.

bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
" expecting a low surrogate (DC00-DFFF) to "
"complete the unicode surrogate pair\n"
"See Line 1, Column 16 for detail.\n");
}
{
char const doc[] = R"([ "\uDC00" ])";
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
" unexpected low surrogate (DC00-DFFF); a high "
"surrogate (D800-DBFF) must come first\n"
"See Line 1, Column 10 for detail.\n");
}
{
char const doc[] = R"([ "\ua3t@" ])";
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
Expand Down