// { DecimalDigits }
// { DecimalDigits , }
// { DecimalDigits , DecimalDigits }
+//
+// Returns true if parsing succeeds, and set the min_out and max_out
+// values. Values are truncated to RegExpTree::kInfinity if they overflow.
bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
ASSERT_EQ(current(), '{');
int start = position();
return false;
}
while (IsDecimalDigit(current())) {
- min = 10 * min + (current() - '0');
+ int next = current() - '0';
+ if (min > (RegExpTree::kInfinity - next) / 10) {
+ // Overflow. Skip past remaining decimal digits and return -1.
+ do { Advance(); } while (IsDecimalDigit(current()));
+ min = RegExpTree::kInfinity;
+ break;
+ }
+ min = 10 * min + next;
Advance();
}
int max = 0;
Advance();
} else {
while (IsDecimalDigit(current())) {
- max = 10 * max + (current() - '0');
+ int next = current() - '0';
+ if (max > (RegExpTree::kInfinity - next) / 10) {
+ do { Advance(); } while (IsDecimalDigit(current()));
+ max = RegExpTree::kInfinity;;
+ break;
+ }
+ max = 10 * max + next;
Advance();
}
if (current() != '}') {
assertEquals(null, res[255].exec("AbCd", 464));
assertEquals(null, res[255].exec("** Failers", 465));
assertEquals(null, res[255].exec("abcd", 466));
-assertThrows("var re = /(){2,4294967295}/;", 467);
+// We are compatible with JSC, and don't throw an exception in this case.
+// assertThrows("var re = /(){2,4294967295}/;", 467);
assertEquals(null, res[255].exec("abcdefghijklAkB", 468));
assertEquals(null, res[255].exec("abcdefghijklAkB", 469));
assertEquals(null, res[255].exec("abcdefghijklAkB", 470));
assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
// Check decimal escapes doesn't overflow.
-
+// (Note: \214 is interpreted as octal).
assertEquals(/\2147483648/.exec("\x8c7483648"),
["\x8c7483648"],
"Overflow decimal escape");
+
+// Check numbers in quantifiers doesn't overflow and doesn't throw on
+// too large numbers.
+assertFalse(/a{111111111111111111111111111111111111111111111}/.test('b'),
+ "overlarge1");
+assertFalse(/a{999999999999999999999999999999999999999999999}/.test('b'),
+ "overlarge2");
+assertFalse(/a{1,111111111111111111111111111111111111111111111}/.test('b'),
+ "overlarge3");
+assertFalse(/a{1,999999999999999999999999999999999999999999999}/.test('b'),
+ "overlarge4");
+assertFalse(/a{2147483648}/.test('b'),
+ "overlarge5");
+assertFalse(/a{21474836471}/.test('b'),
+ "overlarge6");
+assertFalse(/a{1,2147483648}/.test('b'),
+ "overlarge7");
+assertFalse(/a{1,21474836471}/.test('b'),
+ "overlarge8");
+assertFalse(/a{2147483648,2147483648}/.test('b'),
+ "overlarge9");
+assertFalse(/a{21474836471,21474836471}/.test('b'),
+ "overlarge10");
+assertFalse(/a{2147483647}/.test('b'),
+ "overlarge11");
+assertFalse(/a{1,2147483647}/.test('b'),
+ "overlarge12");
+assertTrue(/a{1,2147483647}/.test('a'),
+ "overlarge13");
+assertFalse(/a{2147483647,2147483647}/.test('a'),
+ "overlarge14");
+
+
// Check that we don't read past the end of the string.
assertFalse(/f/.test('b'));
assertFalse(/[abc]f/.test('x'));