Fix out of bounds read with kParseValidateEncodingFlag

This commit is contained in:
Mikhail Khachayants 2024-12-22 15:53:24 +02:00 committed by Milo Yip
parent b1c0c2843f
commit 24b5e7a8b2
2 changed files with 20 additions and 2 deletions

View File

@ -177,10 +177,10 @@ struct UTF8 {
template <typename InputStream, typename OutputStream> template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) { static bool Validate(InputStream& is, OutputStream& os) {
#define RAPIDJSON_COPY() os.Put(c = is.Take()) #define RAPIDJSON_COPY() if (c != '\0') os.Put(c = is.Take())
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
Ch c; Ch c = static_cast<Ch>(-1);
RAPIDJSON_COPY(); RAPIDJSON_COPY();
if (!(c & 0x80)) if (!(c & 0x80))
return true; return true;

View File

@ -987,6 +987,24 @@ TEST(Reader, ParseString_Error) {
} }
} }
// 3.6 Lonely start characters near the end of the input
{
char e[] = { '\"', 0, '\"', '\0' };
for (unsigned c = 0xC0u; c <= 0xFFu; c++) {
e[1] = static_cast<char>(c);
unsigned streamPos;
if (c <= 0xC1u)
streamPos = 2; // 0xC0 - 0xC1
else if (c <= 0xDFu)
streamPos = 3; // 0xC2 - 0xDF
else if (c <= 0xF4u)
streamPos = 4; // 0xE0 - 0xF4
else
streamPos = 2; // 0xF5 - 0xFF
TEST_STRING_ERROR(kParseErrorStringInvalidEncoding, e, 1u, streamPos);
}
}
// 4 Overlong sequences // 4 Overlong sequences
// 4.1 Examples of an overlong ASCII character // 4.1 Examples of an overlong ASCII character