unexpected_strict_reserved: ["Unexpected strict mode reserved word"],
unexpected_eos: ["Unexpected end of input"],
malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
+ malformed_regexp_flags: ["Invalid regular expression flags"],
unterminated_regexp: ["Invalid regular expression: missing /"],
regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
uc32 Scanner::ScanHexNumber(int expected_length) {
DCHECK(expected_length <= 4); // prevent overflow
- uc32 digits[4] = { 0, 0, 0, 0 };
uc32 x = 0;
for (int i = 0; i < expected_length; i++) {
- digits[i] = c0_;
int d = HexValue(c0_);
if (d < 0) {
- // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
- // should be illegal, but other JS VMs just return the
- // non-escaped version of the original character.
-
- // Push back digits that we have advanced past.
- for (int j = i-1; j >= 0; j--) {
- PushBack(digits[j]);
- }
return -1;
}
x = x * 16 + d;
Advance();
if (c0_ != 'u') return -1;
Advance();
- uc32 result = ScanHexNumber(4);
- if (result < 0) PushBack('u');
- return result;
+ return ScanHexNumber(4);
}
bool Scanner::ScanLiteralUnicodeEscape() {
DCHECK(c0_ == '\\');
- uc32 chars_read[6] = {'\\', 'u', 0, 0, 0, 0};
+ AddLiteralChar(c0_);
Advance();
- int i = 1;
+ int hex_digits_read = 0;
if (c0_ == 'u') {
- i++;
- while (i < 6) {
+ AddLiteralChar(c0_);
+ while (hex_digits_read < 4) {
Advance();
if (!IsHexDigit(c0_)) break;
- chars_read[i] = c0_;
- i++;
- }
- }
- if (i < 6) {
- // Incomplete escape. Undo all advances and return false.
- while (i > 0) {
- i--;
- PushBack(chars_read[i]);
+ AddLiteralChar(c0_);
+ ++hex_digits_read;
}
- return false;
- }
- // Complete escape. Add all chars to current literal buffer.
- for (int i = 0; i < 6; i++) {
- AddLiteralChar(chars_read[i]);
}
- return true;
+ return hex_digits_read == 4;
}
AddLiteralCharAdvance();
} else {
if (!ScanLiteralUnicodeEscape()) {
- break;
+ return false;
}
Advance();
}
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
+
+
+TEST(InvalidUnicodeEscapes) {
+ const char* context_data[][2] = {{"", ""},
+ {"'use strict';", ""},
+ {NULL, NULL}};
+ const char* data[] = {
+ "var foob\\u123r = 0;",
+ "var \\u123roo = 0;",
+ "\"foob\\u123rr\"",
+ "/regex/g\\u123r",
+ NULL};
+ RunParserSyncTest(context_data, data, kError);
+}