diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 79f5d89dd47e..4f02c42333be 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -171,6 +171,15 @@ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj, return CreateRegExpMatchResult(cx, input, matches, rval); } +static bool +CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags) +{ + CompileOptions options(cx); + frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); + return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern, + flags & UnicodeFlag); +} + enum RegExpSharedUse { UseRegExpShared, DontUseRegExpShared @@ -222,13 +231,8 @@ RegExpInitializeIgnoringLastIndex(JSContext* cx, Handle obj, obj->setShared(*re); } else { /* Steps 7-8. */ - CompileOptions options(cx); - frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); - if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern, - flags & UnicodeFlag)) - { + if (!CheckPatternSyntax(cx, pattern, flags)) return false; - } /* Steps 9-12. */ obj->initIgnoringLastIndex(pattern, flags); @@ -419,10 +423,9 @@ js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) return false; sourceAtom = g->getSource(); - if (!args.hasDefined(1)) { - // Step 4.b. - flags = g->getFlags(); - } + // Step 4.b. + // Get original flags in all cases, to compare with passed flags. + flags = g->getFlags(); } // Step 7. @@ -437,12 +440,22 @@ js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) // Step 8. if (args.hasDefined(1)) { // Step 4.c / 21.2.3.2.2 RegExpInitialize step 4. - flags = RegExpFlag(0); + RegExpFlag flagsArg = RegExpFlag(0); RootedString flagStr(cx, ToString(cx, args[1])); if (!flagStr) return false; - if (!ParseRegExpFlags(cx, flagStr, &flags)) + if (!ParseRegExpFlags(cx, flagStr, &flagsArg)) return false; + + if (!(flags & UnicodeFlag) && flagsArg & UnicodeFlag) { + // Have to check syntax again when adding 'u' flag. + + // ES 2017 draft rev 9b49a888e9dfe2667008a01b2754c3662059ae56 + // 21.2.3.2.2 step 7. + if (!CheckPatternSyntax(cx, sourceAtom, flagsArg)) + return false; + } + flags = flagsArg; } regexp->initAndZeroLastIndex(sourceAtom, flags, cx); diff --git a/js/src/tests/ecma_6/RegExp/constructor-regexp-unicode.js b/js/src/tests/ecma_6/RegExp/constructor-regexp-unicode.js new file mode 100644 index 000000000000..b348c34a0152 --- /dev/null +++ b/js/src/tests/ecma_6/RegExp/constructor-regexp-unicode.js @@ -0,0 +1,9 @@ +var BUGNUMBER = 1274393; +var summary = "RegExp constructor should check the pattern syntax again when adding unicode flag."; + +print(BUGNUMBER + ": " + summary); + +assertThrowsInstanceOf(() => RegExp(/\-/, "u"), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true);