From 61f1efb26797bb1176e4d1341a593645d6402dea Mon Sep 17 00:00:00 2001 From: Mykola Bilochub Date: Sun, 11 Jun 2017 03:20:11 +0300 Subject: [PATCH] parser: parse Unicode escape sequences in objects --- src/jsrs_parser.cc | 49 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/jsrs_parser.cc b/src/jsrs_parser.cc index 9b52e450..c2747a06 100644 --- a/src/jsrs_parser.cc +++ b/src/jsrs_parser.cc @@ -24,6 +24,7 @@ using std::isdigit; using std::isinf; using std::isnan; using std::isxdigit; +using std::memcpy; using std::memset; using std::ptrdiff_t; using std::size_t; @@ -718,17 +719,55 @@ MaybeLocal ParseKeyInObject(Isolate* isolate, size_t current_length = 0; size_t cp_size; uint32_t cp; + bool ok; + char* fallback = nullptr; + size_t fallback_length; + bool is_escape = false; while (current_length < *size) { - cp = Utf8ToCodePoint(begin + current_length, &cp_size); + if (begin[current_length] == '\\' && + begin[current_length + 1] == 'u') { + cp = ReadUnicodeEscapeSequence(isolate, begin + current_length + 2, + &cp_size, &ok); + if (!ok) { + return MaybeLocal(); + } + cp_size += 2; + if (!fallback) { + fallback = new char[*size + 1]; + memcpy(fallback, begin, current_length); + fallback_length = current_length; + } + is_escape = true; + } else { + cp = Utf8ToCodePoint(begin + current_length, &cp_size); + is_escape = false; + } if (current_length == 0 ? IsIdStartCodePoint(cp) : IsIdPartCodePoint(cp)) { + if (fallback) { + if (!is_escape) { + memcpy(fallback + fallback_length, begin + current_length, cp_size); + fallback_length += cp_size; + } else { + size_t fallback_cp_size; + CodePointToUtf8(cp, &fallback_cp_size, fallback + fallback_length); + fallback_length += fallback_cp_size; + } + } current_length += cp_size; } else { if (current_length != 0) { - result = String::NewFromUtf8(isolate, begin, - NewStringType::kInternalized, - static_cast(current_length)) - .ToLocalChecked(); + if (!fallback) { + result = String::NewFromUtf8(isolate, begin, + NewStringType::kInternalized, + static_cast(current_length)) + .ToLocalChecked(); + } else { + result = String::NewFromUtf8(isolate, fallback, + NewStringType::kInternalized, + static_cast(fallback_length)) + .ToLocalChecked(); + } break; } else { THROW_EXCEPTION(SyntaxError, "Unexpected identifier");