Commit d8a12316 authored by lrn@chromium.org's avatar lrn@chromium.org

Make regexp flag parsing stricter.

BUG=v8:1628
TEST=mjsunit/regress/regress-219

Review URL: http://codereview.chromium.org/7624045

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8973 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dc917453
...@@ -207,7 +207,7 @@ function FormatMessage(message) { ...@@ -207,7 +207,7 @@ function FormatMessage(message) {
stack_overflow: ["Maximum call stack size exceeded"], stack_overflow: ["Maximum call stack size exceeded"],
// SyntaxError // SyntaxError
unable_to_parse: ["Parse error"], unable_to_parse: ["Parse error"],
duplicate_regexp_flag: ["Duplicate RegExp flag ", "%0"], invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"], invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
illegal_break: ["Illegal break statement"], illegal_break: ["Illegal break statement"],
illegal_continue: ["Illegal continue statement"], illegal_continue: ["Illegal continue statement"],
......
...@@ -50,24 +50,29 @@ function DoConstructRegExp(object, pattern, flags) { ...@@ -50,24 +50,29 @@ function DoConstructRegExp(object, pattern, flags) {
var global = false; var global = false;
var ignoreCase = false; var ignoreCase = false;
var multiline = false; var multiline = false;
for (var i = 0; i < flags.length; i++) { for (var i = 0; i < flags.length; i++) {
var c = %_CallFunction(flags, i, StringCharAt); var c = %_CallFunction(flags, i, StringCharAt);
switch (c) { switch (c) {
case 'g': case 'g':
// Allow duplicate flags to be consistent with JSC and others. if (global) {
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
}
global = true; global = true;
break; break;
case 'i': case 'i':
if (ignoreCase) {
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
}
ignoreCase = true; ignoreCase = true;
break; break;
case 'm': case 'm':
if (multiline) {
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
}
multiline = true; multiline = true;
break; break;
default: default:
// Ignore flags that have no meaning to be consistent with throw MakeSyntaxError("invalid_regexp_flags", [flags]);
// JSC.
break;
} }
} }
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
// We should now allow duplicates of flags. // We should now allow duplicates of flags.
// (See http://code.google.com/p/v8/issues/detail?id=219) // (See http://code.google.com/p/v8/issues/detail?id=219)
// This has been reversed by issue 1628, since other browsers have also
// tightened their syntax.
// (See http://code.google.com/p/v8/issues/detail?id=1628)
// Base tests: we recognize the basic flags // Base tests: we recognize the basic flags
function assertFlags(re, global, multiline, ignoreCase) { function assertFlags(re, global, multiline, ignoreCase) {
...@@ -53,124 +57,92 @@ assertFlags(re, true, true, true) ...@@ -53,124 +57,92 @@ assertFlags(re, true, true, true)
// Double i's // Double i's
re = /a/ii; assertThrows("/a/ii");
assertFlags(re, false, false, true)
re = /a/gii;
assertFlags(re, true, false, true)
re = /a/igi; assertThrows("/a/gii");
assertFlags(re, true, false, true)
re = /a/iig; assertThrows("/a/igi");
assertFlags(re, true, false, true)
re = /a/gimi; assertThrows("/a/iig");
assertFlags(re, true, true, true)
re = /a/giim; assertThrows("/a/gimi");
assertFlags(re, true, true, true)
re = /a/igim; assertThrows("/a/giim");
assertFlags(re, true, true, true)
assertThrows("/a/igim");
re = RegExp("a", "ii"); assertThrows(function(){ return RegExp("a", "ii"); })
assertFlags(re, false, false, true)
re = RegExp("a", "gii"); assertThrows(function(){ return RegExp("a", "gii"); })
assertFlags(re, true, false, true)
re = RegExp("a", "igi"); assertThrows(function(){ return RegExp("a", "igi"); })
assertFlags(re, true, false, true)
re = RegExp("a", "iig"); assertThrows(function(){ return RegExp("a", "iig"); })
assertFlags(re, true, false, true)
re = RegExp("a", "gimi"); assertThrows(function(){ return RegExp("a", "gimi"); })
assertFlags(re, true, true, true)
re = RegExp("a", "giim"); assertThrows(function(){ return RegExp("a", "giim"); })
assertFlags(re, true, true, true)
re = RegExp("a", "igim"); assertThrows(function(){ return RegExp("a", "igim"); })
assertFlags(re, true, true, true)
// Tripple i's // Tripple i's
re = /a/iii; assertThrows("/a/iii");
assertFlags(re, false, false, true)
re = /a/giii; assertThrows("/a/giii");
assertFlags(re, true, false, true)
re = /a/igii; assertThrows("/a/igii");
assertFlags(re, true, false, true)
re = /a/iigi; assertThrows("/a/iigi");
assertFlags(re, true, false, true)
re = /a/iiig; assertThrows("/a/iiig");
assertFlags(re, true, false, true)
re = /a/miiig;
assertFlags(re, true, true, true)
assertThrows("/a/miiig");
re = RegExp("a", "iii"); assertThrows(function(){ return RegExp("a", "iii"); })
assertFlags(re, false, false, true)
re = RegExp("a", "giii"); assertThrows(function(){ return RegExp("a", "giii"); })
assertFlags(re, true, false, true)
re = RegExp("a", "igii"); assertThrows(function(){ return RegExp("a", "igii"); })
assertFlags(re, true, false, true)
re = RegExp("a", "iigi"); assertThrows(function(){ return RegExp("a", "iigi"); })
assertFlags(re, true, false, true)
re = RegExp("a", "iiig"); assertThrows(function(){ return RegExp("a", "iiig"); })
assertFlags(re, true, false, true)
re = RegExp("a", "miiig"); assertThrows(function(){ return RegExp("a", "miiig"); })
assertFlags(re, true, true, true)
// Illegal flags - flags late in string. // Illegal flags - valid flags late in string.
re = /a/arglebargleglopglyf; assertThrows("/a/arglebargleglopglyf");
assertFlags(re, true, false, false)
re = /a/arglebargleglopglif; assertThrows("/a/arglebargleglopglif");
assertFlags(re, true, false, true)
re = /a/arglebargleglopglym; assertThrows("/a/arglebargleglopglym");
assertFlags(re, true, true, false)
re = /a/arglebargleglopglim; assertThrows("/a/arglebargleglopglim");
assertFlags(re, true, true, true)
// Case of flags still matters. // Case of flags still matters.
re = /a/gmi; var re = /a/gmi;
assertFlags(re, true, true, true) assertFlags(re, true, true, true)
re = /a/Gmi; assertThrows("/a/Gmi");
assertFlags(re, false, true, true)
re = /a/gMi; assertThrows("/a/gMi");
assertFlags(re, true, false, true)
re = /a/gmI; assertThrows("/a/gmI");
assertFlags(re, true, true, false)
re = /a/GMi; assertThrows("/a/GMi");
assertFlags(re, false, false, true)
re = /a/GmI; assertThrows("/a/GmI");
assertFlags(re, false, true, false)
re = /a/gMI; assertThrows("/a/gMI");
assertFlags(re, true, false, false)
re = /a/GMI; assertThrows("/a/GMI");
assertFlags(re, false, false, false)
// Unicode escape sequences are not interpreted.
assertThrows("/a/\\u0067");
assertThrows("/a/\\u0069");
assertThrows("/a/\\u006d");
assertThrows("/a/\\u006D");
...@@ -25,34 +25,29 @@ ...@@ -25,34 +25,29 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function testFlags(flagstring, global, ignoreCase, multiline) { // In Issue 87, we allowed unicode escape sequences in RegExp flags.
var text = "/x/"+flagstring; // However, according to ES5, they should not be interpreted, but passed
var re = eval(text); // verbatim to the RegExp constructor.
assertEquals(global, re.global, text + ".global"); // (On top of that, the original test was bugged and never tested anything).
assertEquals(ignoreCase, re.ignoreCase, text + ".ignoreCase"); // The behavior was changed in r8969 to not interpret escapes, but this
assertEquals(multiline, re.multiline, text + ".multiline"); // test didn't test that, and only failed when making invalid flag characters
} // an error too.
testFlags("", false, false, false); assertThrows("/x/\\u0067");
assertThrows("/x/\\u0069");
testFlags("\u0067", true, false, false); assertThrows("/x/\\u006d");
testFlags("\u0069", false, true, false) assertThrows("/x/\\u0067i");
assertThrows("/x/\\u0069m");
testFlags("\u006d", false, false, true); assertThrows("/x/\\u006dg");
testFlags("\u0068", false, false, false); assertThrows("/x/m\\u0067");
assertThrows("/x/g\\u0069");
testFlags("\u0020", false, false, false); assertThrows("/x/i\\u006d");
assertThrows("/x/m\\u0067i");
testFlags("\u0067g", true, false, false); assertThrows("/x/g\\u0069m");
assertThrows("/x/i\\u006dg");
testFlags("g\u0067", true, false, false);
assertThrows("/x/\\u0068");
testFlags("abc\u0067efg", true, false, false); assertThrows("/x/\\u0020");
testFlags("i\u0067", true, true, false);
testFlags("\u0067i", true, true, false);
...@@ -246,9 +246,8 @@ ecma_3/Number/15.7.4.7-1: FAIL_OK ...@@ -246,9 +246,8 @@ ecma_3/Number/15.7.4.7-1: FAIL_OK
ecma_3/Number/15.7.4.6-1: FAIL_OK ecma_3/Number/15.7.4.6-1: FAIL_OK
#:=== RegExp:=== #:=== RegExp:===
# To be compatible with JSC we silently ignore flags that do not make # We don't match the syntax error message of Mozilla for invalid
# sense. These tests expects us to throw exceptions. # RegExp flags.
ecma_3/RegExp/regress-57631: FAIL_OK
ecma_3/RegExp/15.10.4.1-6: FAIL_OK ecma_3/RegExp/15.10.4.1-6: FAIL_OK
# PCRE doesn't allow subpattern nesting deeper than 200, this tests # PCRE doesn't allow subpattern nesting deeper than 200, this tests
......
...@@ -56,15 +56,6 @@ S15.10.6.3_A1_T16: FAIL_OK ...@@ -56,15 +56,6 @@ S15.10.6.3_A1_T16: FAIL_OK
# errors, for compatibility. # errors, for compatibility.
S15.10.2.11_A1_T2: FAIL S15.10.2.11_A1_T2: FAIL
S15.10.2.11_A1_T3: FAIL S15.10.2.11_A1_T3: FAIL
S15.10.4.1_A5_T1: FAIL
S15.10.4.1_A5_T2: FAIL
S15.10.4.1_A5_T3: FAIL
S15.10.4.1_A5_T4: FAIL
S15.10.4.1_A5_T5: FAIL
S15.10.4.1_A5_T6: FAIL
S15.10.4.1_A5_T7: FAIL
S15.10.4.1_A5_T8: FAIL
S15.10.4.1_A5_T9: FAIL
# We are more lenient in which string character escapes we allow than # We are more lenient in which string character escapes we allow than
# the spec (7.8.4 p. 19) wants us to be. This is for compatibility. # the spec (7.8.4 p. 19) wants us to be. This is for compatibility.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment