Fixed overflow bug in parsing of regexp repetitions.
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f7f4cb1c33
commit
0070e8c572
@ -3938,6 +3938,9 @@ bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
|
|||||||
// { DecimalDigits }
|
// { DecimalDigits }
|
||||||
// { DecimalDigits , }
|
// { DecimalDigits , }
|
||||||
// { 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) {
|
bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
|
||||||
ASSERT_EQ(current(), '{');
|
ASSERT_EQ(current(), '{');
|
||||||
int start = position();
|
int start = position();
|
||||||
@ -3948,7 +3951,14 @@ bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
while (IsDecimalDigit(current())) {
|
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();
|
Advance();
|
||||||
}
|
}
|
||||||
int max = 0;
|
int max = 0;
|
||||||
@ -3962,7 +3972,13 @@ bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
|
|||||||
Advance();
|
Advance();
|
||||||
} else {
|
} else {
|
||||||
while (IsDecimalDigit(current())) {
|
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();
|
Advance();
|
||||||
}
|
}
|
||||||
if (current() != '}') {
|
if (current() != '}') {
|
||||||
|
@ -2110,7 +2110,8 @@ assertEquals(null, res[255].exec("ab\ncd", 463));
|
|||||||
assertEquals(null, res[255].exec("AbCd", 464));
|
assertEquals(null, res[255].exec("AbCd", 464));
|
||||||
assertEquals(null, res[255].exec("** Failers", 465));
|
assertEquals(null, res[255].exec("** Failers", 465));
|
||||||
assertEquals(null, res[255].exec("abcd", 466));
|
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", 468));
|
||||||
assertEquals(null, res[255].exec("abcdefghijklAkB", 469));
|
assertEquals(null, res[255].exec("abcdefghijklAkB", 469));
|
||||||
assertEquals(null, res[255].exec("abcdefghijklAkB", 470));
|
assertEquals(null, res[255].exec("abcdefghijklAkB", 470));
|
||||||
|
@ -304,11 +304,44 @@ for (var i = 0; i < 128; i++) {
|
|||||||
assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
|
assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
|
||||||
|
|
||||||
// Check decimal escapes doesn't overflow.
|
// Check decimal escapes doesn't overflow.
|
||||||
|
// (Note: \214 is interpreted as octal).
|
||||||
assertEquals(/\2147483648/.exec("\x8c7483648"),
|
assertEquals(/\2147483648/.exec("\x8c7483648"),
|
||||||
["\x8c7483648"],
|
["\x8c7483648"],
|
||||||
"Overflow decimal escape");
|
"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.
|
// Check that we don't read past the end of the string.
|
||||||
assertFalse(/f/.test('b'));
|
assertFalse(/f/.test('b'));
|
||||||
assertFalse(/[abc]f/.test('x'));
|
assertFalse(/[abc]f/.test('x'));
|
||||||
|
Loading…
Reference in New Issue
Block a user