Title: [203452] trunk/Source/_javascript_Core
Revision
203452
Author
msab...@apple.com
Date
2016-07-20 07:50:32 -0700 (Wed, 20 Jul 2016)

Log Message

CrashOnOverflow in JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets
https://bugs.webkit.org/show_bug.cgi?id=159954

Reviewed by Benjamin Poulain.

YarrPatternConstructor::setupAlternativeOffsets() is using the checked arithmetic class
Checked<>, for offset calculations.  However the default use will just crash on
overflow.  Instead we should stop processing and propagate the error up the call stack.

Consolidated explicit error string with the common RegExp parsing error logic.
Moved that logic to YarrPattern as that seems like a better common place to put it.

* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* tests/stress/regress-159954.js: New test.
* yarr/YarrParser.h:
(JSC::Yarr::Parser::CharacterClassParserDelegate::CharacterClassParserDelegate):
(JSC::Yarr::Parser::CharacterClassParserDelegate::atomPatternCharacter):
(JSC::Yarr::Parser::Parser):
(JSC::Yarr::Parser::isIdentityEscapeAnError):
(JSC::Yarr::Parser::parseEscape):
(JSC::Yarr::Parser::parseCharacterClass):
(JSC::Yarr::Parser::parseParenthesesBegin):
(JSC::Yarr::Parser::parseParenthesesEnd):
(JSC::Yarr::Parser::parseQuantifier):
(JSC::Yarr::Parser::parseTokens):
(JSC::Yarr::Parser::parse):
* yarr/YarrPattern.cpp:
(JSC::Yarr::YarrPatternConstructor::disjunction):
(JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets):
(JSC::Yarr::YarrPatternConstructor::setupOffsets):
(JSC::Yarr::YarrPattern::errorMessage):
(JSC::Yarr::YarrPattern::compile):
* yarr/YarrPattern.h:
(JSC::Yarr::YarrPattern::reset):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (203451 => 203452)


--- trunk/Source/_javascript_Core/ChangeLog	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-07-20 14:50:32 UTC (rev 203452)
@@ -1,3 +1,42 @@
+2016-07-20  Michael Saboff  <msab...@apple.com>
+
+        CrashOnOverflow in JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets
+        https://bugs.webkit.org/show_bug.cgi?id=159954
+
+        Reviewed by Benjamin Poulain.
+
+        YarrPatternConstructor::setupAlternativeOffsets() is using the checked arithmetic class
+        Checked<>, for offset calculations.  However the default use will just crash on
+        overflow.  Instead we should stop processing and propagate the error up the call stack.
+
+        Consolidated explicit error string with the common RegExp parsing error logic.
+        Moved that logic to YarrPattern as that seems like a better common place to put it.
+
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * tests/stress/regress-159954.js: New test.
+        * yarr/YarrParser.h:
+        (JSC::Yarr::Parser::CharacterClassParserDelegate::CharacterClassParserDelegate):
+        (JSC::Yarr::Parser::CharacterClassParserDelegate::atomPatternCharacter):
+        (JSC::Yarr::Parser::Parser):
+        (JSC::Yarr::Parser::isIdentityEscapeAnError):
+        (JSC::Yarr::Parser::parseEscape):
+        (JSC::Yarr::Parser::parseCharacterClass):
+        (JSC::Yarr::Parser::parseParenthesesBegin):
+        (JSC::Yarr::Parser::parseParenthesesEnd):
+        (JSC::Yarr::Parser::parseQuantifier):
+        (JSC::Yarr::Parser::parseTokens):
+        (JSC::Yarr::Parser::parse):
+        * yarr/YarrPattern.cpp:
+        (JSC::Yarr::YarrPatternConstructor::disjunction):
+        (JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets):
+        (JSC::Yarr::YarrPatternConstructor::setupOffsets):
+        (JSC::Yarr::YarrPattern::errorMessage):
+        (JSC::Yarr::YarrPattern::compile):
+        * yarr/YarrPattern.h:
+        (JSC::Yarr::YarrPattern::reset):
+
 2016-07-19  Filip Pizlo  <fpi...@apple.com>
 
         The default testing mode should not involve disabling the FTL JIT

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (203451 => 203452)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-07-20 14:50:32 UTC (rev 203452)
@@ -1137,7 +1137,7 @@
     NativeCallFrameTracer tracer(&vm, exec);
     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
     if (!regexp->isValid()) {
-        vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
+        vm.throwException(exec, createSyntaxError(exec, regexp->errorMessage()));
         return JSValue::encode(jsUndefined());
     }
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (203451 => 203452)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-07-20 14:50:32 UTC (rev 203452)
@@ -536,7 +536,7 @@
     LLINT_BEGIN();
     RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
     if (!regExp->isValid())
-        LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
+        LLINT_THROW(createSyntaxError(exec, regExp->errorMessage()));
     LLINT_RETURN(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regExp));
 }
 

Added: trunk/Source/_javascript_Core/tests/stress/regress-159954.js (0 => 203452)


--- trunk/Source/_javascript_Core/tests/stress/regress-159954.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/regress-159954.js	2016-07-20 14:50:32 UTC (rev 203452)
@@ -0,0 +1,23 @@
+// Regression test for 159954.  This test should not crash or throw an exception.
+
+function testRegExp(regexpExpression)
+{
+    try {
+        let result = eval(regexpExpression);
+
+        throw "Expected \"" + regexpExpression + "\" to throw and it didn't";
+    } catch (e) {
+        if (e != "SyntaxError: Invalid regular _expression_: pattern exceeds string length limits")
+            throw e;
+        return true;
+    }
+}
+
+testRegExp("/a{2147483649,2147483650}a{2147483649,2147483650}/.exec('aaaa')");
+testRegExp("/a{2147483649,2147483650}a{2147483649,2147483650}/.exec('aa')");
+testRegExp("/(?:\1{2147483649,2147483650})+/.exec('123')");
+testRegExp("/([^]{2147483648,2147483651}(?:.){2})+?/.exec('xxx')");
+testRegExp("/(\u0004\W\u0f0b+?$[\xa7\t\t-\ue118\f]{2147483648,2147483648})+.+?/u.exec('testing')");
+testRegExp("/(.{2147483649,2147483652})+?/g.exec('xxx')");
+testRegExp("/(?:(?:[\D]{2147483649})+?.)*?/igmy.exec('123\\n123')");
+testRegExp("/(?:\1{2147483648,})+?/m.exec('xxx')");

Modified: trunk/Source/_javascript_Core/yarr/YarrParser.h (203451 => 203452)


--- trunk/Source/_javascript_Core/yarr/YarrParser.h	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/yarr/YarrParser.h	2016-07-20 14:50:32 UTC (rev 203452)
@@ -32,8 +32,6 @@
 
 namespace JSC { namespace Yarr {
 
-#define REGEXP_ERROR_PREFIX "Invalid regular _expression_: "
-
 enum BuiltInCharacterClassID {
     DigitClassID,
     SpaceClassID,
@@ -48,23 +46,6 @@
     template<class FriendDelegate>
     friend const char* parse(FriendDelegate&, const String& pattern, bool isUnicode, unsigned backReferenceLimit);
 
-    enum ErrorCode {
-        NoError,
-        PatternTooLarge,
-        QuantifierOutOfOrder,
-        QuantifierWithoutAtom,
-        QuantifierTooLarge,
-        MissingParentheses,
-        ParenthesesUnmatched,
-        ParenthesesTypeInvalid,
-        CharacterClassUnmatched,
-        CharacterClassOutOfOrder,
-        EscapeUnterminated,
-        InvalidUnicodeEscape,
-        InvalidIdentityEscape,
-        NumberOfErrorCodes
-    };
-
     /*
      * CharacterClassParserDelegate:
      *
@@ -76,7 +57,7 @@
      */
     class CharacterClassParserDelegate {
     public:
-        CharacterClassParserDelegate(Delegate& delegate, ErrorCode& err)
+        CharacterClassParserDelegate(Delegate& delegate, YarrPattern::ErrorCode& err)
             : m_delegate(delegate)
             , m_err(err)
             , m_state(Empty)
@@ -138,7 +119,7 @@
 
             case CachedCharacterHyphen:
                 if (ch < m_character) {
-                    m_err = CharacterClassOutOfOrder;
+                    m_err = YarrPattern::CharacterClassOutOfOrder;
                     return;
                 }
                 m_delegate.atomCharacterClassRange(m_character, ch);
@@ -219,7 +200,7 @@
 
     private:
         Delegate& m_delegate;
-        ErrorCode& m_err;
+        YarrPattern::ErrorCode& m_err;
         enum CharacterClassConstructionState {
             Empty,
             CachedCharacter,
@@ -233,7 +214,7 @@
     Parser(Delegate& delegate, const String& pattern, bool isUnicode, unsigned backReferenceLimit)
         : m_delegate(delegate)
         , m_backReferenceLimit(backReferenceLimit)
-        , m_err(NoError)
+        , m_err(YarrPattern::NoError)
         , m_data(pattern.characters<CharType>())
         , m_size(pattern.length())
         , m_index(0)
@@ -248,7 +229,7 @@
     bool isIdentityEscapeAnError(int ch)
     {
         if (m_isUnicode && !strchr("^$\\.*+?()[]{}|/", ch)) {
-            m_err = InvalidIdentityEscape;
+            m_err = YarrPattern::InvalidIdentityEscape;
             return true;
         }
 
@@ -283,7 +264,7 @@
         consume();
 
         if (atEndOfPattern()) {
-            m_err = EscapeUnterminated;
+            m_err = YarrPattern::EscapeUnterminated;
             return false;
         }
 
@@ -449,7 +430,7 @@
                 UChar32 codePoint = 0;
                 do {
                     if (atEndOfPattern() || !isASCIIHexDigit(peek())) {
-                        m_err = InvalidUnicodeEscape;
+                        m_err = YarrPattern::InvalidUnicodeEscape;
                         break;
                     }
 
@@ -456,12 +437,12 @@
                     codePoint = (codePoint << 4) | toASCIIHexValue(consume());
 
                     if (codePoint > UCHAR_MAX_VALUE)
-                        m_err = InvalidUnicodeEscape;
+                        m_err = YarrPattern::InvalidUnicodeEscape;
                 } while (!atEndOfPattern() && peek() != '}');
                 if (!atEndOfPattern() && peek() == '}')
                     consume();
                 else if (!m_err)
-                    m_err = InvalidUnicodeEscape;
+                    m_err = YarrPattern::InvalidUnicodeEscape;
                 if (m_err)
                     return false;
 
@@ -581,7 +562,7 @@
                 return;
         }
 
-        m_err = CharacterClassUnmatched;
+        m_err = YarrPattern::CharacterClassUnmatched;
     }
 
     /*
@@ -597,7 +578,7 @@
 
         if (tryConsume('?')) {
             if (atEndOfPattern()) {
-                m_err = ParenthesesTypeInvalid;
+                m_err = YarrPattern::ParenthesesTypeInvalid;
                 return;
             }
 
@@ -615,7 +596,7 @@
                 break;
             
             default:
-                m_err = ParenthesesTypeInvalid;
+                m_err = YarrPattern::ParenthesesTypeInvalid;
             }
         } else
             m_delegate.atomParenthesesSubpatternBegin();
@@ -637,7 +618,7 @@
         if (m_parenthesesNestingDepth > 0)
             m_delegate.atomParenthesesEnd();
         else
-            m_err = ParenthesesUnmatched;
+            m_err = YarrPattern::ParenthesesUnmatched;
 
         --m_parenthesesNestingDepth;
     }
@@ -653,7 +634,7 @@
         ASSERT(min <= max);
 
         if (min == UINT_MAX) {
-            m_err = QuantifierTooLarge;
+            m_err = YarrPattern::QuantifierTooLarge;
             return;
         }
 
@@ -660,7 +641,7 @@
         if (lastTokenWasAnAtom)
             m_delegate.quantifyAtom(min, max, !tryConsume('?'));
         else
-            m_err = QuantifierWithoutAtom;
+            m_err = YarrPattern::QuantifierWithoutAtom;
     }
 
     /*
@@ -754,7 +735,7 @@
                         if (min <= max)
                             parseQuantifier(lastTokenWasAnAtom, min, max);
                         else
-                            m_err = QuantifierOutOfOrder;
+                            m_err = YarrPattern::QuantifierOutOfOrder;
                         lastTokenWasAnAtom = false;
                         break;
                     }
@@ -775,7 +756,7 @@
         }
 
         if (m_parenthesesNestingDepth > 0)
-            m_err = MissingParentheses;
+            m_err = YarrPattern::MissingParentheses;
     }
 
     /*
@@ -787,29 +768,12 @@
     const char* parse()
     {
         if (m_size > MAX_PATTERN_SIZE)
-            m_err = PatternTooLarge;
+            m_err = YarrPattern::PatternTooLarge;
         else
             parseTokens();
         ASSERT(atEndOfPattern() || m_err);
-
-        // The order of this array must match the ErrorCode enum.
-        static const char* errorMessages[NumberOfErrorCodes] = {
-            0, // NoError
-            REGEXP_ERROR_PREFIX "regular _expression_ too large",
-            REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier",
-            REGEXP_ERROR_PREFIX "nothing to repeat",
-            REGEXP_ERROR_PREFIX "number too large in {} quantifier",
-            REGEXP_ERROR_PREFIX "missing )",
-            REGEXP_ERROR_PREFIX "unmatched parentheses",
-            REGEXP_ERROR_PREFIX "unrecognized character after (?",
-            REGEXP_ERROR_PREFIX "missing terminating ] for character class",
-            REGEXP_ERROR_PREFIX "range out of order in character class",
-            REGEXP_ERROR_PREFIX "\\ at end of pattern",
-            REGEXP_ERROR_PREFIX "invalid unicode {} escape",
-            REGEXP_ERROR_PREFIX "invalid escaped character for unicode pattern"
-        };
-
-        return errorMessages[m_err];
+        
+        return YarrPattern::errorMessage(m_err);
     }
 
     // Misc helper functions:
@@ -913,7 +877,7 @@
 
     Delegate& m_delegate;
     unsigned m_backReferenceLimit;
-    ErrorCode m_err;
+    YarrPattern::ErrorCode m_err;
     const CharType* m_data;
     unsigned m_size;
     unsigned m_index;

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.cpp (203451 => 203452)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2016-07-20 14:50:32 UTC (rev 203452)
@@ -578,13 +578,14 @@
         m_alternative = m_alternative->m_parent->addNewAlternative();
     }
 
-    bool setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition, unsigned& newCallFrameSize) WARN_UNUSED_RETURN
+    YarrPattern::ErrorCode setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition, unsigned& newCallFrameSize) WARN_UNUSED_RETURN
     {
         if (UNLIKELY(!isSafeToRecurse()))
-            return false;
+            return YarrPattern::TooManyDisjunctions;
 
+        YarrPattern::ErrorCode error = YarrPattern::NoError;
         alternative->m_hasFixedSize = true;
-        Checked<unsigned> currentInputPosition = initialInputPosition;
+        Checked<unsigned, RecordOverflow> currentInputPosition = initialInputPosition;
 
         for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
             PatternTerm& term = alternative->m_terms[i];
@@ -639,8 +640,9 @@
                 if (term.quantityCount == 1 && !term.parentheses.isCopy) {
                     if (term.quantityType != QuantifierFixedCount)
                         currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce;
-                    if (!setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet(), currentCallFrameSize))
-                        return false;
+                    error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet(), currentCallFrameSize);
+                    if (error)
+                        return error;
                     // If quantity is fixed, then pre-check its minimum size.
                     if (term.quantityType == QuantifierFixedCount)
                         currentInputPosition += term.parentheses.disjunction->m_minimumSize;
@@ -647,14 +649,16 @@
                     term.inputPosition = currentInputPosition.unsafeGet();
                 } else if (term.parentheses.isTerminal) {
                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal;
-                    if (!setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet(), currentCallFrameSize))
-                        return false;
+                    error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet(), currentCallFrameSize);
+                    if (error)
+                        return error;
                     term.inputPosition = currentInputPosition.unsafeGet();
                 } else {
                     term.inputPosition = currentInputPosition.unsafeGet();
                     unsigned ignoredCallFrameSize;
-                    if (!setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition.unsafeGet(), ignoredCallFrameSize))
-                        return false;
+                    error = setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition.unsafeGet(), ignoredCallFrameSize);
+                    if (error)
+                        return error;
                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses;
                 }
                 // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
@@ -664,8 +668,9 @@
             case PatternTerm::TypeParentheticalAssertion:
                 term.inputPosition = currentInputPosition.unsafeGet();
                 term.frameLocation = currentCallFrameSize;
-                if (!setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition.unsafeGet(), currentCallFrameSize))
-                    return false;
+                error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition.unsafeGet(), currentCallFrameSize);
+                if (error)
+                    return error;
                 break;
 
             case PatternTerm::TypeDotStarEnclosure:
@@ -673,17 +678,19 @@
                 term.inputPosition = initialInputPosition;
                 break;
             }
+            if (currentInputPosition.hasOverflowed())
+                return YarrPattern::OffsetTooLarge;
         }
 
         alternative->m_minimumSize = (currentInputPosition - initialInputPosition).unsafeGet();
         newCallFrameSize = currentCallFrameSize;
-        return true;
+        return error;
     }
 
-    bool setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned& callFrameSize) WARN_UNUSED_RETURN
+    YarrPattern::ErrorCode setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned& callFrameSize)
     {
         if (UNLIKELY(!isSafeToRecurse()))
-            return false;
+            return YarrPattern::TooManyDisjunctions;
 
         if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
             initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
@@ -691,12 +698,14 @@
         unsigned minimumInputSize = UINT_MAX;
         unsigned maximumCallFrameSize = 0;
         bool hasFixedSize = true;
+        YarrPattern::ErrorCode error = YarrPattern::NoError;
 
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
             PatternAlternative* alternative = disjunction->m_alternatives[alt].get();
             unsigned currentAlternativeCallFrameSize;
-            if (!setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition, currentAlternativeCallFrameSize))
-                return false;
+            error = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition, currentAlternativeCallFrameSize);
+            if (error)
+                return error;
             minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize);
             maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize);
             hasFixedSize &= alternative->m_hasFixedSize;
@@ -711,7 +720,7 @@
         disjunction->m_minimumSize = minimumInputSize;
         disjunction->m_callFrameSize = maximumCallFrameSize;
         callFrameSize = maximumCallFrameSize;
-        return true;
+        return error;
     }
 
     const char* setupOffsets()
@@ -718,8 +727,9 @@
     {
         // FIXME: Yarr should not use the stack to handle subpatterns (rdar://problem/26436314).
         unsigned ignoredCallFrameSize;
-        if (!setupDisjunctionOffsets(m_pattern.m_body, 0, 0, ignoredCallFrameSize))
-            return REGEXP_ERROR_PREFIX "too many nested disjunctions";
+        YarrPattern::ErrorCode error = setupDisjunctionOffsets(m_pattern.m_body, 0, 0, ignoredCallFrameSize);
+        if (error)
+            return YarrPattern::errorMessage(error);
         return nullptr;
     }
 
@@ -878,6 +888,31 @@
     bool m_invertParentheticalAssertion;
 };
 
+const char* YarrPattern::errorMessage(YarrPattern::ErrorCode error)
+{
+#define REGEXP_ERROR_PREFIX "Invalid regular _expression_: "
+    // The order of this array must match the ErrorCode enum.
+    static const char* errorMessages[NumberOfErrorCodes] = {
+        nullptr, // NoError
+        REGEXP_ERROR_PREFIX "regular _expression_ too large",
+        REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier",
+        REGEXP_ERROR_PREFIX "nothing to repeat",
+        REGEXP_ERROR_PREFIX "number too large in {} quantifier",
+        REGEXP_ERROR_PREFIX "missing )",
+        REGEXP_ERROR_PREFIX "unmatched parentheses",
+        REGEXP_ERROR_PREFIX "unrecognized character after (?",
+        REGEXP_ERROR_PREFIX "missing terminating ] for character class",
+        REGEXP_ERROR_PREFIX "range out of order in character class",
+        REGEXP_ERROR_PREFIX "\\ at end of pattern",
+        REGEXP_ERROR_PREFIX "invalid unicode {} escape",
+        REGEXP_ERROR_PREFIX "invalid escaped character for unicode pattern",
+        REGEXP_ERROR_PREFIX "too many nested disjunctions",
+        REGEXP_ERROR_PREFIX "pattern exceeds string length limits"
+    };
+
+    return errorMessages[error];
+}
+
 const char* YarrPattern::compile(const String& patternString, void* stackLimit)
 {
     YarrPatternConstructor constructor(*this, stackLimit);

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.h (203451 => 203452)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.h	2016-07-20 13:07:05 UTC (rev 203451)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.h	2016-07-20 14:50:32 UTC (rev 203452)
@@ -306,6 +306,27 @@
 struct YarrPattern {
     JS_EXPORT_PRIVATE YarrPattern(const String& pattern, RegExpFlags, const char** error, void* stackLimit = nullptr);
 
+    enum ErrorCode {
+        NoError,
+        PatternTooLarge,
+        QuantifierOutOfOrder,
+        QuantifierWithoutAtom,
+        QuantifierTooLarge,
+        MissingParentheses,
+        ParenthesesUnmatched,
+        ParenthesesTypeInvalid,
+        CharacterClassUnmatched,
+        CharacterClassOutOfOrder,
+        EscapeUnterminated,
+        InvalidUnicodeEscape,
+        InvalidIdentityEscape,
+        TooManyDisjunctions,
+        OffsetTooLarge,
+        NumberOfErrorCodes
+    };
+    
+    WTF_EXPORT_PRIVATE static const char* errorMessage(ErrorCode);
+
     void reset()
     {
         m_numSubpatterns = 0;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to