⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 242699 in webkit


Ignore:
Timestamp:
Mar 10, 2019, 11:20:53 PM (7 years ago)
Author:
Ross Kirsling
Message:

Invalid flags in a RegExp literal should be an early SyntaxError
https://bugs.webkit.org/show_bug.cgi?id=195514

Reviewed by Darin Adler.

JSTests:

  • test262/expectations.yaml:

Mark 4 test cases as passing.

  • stress/regexp-syntax-error-invalid-flags.js:
  • stress/regress-161995.js: Removed.

Update existing test, merging in an older test for the same behavior.

Source/JavaScriptCore:

Currently we're throwing a *runtime* SyntaxError; this should occur at parse time.

12.2.8.1 Static Semantics: Early Errors

PrimaryExpression : RegularExpressionLiteral

  • It is a Syntax Error if BodyText of RegularExpressionLiteral cannot be recognized using the goal symbol Pattern of the ECMAScript RegExp grammar specified in 21.2.1.
  • It is a Syntax Error if FlagText of RegularExpressionLiteral contains any code points other than "g", "i", "m", "s", "u", or "y", or if it contains the same code point more than once.

In fixing this, let's also move flag handling from runtime/ to yarr/.

  • yarr/YarrSyntaxChecker.cpp:

(JSC::Yarr::checkSyntax):
Check flags before checking pattern.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecompiler/NodesCodegen.cpp:

(JSC::RegExpNode::emitBytecode):

  • inspector/ContentSearchUtilities.cpp:

(Inspector::ContentSearchUtilities::findMagicComment):

  • runtime/CachedTypes.cpp:
  • runtime/RegExp.cpp:

(JSC::RegExp::RegExp):
(JSC::RegExp::createWithoutCaching):
(JSC::RegExp::create):
(JSC::regExpFlags): Deleted.

  • runtime/RegExp.h:
  • runtime/RegExpCache.cpp:

(JSC::RegExpCache::lookupOrCreate):
(JSC::RegExpCache::ensureEmptyRegExpSlow):

  • runtime/RegExpCache.h:
  • runtime/RegExpConstructor.cpp:

(JSC::toFlags):
(JSC::regExpCreate):
(JSC::constructRegExp):

  • runtime/RegExpKey.h:

(JSC::RegExpKey::RegExpKey):
(WTF::HashTraits<JSC::RegExpKey>::constructDeletedValue):
(WTF::HashTraits<JSC::RegExpKey>::isDeletedValue):
(): Deleted.

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncCompile):

  • testRegExp.cpp:

(parseRegExpLine):

  • yarr/RegularExpression.cpp:

(JSC::Yarr::RegularExpression::Private::compile):

  • yarr/YarrFlags.cpp: Added.

(JSC::Yarr::parseFlags):

  • yarr/YarrFlags.h: Added.
  • yarr/YarrInterpreter.h:

(JSC::Yarr::BytecodePattern::ignoreCase const):
(JSC::Yarr::BytecodePattern::multiline const):
(JSC::Yarr::BytecodePattern::sticky const):
(JSC::Yarr::BytecodePattern::unicode const):
(JSC::Yarr::BytecodePattern::dotAll const):

  • yarr/YarrPattern.cpp:

(JSC::Yarr::YarrPattern::compile):
(JSC::Yarr::YarrPattern::YarrPattern):
(JSC::Yarr::YarrPattern::dumpPattern):

  • yarr/YarrPattern.h:

(JSC::Yarr::YarrPattern::global const):
(JSC::Yarr::YarrPattern::ignoreCase const):
(JSC::Yarr::YarrPattern::multiline const):
(JSC::Yarr::YarrPattern::sticky const):
(JSC::Yarr::YarrPattern::unicode const):
(JSC::Yarr::YarrPattern::dotAll const):
Move flag handling to Yarr and modernize API.

Source/WebCore:

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneDeserializer::readTerminal):
Consume YarrFlags.

Location:
trunk
Files:
2 added
1 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r242667 r242699  
     12019-03-10  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Invalid flags in a RegExp literal should be an early SyntaxError
     4        https://bugs.webkit.org/show_bug.cgi?id=195514
     5
     6        Reviewed by Darin Adler.
     7
     8        * test262/expectations.yaml:
     9        Mark 4 test cases as passing.
     10
     11        * stress/regexp-syntax-error-invalid-flags.js:
     12        * stress/regress-161995.js: Removed.
     13        Update existing test, merging in an older test for the same behavior.
     14
    1152019-03-08  Mark Lam  <mark.lam@apple.com>
    216
  • trunk/JSTests/stress/regexp-syntax-error-invalid-flags.js

    r226209 r242699  
    1 function shouldThrow(func, errorMessage) {
    2     var errorThrown = false;
    3     var error = null;
     1function shouldThrowSyntaxError(script) {
     2    let error;
    43    try {
    5         func();
     4        eval(script);
    65    } catch (e) {
    7         errorThrown = true;
    86        error = e;
    97    }
    10     if (!errorThrown)
     8
     9    if (!error)
    1110        throw new Error('not thrown');
    12     if (String(error) !== errorMessage)
     11    if (String(error) !== 'SyntaxError: Invalid regular expression: invalid flags')
    1312        throw new Error(`bad error: ${String(error)}`);
    1413}
    1514
    16 function test()
    17 {
    18     return /Hello/cocoa;
    19 }
    20 noInline(test);
    21 
    22 for (var i = 0; i < 1e4; ++i)
    23     shouldThrow(test, `SyntaxError: Invalid regular expression: invalid flags`);
     15shouldThrowSyntaxError('/Hello/cocoa');
     16shouldThrowSyntaxError('/a/Z');
     17shouldThrowSyntaxError('/./ii');
  • trunk/JSTests/test262/expectations.yaml

    r240754 r242699  
    23972397  default: 'SyntaxError: No identifiers allowed directly after numeric literal'
    23982398  strict mode: 'SyntaxError: No identifiers allowed directly after numeric literal'
    2399 test/language/literals/regexp/early-err-bad-flag.js:
    2400   default: 'Test262: This statement should not be evaluated.'
    2401   strict mode: 'Test262: This statement should not be evaluated.'
    2402 test/language/literals/regexp/early-err-dup-flag.js:
    2403   default: 'Test262: This statement should not be evaluated.'
    2404   strict mode: 'Test262: This statement should not be evaluated.'
    24052399test/language/literals/regexp/named-groups/invalid-dangling-groupname-2-u.js:
    24062400  default: 'Test262: This statement should not be evaluated.'
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r242123 r242699  
    10011001    yarr/Yarr.h
    10021002    yarr/YarrErrorCode.h
     1003    yarr/YarrFlags.h
    10031004    yarr/YarrInterpreter.h
    10041005    yarr/YarrJIT.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r242674 r242699  
     12019-03-10  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Invalid flags in a RegExp literal should be an early SyntaxError
     4        https://bugs.webkit.org/show_bug.cgi?id=195514
     5
     6        Reviewed by Darin Adler.
     7
     8        Currently we're throwing a *runtime* SyntaxError; this should occur at parse time.
     9
     10          12.2.8.1 Static Semantics: Early Errors
     11            PrimaryExpression : RegularExpressionLiteral
     12              - It is a Syntax Error if BodyText of RegularExpressionLiteral cannot be recognized
     13                using the goal symbol Pattern of the ECMAScript RegExp grammar specified in 21.2.1.
     14              - It is a Syntax Error if FlagText of RegularExpressionLiteral contains any code points
     15                other than "g", "i", "m",  "s", "u", or "y", or if it contains the same code point more than once.
     16
     17        In fixing this, let's also move flag handling from runtime/ to yarr/.
     18
     19        * yarr/YarrSyntaxChecker.cpp:
     20        (JSC::Yarr::checkSyntax):
     21        Check flags before checking pattern.
     22
     23        * CMakeLists.txt:
     24        * JavaScriptCore.xcodeproj/project.pbxproj:
     25        * Sources.txt:
     26        * bytecompiler/NodesCodegen.cpp:
     27        (JSC::RegExpNode::emitBytecode):
     28        * inspector/ContentSearchUtilities.cpp:
     29        (Inspector::ContentSearchUtilities::findMagicComment):
     30        * runtime/CachedTypes.cpp:
     31        * runtime/RegExp.cpp:
     32        (JSC::RegExp::RegExp):
     33        (JSC::RegExp::createWithoutCaching):
     34        (JSC::RegExp::create):
     35        (JSC::regExpFlags): Deleted.
     36        * runtime/RegExp.h:
     37        * runtime/RegExpCache.cpp:
     38        (JSC::RegExpCache::lookupOrCreate):
     39        (JSC::RegExpCache::ensureEmptyRegExpSlow):
     40        * runtime/RegExpCache.h:
     41        * runtime/RegExpConstructor.cpp:
     42        (JSC::toFlags):
     43        (JSC::regExpCreate):
     44        (JSC::constructRegExp):
     45        * runtime/RegExpKey.h:
     46        (JSC::RegExpKey::RegExpKey):
     47        (WTF::HashTraits<JSC::RegExpKey>::constructDeletedValue):
     48        (WTF::HashTraits<JSC::RegExpKey>::isDeletedValue):
     49        (): Deleted.
     50        * runtime/RegExpPrototype.cpp:
     51        (JSC::regExpProtoFuncCompile):
     52        * testRegExp.cpp:
     53        (parseRegExpLine):
     54        * yarr/RegularExpression.cpp:
     55        (JSC::Yarr::RegularExpression::Private::compile):
     56        * yarr/YarrFlags.cpp: Added.
     57        (JSC::Yarr::parseFlags):
     58        * yarr/YarrFlags.h: Added.
     59        * yarr/YarrInterpreter.h:
     60        (JSC::Yarr::BytecodePattern::ignoreCase const):
     61        (JSC::Yarr::BytecodePattern::multiline const):
     62        (JSC::Yarr::BytecodePattern::sticky const):
     63        (JSC::Yarr::BytecodePattern::unicode const):
     64        (JSC::Yarr::BytecodePattern::dotAll const):
     65        * yarr/YarrPattern.cpp:
     66        (JSC::Yarr::YarrPattern::compile):
     67        (JSC::Yarr::YarrPattern::YarrPattern):
     68        (JSC::Yarr::YarrPattern::dumpPattern):
     69        * yarr/YarrPattern.h:
     70        (JSC::Yarr::YarrPattern::global const):
     71        (JSC::Yarr::YarrPattern::ignoreCase const):
     72        (JSC::Yarr::YarrPattern::multiline const):
     73        (JSC::Yarr::YarrPattern::sticky const):
     74        (JSC::Yarr::YarrPattern::unicode const):
     75        (JSC::Yarr::YarrPattern::dotAll const):
     76        Move flag handling to Yarr and modernize API.
     77
    1782019-03-09  Robin Morisset  <rmorisset@apple.com>
    279
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r242252 r242699  
    13401340                A1D792FF1B43864B004516F5 /* IntlNumberFormatConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792F91B43864B004516F5 /* IntlNumberFormatConstructor.h */; };
    13411341                A1D793011B43864B004516F5 /* IntlNumberFormatPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792FB1B43864B004516F5 /* IntlNumberFormatPrototype.h */; };
     1342                A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FF9BC52234746600B1A9AB /* YarrFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13421343                A503FA1A188E0FB000110F14 /* JavaScriptCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA14188E0FAF00110F14 /* JavaScriptCallFrame.h */; };
    13431344                A503FA1E188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA18188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h */; };
     
    40874088                A1FE1EB01C2C537E00A289FF /* DatePrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = DatePrototype.js; sourceTree = "<group>"; };
    40884089                A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmContextInlines.h; sourceTree = "<group>"; };
     4090                A3FF9BC52234746600B1A9AB /* YarrFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrFlags.h; path = yarr/YarrFlags.h; sourceTree = "<group>"; };
     4091                A3FF9BC62234746600B1A9AB /* YarrFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrFlags.cpp; path = yarr/YarrFlags.cpp; sourceTree = "<group>"; };
    40894092                A503FA13188E0FAF00110F14 /* JavaScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptCallFrame.cpp; sourceTree = "<group>"; };
    40904093                A503FA14188E0FAF00110F14 /* JavaScriptCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCallFrame.h; sourceTree = "<group>"; };
     
    73047307                                E3282BB91FE930A300EDAF71 /* YarrErrorCode.cpp */,
    73057308                                E3282BBA1FE930A400EDAF71 /* YarrErrorCode.h */,
     7309                                A3FF9BC62234746600B1A9AB /* YarrFlags.cpp */,
     7310                                A3FF9BC52234746600B1A9AB /* YarrFlags.h */,
    73067311                                86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */,
    73077312                                86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */,
     
    98979902                                451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
    98989903                                E3282BBB1FE930AF00EDAF71 /* YarrErrorCode.h in Headers */,
     9904                                A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */,
    98999905                                86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
    99009906                                86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r242123 r242699  
    10461046yarr/YarrDisassembler.cpp
    10471047yarr/YarrErrorCode.cpp
     1048yarr/YarrFlags.cpp
    10481049yarr/YarrInterpreter.cpp
    10491050yarr/YarrJIT.cpp
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r242591 r242699  
    4242#include "Parser.h"
    4343#include "StackAlignment.h"
     44#include "YarrFlags.h"
    4445#include <wtf/Assertions.h>
    4546#include <wtf/Threading.h>
     
    142143    if (dst == generator.ignoredResult())
    143144        return nullptr;
    144     RegExp* regExp = RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string()));
     145
     146    auto flags = Yarr::parseFlags(m_flags.string());
     147    ASSERT(flags.hasValue());
     148    RegExp* regExp = RegExp::create(*generator.vm(), m_pattern.string(), flags.value());
    145149    if (regExp->isValid())
    146150        return generator.emitNewRegExp(generator.finalDestination(dst), regExp);
     151
    147152    const char* messageCharacters = regExp->errorMessage();
    148153    const Identifier& message = generator.parserArena().identifierArena().makeIdentifier(generator.vm(), bitwise_cast<const LChar*>(messageCharacters), strlen(messageCharacters));
  • trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp

    r233122 r242699  
    3232#include "RegularExpression.h"
    3333#include "Yarr.h"
     34#include "YarrFlags.h"
    3435#include "YarrInterpreter.h"
    3536#include <wtf/BumpPointerAllocator.h>
     
    168169
    169170    JSC::Yarr::ErrorCode error { JSC::Yarr::ErrorCode::NoError };
    170     YarrPattern pattern(patternString, JSC::RegExpFlags::FlagMultiline, error);
     171    YarrPattern pattern(patternString, JSC::Yarr::Flags::Multiline, error);
    171172    ASSERT(!hasError(error));
    172173    BumpPointerAllocator regexAllocator;
  • trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp

    r242605 r242699  
    2929#include "BytecodeCacheVersion.h"
    3030#include "BytecodeLivenessAnalysis.h"
    31 #include "JSCast.h"
    3231#include "JSImmutableButterfly.h"
    3332#include "JSTemplateObjectDescriptor.h"
     
    4140#include "UnlinkedProgramCodeBlock.h"
    4241#include <wtf/FastMalloc.h>
    43 #include <wtf/Forward.h>
    4442#include <wtf/Optional.h>
    4543#include <wtf/UUID.h>
     
    4745
    4846namespace JSC {
     47
     48namespace Yarr {
     49enum class Flags : uint8_t;
     50}
    4951
    5052template <typename T, typename = void>
     
    11121114private:
    11131115    CachedString m_patternString;
    1114     RegExpFlags m_flags;
     1116    OptionSet<Yarr::Flags> m_flags;
    11151117};
    11161118
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r237763 r242699  
    2929#include "RegExpCache.h"
    3030#include "RegExpInlines.h"
    31 #include "Yarr.h"
    3231#include "YarrJIT.h"
    3332#include <wtf/Assertions.h>
     
    3635
    3736const ClassInfo RegExp::s_info = { "RegExp", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(RegExp) };
    38 
    39 RegExpFlags regExpFlags(const String& string)
    40 {
    41     RegExpFlags flags = NoFlags;
    42 
    43     for (unsigned i = 0; i < string.length(); ++i) {
    44         switch (string[i]) {
    45         case 'g':
    46             if (flags & FlagGlobal)
    47                 return InvalidFlags;
    48             flags = static_cast<RegExpFlags>(flags | FlagGlobal);
    49             break;
    50 
    51         case 'i':
    52             if (flags & FlagIgnoreCase)
    53                 return InvalidFlags;
    54             flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
    55             break;
    56 
    57         case 'm':
    58             if (flags & FlagMultiline)
    59                 return InvalidFlags;
    60             flags = static_cast<RegExpFlags>(flags | FlagMultiline);
    61             break;
    62 
    63         case 's':
    64             if (flags & FlagDotAll)
    65                 return InvalidFlags;
    66             flags = static_cast<RegExpFlags>(flags | FlagDotAll);
    67             break;
    68            
    69         case 'u':
    70             if (flags & FlagUnicode)
    71                 return InvalidFlags;
    72             flags = static_cast<RegExpFlags>(flags | FlagUnicode);
    73             break;
    74                
    75         case 'y':
    76             if (flags & FlagSticky)
    77                 return InvalidFlags;
    78             flags = static_cast<RegExpFlags>(flags | FlagSticky);
    79             break;
    80 
    81         default:
    82             return InvalidFlags;
    83         }
    84     }
    85 
    86     return flags;
    87 }
    8837
    8938#if REGEXP_FUNC_TEST_DATA_GEN
     
    211160#endif
    212161
    213 RegExp::RegExp(VM& vm, const String& patternString, RegExpFlags flags)
     162RegExp::RegExp(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
    214163    : JSCell(vm, vm.regExpStructure.get())
    215164    , m_patternString(patternString)
    216165    , m_flags(flags)
    217166{
     167    ASSERT(m_flags != Yarr::Flags::DeletedValue);
    218168}
    219169
     
    250200}
    251201
    252 RegExp* RegExp::createWithoutCaching(VM& vm, const String& patternString, RegExpFlags flags)
     202RegExp* RegExp::createWithoutCaching(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
    253203{
    254204    RegExp* regExp = new (NotNull, allocateCell<RegExp>(vm.heap)) RegExp(vm, patternString, flags);
     
    257207}
    258208
    259 RegExp* RegExp::create(VM& vm, const String& patternString, RegExpFlags flags)
     209RegExp* RegExp::create(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
    260210{
    261211    return vm.regExpCache()->lookupOrCreate(patternString, flags);
  • trunk/Source/JavaScriptCore/runtime/RegExp.h

    r240255 r242699  
    3939class VM;
    4040
    41 JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
    42 
    4341class RegExp final : public JSCell {
    4442    friend class CachedRegExp;
     
    4846    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
    4947
    50     JS_EXPORT_PRIVATE static RegExp* create(VM&, const String& pattern, RegExpFlags);
     48    JS_EXPORT_PRIVATE static RegExp* create(VM&, const String& pattern, OptionSet<Yarr::Flags>);
    5149    static const bool needsDestruction = true;
    5250    static void destroy(JSCell*);
     
    5452    JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);
    5553
    56     bool global() const { return m_flags & FlagGlobal; }
    57     bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
    58     bool multiline() const { return m_flags & FlagMultiline; }
    59     bool sticky() const { return m_flags & FlagSticky; }
     54    bool global() const { return m_flags.contains(Yarr::Flags::Global); }
     55    bool ignoreCase() const { return m_flags.contains(Yarr::Flags::IgnoreCase); }
     56    bool multiline() const { return m_flags.contains(Yarr::Flags::Multiline); }
     57    bool sticky() const { return m_flags.contains(Yarr::Flags::Sticky); }
    6058    bool globalOrSticky() const { return global() || sticky(); }
    61     bool unicode() const { return m_flags & FlagUnicode; }
    62     bool dotAll() const { return m_flags & FlagDotAll; }
     59    bool unicode() const { return m_flags.contains(Yarr::Flags::Unicode); }
     60    bool dotAll() const { return m_flags.contains(Yarr::Flags::DotAll); }
    6361
    6462    const String& pattern() const { return m_patternString; }
    6563
    66     bool isValid() const { return !Yarr::hasError(m_constructionErrorCode) && m_flags != InvalidFlags; }
     64    bool isValid() const { return !Yarr::hasError(m_constructionErrorCode); }
    6765    const char* errorMessage() const { return Yarr::errorMessage(m_constructionErrorCode); }
    6866    JSObject* errorToThrow(ExecState* exec) { return Yarr::errorToThrow(exec, m_constructionErrorCode); }
     
    137135private:
    138136    friend class RegExpCache;
    139     RegExp(VM&, const String&, RegExpFlags);
     137    RegExp(VM&, const String&, OptionSet<Yarr::Flags>);
    140138
    141     static RegExp* createWithoutCaching(VM&, const String&, RegExpFlags);
     139    static RegExp* createWithoutCaching(VM&, const String&, OptionSet<Yarr::Flags>);
    142140
    143141    enum RegExpState : uint8_t {
     
    162160    String m_patternString;
    163161    RegExpState m_state { NotCompiled };
    164     RegExpFlags m_flags;
     162    OptionSet<Yarr::Flags> m_flags;
    165163    ConcurrentJSLock m_lock;
    166164    Yarr::ErrorCode m_constructionErrorCode { Yarr::ErrorCode::NoError };
  • trunk/Source/JavaScriptCore/runtime/RegExpCache.cpp

    r241640 r242699  
    3636namespace JSC {
    3737
    38 RegExp* RegExpCache::lookupOrCreate(const String& patternString, RegExpFlags flags)
     38RegExp* RegExpCache::lookupOrCreate(const String& patternString, OptionSet<Yarr::Flags> flags)
    3939{
    4040    RegExpKey key(flags, patternString);
     
    5959RegExp* RegExpCache::ensureEmptyRegExpSlow(VM& vm)
    6060{
    61     RegExp* regExp = RegExp::create(vm, "", NoFlags);
     61    RegExp* regExp = RegExp::create(vm, "", { });
    6262    m_emptyRegExp.set(vm, regExp);
    6363    return regExp;
  • trunk/Source/JavaScriptCore/runtime/RegExpCache.h

    r241640 r242699  
    3737namespace JSC {
    3838
     39namespace Yarr {
     40enum class Flags : uint8_t;
     41}
     42
    3943class RegExpCache : private WeakHandleOwner {
    4044    WTF_MAKE_FAST_ALLOCATED;
     
    6468    RegExp* ensureEmptyRegExpSlow(VM&);
    6569
    66     RegExp* lookupOrCreate(const WTF::String& patternString, RegExpFlags);
     70    RegExp* lookupOrCreate(const WTF::String& patternString, OptionSet<Yarr::Flags>);
    6771    void addToStrongCache(RegExp*);
    6872    RegExpCacheMap m_weakCache; // Holds all regular expressions currently live.
  • trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp

    r242650 r242699  
    2525#include "Error.h"
    2626#include "GetterSetter.h"
    27 #include "JSCInlines.h"
    2827#include "RegExpGlobalDataInlines.h"
    2928#include "RegExpPrototype.h"
    3029#include "StructureInlines.h"
     30#include "YarrFlags.h"
    3131
    3232namespace JSC {
     
    178178}
    179179
    180 inline RegExpFlags toFlags(ExecState* exec, JSValue flags)
     180inline OptionSet<Yarr::Flags> toFlags(ExecState* exec, JSValue flags)
    181181{
    182182    VM& vm = exec->vm();
     
    184184
    185185    if (flags.isUndefined())
    186         return NoFlags;
    187     JSString* flagsString = flags.toStringOrNull(exec);
    188     EXCEPTION_ASSERT(!!scope.exception() == !flagsString);
    189     if (UNLIKELY(!flagsString))
    190         return InvalidFlags;
    191 
    192     RegExpFlags result = regExpFlags(flagsString->value(exec));
    193     RETURN_IF_EXCEPTION(scope, InvalidFlags);
    194     if (result == InvalidFlags)
     186        return { };
     187   
     188    auto result = Yarr::parseFlags(flags.toWTFString(exec));
     189    RETURN_IF_EXCEPTION(scope, { });
     190    if (!result) {
    195191        throwSyntaxError(exec, scope, "Invalid flags supplied to RegExp constructor."_s);
    196     return result;
     192        return { };
     193    }
     194
     195    return result.value();
    197196}
    198197
     
    205204    RETURN_IF_EXCEPTION(scope, nullptr);
    206205
    207     RegExpFlags flags = toFlags(exec, flagsArg);
    208     EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
    209     if (UNLIKELY(flags == InvalidFlags))
    210         return nullptr;
     206    auto flags = toFlags(exec, flagsArg);
     207    RETURN_IF_EXCEPTION(scope, nullptr);
    211208
    212209    RegExp* regExp = RegExp::create(vm, pattern, flags);
     
    247244
    248245        if (!flagsArg.isUndefined()) {
    249             RegExpFlags flags = toFlags(exec, flagsArg);
    250             EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
    251             if (flags == InvalidFlags)
    252                 return nullptr;
     246            auto flags = toFlags(exec, flagsArg);
     247            RETURN_IF_EXCEPTION(scope, nullptr);
     248
    253249            regExp = RegExp::create(vm, regExp->pattern(), flags);
    254 
    255250            if (UNLIKELY(!regExp->isValid())) {
    256251                throwException(exec, scope, regExp->errorToThrow(exec));
  • trunk/Source/JavaScriptCore/runtime/RegExpKey.h

    r233621 r242699  
    2828#pragma once
    2929
     30#include "YarrFlags.h"
     31#include <wtf/OptionSet.h>
    3032#include <wtf/text/StringHash.h>
    31 #include <wtf/text/WTFString.h>
    3233
    3334namespace JSC {
    3435
    35 enum RegExpFlags : int8_t {
    36     NoFlags = 0,
    37     FlagGlobal = 1,
    38     FlagIgnoreCase = 2,
    39     FlagMultiline = 4,
    40     FlagSticky = 8,
    41     FlagUnicode = 16,
    42     FlagDotAll = 32,
    43     InvalidFlags = 64,
    44     DeletedValueFlags = -1
    45 };
    46 
    4736struct RegExpKey {
    48     RegExpFlags flagsValue;
     37    OptionSet<Yarr::Flags> flagsValue;
    4938    RefPtr<StringImpl> pattern;
    5039
    5140    RegExpKey()
    52         : flagsValue(NoFlags)
    5341    {
    5442    }
    5543
    56     RegExpKey(RegExpFlags flags)
     44    RegExpKey(OptionSet<Yarr::Flags> flags)
    5745        : flagsValue(flags)
    5846    {
    5947    }
    6048
    61     RegExpKey(RegExpFlags flags, const String& pattern)
     49    RegExpKey(OptionSet<Yarr::Flags> flags, const String& pattern)
    6250        : flagsValue(flags)
    6351        , pattern(pattern.impl())
     
    6553    }
    6654
    67     RegExpKey(RegExpFlags flags, RefPtr<StringImpl>&& pattern)
     55    RegExpKey(OptionSet<Yarr::Flags> flags, RefPtr<StringImpl>&& pattern)
    6856        : flagsValue(flags)
    6957        , pattern(WTFMove(pattern))
     
    7159    }
    7260
    73     RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern)
     61    RegExpKey(OptionSet<Yarr::Flags> flags, const RefPtr<StringImpl>& pattern)
    7462        : flagsValue(flags)
    7563        , pattern(pattern)
     
    10896template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
    10997    static const bool emptyValueIsZero = true;
    110     static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; }
    111     static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; }
     98    static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::Yarr::Flags::DeletedValue; }
     99    static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::Yarr::Flags::DeletedValue; }
    112100};
    113101} // namespace WTF
  • trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp

    r242650 r242699  
    3030#include "JSCJSValue.h"
    3131#include "JSFunction.h"
    32 #include "JSObject.h"
    3332#include "JSStringInlines.h"
    3433#include "Lexer.h"
    3534#include "ObjectPrototype.h"
    36 #include "RegExp.h"
    3735#include "RegExpCache.h"
    3836#include "RegExpObject.h"
     
    4038#include "StringObject.h"
    4139#include "StringRecursionChecker.h"
     40#include "YarrFlags.h"
    4241#include <wtf/text/StringBuilder.h>
    4342
     
    150149        RETURN_IF_EXCEPTION(scope, encodedJSValue());
    151150
    152         RegExpFlags flags = NoFlags;
    153         if (!arg1.isUndefined()) {
    154             flags = regExpFlags(arg1.toWTFString(exec));
    155             RETURN_IF_EXCEPTION(scope, encodedJSValue());
    156             if (flags == InvalidFlags)
    157                 return throwVMError(exec, scope, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."_s));
    158         }
    159         regExp = RegExp::create(vm, pattern, flags);
     151        auto flags = arg1.isUndefined() ? makeOptional(OptionSet<Yarr::Flags> { }) : Yarr::parseFlags(arg1.toWTFString(exec));
     152        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     153        if (!flags)
     154            return throwVMError(exec, scope, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."_s));
     155
     156        regExp = RegExp::create(vm, pattern, flags.value());
    160157    }
    161158
  • trunk/Source/JavaScriptCore/testRegExp.cpp

    r240641 r242699  
    2525#include "JSCInlines.h"
    2626#include "JSGlobalObject.h"
     27#include "YarrFlags.h"
    2728#include <errno.h>
    2829#include <stdio.h>
     
    329330    ++i;
    330331
    331     RegExp* r = RegExp::create(vm, pattern.toString(), regExpFlags(line + i));
     332    auto flags = Yarr::parseFlags(line + i);
     333    if (!flags) {
     334        *regexpError = Yarr::errorMessage(Yarr::ErrorCode::InvalidRegularExpressionFlags);
     335        return nullptr;
     336    }
     337
     338    RegExp* r = RegExp::create(vm, pattern.toString(), flags.value());
    332339    if (!r->isValid()) {
    333340        *regexpError = r->errorMessage();
    334341        return nullptr;
    335342    }
     343
    336344    return r;
    337345}
  • trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp

    r229363 r242699  
    3030
    3131#include "Yarr.h"
     32#include "YarrFlags.h"
    3233#include "YarrInterpreter.h"
    3334#include <wtf/Assertions.h>
     
    5657    std::unique_ptr<JSC::Yarr::BytecodePattern> compile(const String& patternString, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode, UnicodeMode unicodeMode)
    5758    {
    58         RegExpFlags flags = NoFlags;
     59        OptionSet<JSC::Yarr::Flags> flags;
    5960
    6061        if (caseSensitivity == TextCaseInsensitive)
    61             flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
     62            flags.add(Flags::IgnoreCase);
    6263
    6364        if (multilineMode == MultilineEnabled)
    64             flags = static_cast<RegExpFlags>(flags | FlagMultiline);
     65            flags.add(Flags::Multiline);
    6566
    6667        if (unicodeMode == UnicodeAwareMode)
    67             flags = static_cast<RegExpFlags>(flags | FlagUnicode);
     68            flags.add(Flags::Unicode);
    6869
    6970        JSC::Yarr::YarrPattern pattern(patternString, flags, m_constructionErrorCode);
  • trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h

    r221160 r242699  
    2727
    2828#include "ConcurrentJSLock.h"
     29#include "YarrFlags.h"
    2930#include "YarrPattern.h"
    3031
     
    368369    size_t estimatedSizeInBytes() const { return m_body->estimatedSizeInBytes(); }
    369370   
    370     bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
    371     bool multiline() const { return m_flags & FlagMultiline; }
    372     bool sticky() const { return m_flags & FlagSticky; }
    373     bool unicode() const { return m_flags & FlagUnicode; }
    374     bool dotAll() const { return m_flags & FlagDotAll; }
     371    bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); }
     372    bool multiline() const { return m_flags.contains(Flags::Multiline); }
     373    bool sticky() const { return m_flags.contains(Flags::Sticky); }
     374    bool unicode() const { return m_flags.contains(Flags::Unicode); }
     375    bool dotAll() const { return m_flags.contains(Flags::DotAll); }
    375376
    376377    std::unique_ptr<ByteDisjunction> m_body;
    377     RegExpFlags m_flags;
     378    OptionSet<Flags> m_flags;
    378379    // Each BytecodePattern is associated with a RegExp, each RegExp is associated
    379380    // with a VM.  Cache a pointer to out VM's m_regExpAllocator.
  • trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp

    r240641 r242699  
    3737#include <wtf/Threading.h>
    3838#include <wtf/Vector.h>
    39 #include <wtf/text/WTFString.h>
    4039
    4140namespace JSC { namespace Yarr {
     
    11111110    YarrPatternConstructor constructor(*this, stackLimit);
    11121111
    1113     if (m_flags == InvalidFlags)
    1114         return ErrorCode::InvalidRegularExpressionFlags;
    1115 
    11161112    {
    11171113        ErrorCode error = parse(constructor, patternString, unicode());
     
    11531149}
    11541150
    1155 YarrPattern::YarrPattern(const String& pattern, RegExpFlags flags, ErrorCode& error, void* stackLimit)
     1151YarrPattern::YarrPattern(const String& pattern, OptionSet<Flags> flags, ErrorCode& error, void* stackLimit)
    11561152    : m_containsBackreferences(false)
    11571153    , m_containsBOL(false)
     
    11611157    , m_flags(flags)
    11621158{
     1159    ASSERT(m_flags != Flags::DeletedValue);
    11631160    error = compile(pattern, stackLimit);
    11641161}
     
    14211418    dumpPatternString(out, patternString);
    14221419
    1423     if (m_flags != NoFlags) {
     1420    if (m_flags) {
    14241421        bool printSeperator = false;
    14251422        out.print(" (");
  • trunk/Source/JavaScriptCore/yarr/YarrPattern.h

    r235882 r242699  
    2727#pragma once
    2828
    29 #include "RegExpKey.h"
    3029#include "YarrErrorCode.h"
     30#include "YarrFlags.h"
    3131#include "YarrUnicodeProperties.h"
    3232#include <wtf/CheckedArithmetic.h>
    3333#include <wtf/HashMap.h>
     34#include <wtf/OptionSet.h>
    3435#include <wtf/PrintStream.h>
    3536#include <wtf/Vector.h>
    36 #include <wtf/text/WTFString.h>
     37#include <wtf/text/StringHash.h>
    3738
    3839namespace JSC { namespace Yarr {
     
    353354
    354355struct YarrPattern {
    355     JS_EXPORT_PRIVATE YarrPattern(const String& pattern, RegExpFlags, ErrorCode&, void* stackLimit = nullptr);
     356    JS_EXPORT_PRIVATE YarrPattern(const String& pattern, OptionSet<Flags>, ErrorCode&, void* stackLimit = nullptr);
    356357
    357358    void resetForReparsing()
     
    508509    void dumpPattern(PrintStream& out, const String& pattern);
    509510
    510     bool global() const { return m_flags & FlagGlobal; }
    511     bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
    512     bool multiline() const { return m_flags & FlagMultiline; }
    513     bool sticky() const { return m_flags & FlagSticky; }
    514     bool unicode() const { return m_flags & FlagUnicode; }
    515     bool dotAll() const { return m_flags & FlagDotAll; }
     511    bool global() const { return m_flags.contains(Flags::Global); }
     512    bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); }
     513    bool multiline() const { return m_flags.contains(Flags::Multiline); }
     514    bool sticky() const { return m_flags.contains(Flags::Sticky); }
     515    bool unicode() const { return m_flags.contains(Flags::Unicode); }
     516    bool dotAll() const { return m_flags.contains(Flags::DotAll); }
    516517
    517518    bool m_containsBackreferences : 1;
     
    520521    bool m_hasCopiedParenSubexpressions : 1;
    521522    bool m_saveInitialStartValue : 1;
    522     RegExpFlags m_flags;
     523    OptionSet<Flags> m_flags;
    523524    unsigned m_numSubpatterns { 0 };
    524525    unsigned m_maxBackReference { 0 };
  • trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp

    r239427 r242699  
    2727#include "YarrSyntaxChecker.h"
    2828
     29#include "YarrFlags.h"
    2930#include "YarrParser.h"
    3031#include <wtf/Optional.h>
    31 #include <wtf/text/WTFString.h>
    3232
    3333namespace JSC { namespace Yarr {
     
    5959{
    6060    SyntaxChecker syntaxChecker;
    61     return parse(syntaxChecker, pattern, flags.contains('u'));
     61
     62    auto parsedFlags = parseFlags(flags);
     63    if (!parsedFlags)
     64        return ErrorCode::InvalidRegularExpressionFlags;
     65
     66    return parse(syntaxChecker, pattern, parsedFlags->contains(Flags::Unicode));
    6267}
    6368
  • trunk/Source/WebCore/ChangeLog

    r242696 r242699  
     12019-03-10  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Invalid flags in a RegExp literal should be an early SyntaxError
     4        https://bugs.webkit.org/show_bug.cgi?id=195514
     5
     6        Reviewed by Darin Adler.
     7
     8        * bindings/js/SerializedScriptValue.cpp:
     9        (WebCore::CloneDeserializer::readTerminal):
     10        Consume YarrFlags.
     11
    1122019-03-10  Tim Horton  <timothy_horton@apple.com>
    213
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r239746 r242699  
    5757#include "WebCoreJSClientData.h"
    5858#include <JavaScriptCore/APICast.h>
    59 #include <JavaScriptCore/ArrayBuffer.h>
    6059#include <JavaScriptCore/BooleanObject.h>
    6160#include <JavaScriptCore/CatchScope.h>
     
    8281#include <JavaScriptCore/TypedArrays.h>
    8382#include <JavaScriptCore/WasmModule.h>
     83#include <JavaScriptCore/YarrFlags.h>
    8484#include <limits>
    8585#include <wtf/MainThread.h>
     
    28922892            if (!readStringData(flags))
    28932893                return JSValue();
    2894             RegExpFlags reFlags = regExpFlags(flags->string());
    2895             ASSERT(reFlags != InvalidFlags);
     2894            auto reFlags = Yarr::parseFlags(flags->string());
     2895            ASSERT(reFlags.hasValue());
    28962896            VM& vm = m_exec->vm();
    2897             RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags);
     2897            RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags.value());
    28982898            return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
    28992899        }
Note: See TracChangeset for help on using the changeset viewer.