Title: [247001] releases/WebKitGTK/webkit-2.24
Revision
247001
Author
carlo...@webkit.org
Date
2019-07-01 04:04:16 -0700 (Mon, 01 Jul 2019)

Log Message

Merge r246408 - Yarr bytecode compilation failure should be gracefully handled
https://bugs.webkit.org/show_bug.cgi?id=198700

Reviewed by Michael Saboff.

JSTests:

* stress/regexp-bytecode-compilation-fail.js: Added.
(shouldThrow):

Source/_javascript_Core:

Currently, we assume that Yarr bytecode compilation does not fail. But in fact it can fail.
We should gracefully handle this failure as a runtime error, as we did for parse errors in [1].
We also harden Yarr's consumed character calculation by using Checked.

[1]: https://bugs.webkit.org/show_bug.cgi?id=185755

* inspector/ContentSearchUtilities.cpp:
(Inspector::ContentSearchUtilities::findMagicComment):
* runtime/RegExp.cpp:
(JSC::RegExp::byteCodeCompileIfNecessary):
(JSC::RegExp::compile):
(JSC::RegExp::compileMatchOnly):
* runtime/RegExpInlines.h:
(JSC::RegExp::matchInline):
* yarr/YarrErrorCode.cpp:
(JSC::Yarr::errorMessage):
(JSC::Yarr::errorToThrow):
* yarr/YarrErrorCode.h:
* yarr/YarrInterpreter.cpp:
(JSC::Yarr::ByteCompiler::ByteCompiler):
(JSC::Yarr::ByteCompiler::compile):
(JSC::Yarr::ByteCompiler::atomCharacterClass):
(JSC::Yarr::ByteCompiler::atomBackReference):
(JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin):
(JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin):
(JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin):
(JSC::Yarr::ByteCompiler::atomParentheticalAssertionBegin):
(JSC::Yarr::ByteCompiler::popParenthesesStack):
(JSC::Yarr::ByteCompiler::closeAlternative):
(JSC::Yarr::ByteCompiler::closeBodyAlternative):
(JSC::Yarr::ByteCompiler::alternativeBodyDisjunction):
(JSC::Yarr::ByteCompiler::alternativeDisjunction):
(JSC::Yarr::ByteCompiler::emitDisjunction):

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/JSTests/ChangeLog (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/JSTests/ChangeLog	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/JSTests/ChangeLog	2019-07-01 11:04:16 UTC (rev 247001)
@@ -1,3 +1,13 @@
+2019-06-13  Yusuke Suzuki  <ysuz...@apple.com>
+
+        Yarr bytecode compilation failure should be gracefully handled
+        https://bugs.webkit.org/show_bug.cgi?id=198700
+
+        Reviewed by Michael Saboff.
+
+        * stress/regexp-bytecode-compilation-fail.js: Added.
+        (shouldThrow):
+
 2019-02-26  Mark Lam  <mark....@apple.com>
 
         wasmToJS() should purify incoming NaNs.

Added: releases/WebKitGTK/webkit-2.24/JSTests/stress/regexp-bytecode-compilation-fail.js (0 => 247001)


--- releases/WebKitGTK/webkit-2.24/JSTests/stress/regexp-bytecode-compilation-fail.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/JSTests/stress/regexp-bytecode-compilation-fail.js	2019-07-01 11:04:16 UTC (rev 247001)
@@ -0,0 +1,23 @@
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function v2() {
+    const v8 = RegExp("(1{2147480000,}2{3648,})|(ab)");
+    "(1{2147480000,}2{3648,})|(ab)";
+    const v4 = RegExp(v2);
+    const v5 = v4.test();
+    return v5;
+}
+shouldThrow(v2, `SyntaxError: Invalid regular _expression_: pattern exceeds string length limits`);

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/ChangeLog	2019-07-01 11:04:16 UTC (rev 247001)
@@ -1,3 +1,44 @@
+2019-06-13  Yusuke Suzuki  <ysuz...@apple.com>
+
+        Yarr bytecode compilation failure should be gracefully handled
+        https://bugs.webkit.org/show_bug.cgi?id=198700
+
+        Reviewed by Michael Saboff.
+
+        Currently, we assume that Yarr bytecode compilation does not fail. But in fact it can fail.
+        We should gracefully handle this failure as a runtime error, as we did for parse errors in [1].
+        We also harden Yarr's consumed character calculation by using Checked.
+
+        [1]: https://bugs.webkit.org/show_bug.cgi?id=185755
+
+        * inspector/ContentSearchUtilities.cpp:
+        (Inspector::ContentSearchUtilities::findMagicComment):
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::byteCodeCompileIfNecessary):
+        (JSC::RegExp::compile):
+        (JSC::RegExp::compileMatchOnly):
+        * runtime/RegExpInlines.h:
+        (JSC::RegExp::matchInline):
+        * yarr/YarrErrorCode.cpp:
+        (JSC::Yarr::errorMessage):
+        (JSC::Yarr::errorToThrow):
+        * yarr/YarrErrorCode.h:
+        * yarr/YarrInterpreter.cpp:
+        (JSC::Yarr::ByteCompiler::ByteCompiler):
+        (JSC::Yarr::ByteCompiler::compile):
+        (JSC::Yarr::ByteCompiler::atomCharacterClass):
+        (JSC::Yarr::ByteCompiler::atomBackReference):
+        (JSC::Yarr::ByteCompiler::atomParenthesesOnceBegin):
+        (JSC::Yarr::ByteCompiler::atomParenthesesTerminalBegin):
+        (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternBegin):
+        (JSC::Yarr::ByteCompiler::atomParentheticalAssertionBegin):
+        (JSC::Yarr::ByteCompiler::popParenthesesStack):
+        (JSC::Yarr::ByteCompiler::closeAlternative):
+        (JSC::Yarr::ByteCompiler::closeBodyAlternative):
+        (JSC::Yarr::ByteCompiler::alternativeBodyDisjunction):
+        (JSC::Yarr::ByteCompiler::alternativeDisjunction):
+        (JSC::Yarr::ByteCompiler::emitDisjunction):
+
 2019-02-26  Mark Lam  <mark....@apple.com>
 
         wasmToJS() should purify incoming NaNs.

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2019-07-01 11:04:16 UTC (rev 247001)
@@ -170,8 +170,9 @@
     YarrPattern pattern(patternString, JSC::RegExpFlags::FlagMultiline, error);
     ASSERT(!hasError(error));
     BumpPointerAllocator regexAllocator;
-    auto bytecodePattern = byteCompile(pattern, &regexAllocator);
-    ASSERT(bytecodePattern);
+    JSC::Yarr::ErrorCode ignoredErrorCode = JSC::Yarr::ErrorCode::NoError;
+    auto bytecodePattern = byteCompile(pattern, &regexAllocator, ignoredErrorCode);
+    RELEASE_ASSERT(bytecodePattern);
 
     ASSERT(pattern.m_numSubpatterns == 1);
     std::array<unsigned, 4> matches;

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExp.cpp (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExp.cpp	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExp.cpp	2019-07-01 11:04:16 UTC (rev 247001)
@@ -262,9 +262,9 @@
 }
 
 
-static std::unique_ptr<Yarr::BytecodePattern> byteCodeCompilePattern(VM* vm, Yarr::YarrPattern& pattern)
+static std::unique_ptr<Yarr::BytecodePattern> byteCodeCompilePattern(VM* vm, Yarr::YarrPattern& pattern, Yarr::ErrorCode& errorCode)
 {
-    return Yarr::byteCompile(pattern, &vm->m_regExpAllocator, &vm->m_regExpAllocatorLock);
+    return Yarr::byteCompile(pattern, &vm->m_regExpAllocator, errorCode, &vm->m_regExpAllocatorLock);
 }
 
 void RegExp::byteCodeCompileIfNecessary(VM* vm)
@@ -282,7 +282,11 @@
     }
     ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
 
-    m_regExpBytecode = byteCodeCompilePattern(vm, pattern);
+    m_regExpBytecode = byteCodeCompilePattern(vm, pattern, m_constructionErrorCode);
+    if (!m_regExpBytecode) {
+        m_state = ParseError;
+        return;
+    }
 }
 
 void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
@@ -322,7 +326,11 @@
         dataLog("Can't JIT this regular _expression_: \"", m_patternString, "\"\n");
 
     m_state = ByteCode;
-    m_regExpBytecode = byteCodeCompilePattern(vm, pattern);
+    m_regExpBytecode = byteCodeCompilePattern(vm, pattern, m_constructionErrorCode);
+    if (!m_regExpBytecode) {
+        m_state = ParseError;
+        return;
+    }
 }
 
 int RegExp::match(VM& vm, const String& s, unsigned startOffset, Vector<int>& ovector)
@@ -379,7 +387,11 @@
         dataLog("Can't JIT this regular _expression_: \"", m_patternString, "\"\n");
 
     m_state = ByteCode;
-    m_regExpBytecode = byteCodeCompilePattern(vm, pattern);
+    m_regExpBytecode = byteCodeCompilePattern(vm, pattern, m_constructionErrorCode);
+    if (!m_regExpBytecode) {
+        m_state = ParseError;
+        return;
+    }
 }
 
 MatchResult RegExp::match(VM& vm, const String& s, unsigned startOffset)

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExpInlines.h (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExpInlines.h	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/runtime/RegExpInlines.h	2019-07-01 11:04:16 UTC (rev 247001)
@@ -139,7 +139,7 @@
 
     compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
 
-    if (m_state == ParseError) {
+    auto throwError = [&] {
         auto throwScope = DECLARE_THROW_SCOPE(vm);
         ExecState* exec = vm.topCallFrame;
         throwScope.throwException(exec, errorToThrow(exec));
@@ -146,8 +146,11 @@
         if (!hasHardError(m_constructionErrorCode))
             reset();
         return -1;
-    }
+    };
 
+    if (m_state == ParseError)
+        return throwError();
+
     int offsetVectorSize = (m_numSubpatterns + 1) * 2;
     ovector.resize(offsetVectorSize);
     int* offsetVector = ovector.data();
@@ -175,6 +178,8 @@
         if (result == Yarr::JSRegExpJITCodeFailure) {
             // JIT'ed code couldn't handle _expression_, so punt back to the interpreter.
             byteCodeCompileIfNecessary(&vm);
+            if (m_state == ParseError)
+                return throwError();
             result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
         }
 
@@ -263,7 +268,7 @@
 
     compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
 
-    if (m_state == ParseError) {
+    auto throwError = [&] {
         auto throwScope = DECLARE_THROW_SCOPE(vm);
         ExecState* exec = vm.topCallFrame;
         throwScope.throwException(exec, errorToThrow(exec));
@@ -270,8 +275,11 @@
         if (!hasHardError(m_constructionErrorCode))
             reset();
         return MatchResult::failed();
-    }
+    };
 
+    if (m_state == ParseError)
+        return throwError();
+
 #if ENABLE(YARR_JIT)
     MatchResult result;
 
@@ -302,6 +310,8 @@
 
         // JIT'ed code couldn't handle _expression_, so punt back to the interpreter.
         byteCodeCompileIfNecessary(&vm);
+        if (m_state == ParseError)
+            return throwError();
     }
 #endif
 

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/RegularExpression.cpp (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/RegularExpression.cpp	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/RegularExpression.cpp	2019-07-01 11:04:16 UTC (rev 247001)
@@ -74,7 +74,7 @@
 
         m_numSubpatterns = pattern.m_numSubpatterns;
 
-        return JSC::Yarr::byteCompile(pattern, &m_regexAllocator);
+        return JSC::Yarr::byteCompile(pattern, &m_regexAllocator, m_constructionErrorCode);
     }
 
     BumpPointerAllocator m_regexAllocator;

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.cpp (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.cpp	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.cpp	2019-07-01 11:04:16 UTC (rev 247001)
@@ -1673,13 +1673,15 @@
     ByteCompiler(YarrPattern& pattern)
         : m_pattern(pattern)
     {
-        m_currentAlternativeIndex = 0;
     }
 
-    std::unique_ptr<BytecodePattern> compile(BumpPointerAllocator* allocator, ConcurrentJSLock* lock)
+    std::unique_ptr<BytecodePattern> compile(BumpPointerAllocator* allocator, ConcurrentJSLock* lock, ErrorCode& errorCode)
     {
         regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize, m_pattern.m_body->m_alternatives[0]->onceThrough());
-        emitDisjunction(m_pattern.m_body);
+        if (auto error = emitDisjunction(m_pattern.m_body, 0, 0)) {
+            errorCode = error.value();
+            return nullptr;
+        }
         regexEnd();
 
 #ifndef NDEBUG
@@ -1734,9 +1736,9 @@
     {
         m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
 
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityMaxCount = quantityMaxCount.unsafeGet();
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().atom.quantityMaxCount = quantityMaxCount.unsafeGet();
+        m_bodyDisjunction->terms.last().atom.quantityType = quantityType;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
     }
 
     void atomBackReference(unsigned subpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityMaxCount, QuantifierType quantityType)
@@ -1745,19 +1747,19 @@
 
         m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
 
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityMaxCount = quantityMaxCount.unsafeGet();
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().atom.quantityMaxCount = quantityMaxCount.unsafeGet();
+        m_bodyDisjunction->terms.last().atom.quantityType = quantityType;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
     }
 
     void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
-        int beginTerm = m_bodyDisjunction->terms.size();
+        unsigned beginTerm = m_bodyDisjunction->terms.size();
 
         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
         m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = alternativeFrameLocation;
 
         m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
         m_currentAlternativeIndex = beginTerm + 1;
@@ -1765,12 +1767,12 @@
 
     void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
-        int beginTerm = m_bodyDisjunction->terms.size();
+        unsigned beginTerm = m_bodyDisjunction->terms.size();
 
         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalBegin, subpatternId, capture, false, inputPosition));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
         m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = alternativeFrameLocation;
 
         m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
         m_currentAlternativeIndex = beginTerm + 1;
@@ -1782,12 +1784,12 @@
         // then fix this up at the end! - simplifying this should make it much clearer.
         // https://bugs.webkit.org/show_bug.cgi?id=50136
 
-        int beginTerm = m_bodyDisjunction->terms.size();
+        unsigned beginTerm = m_bodyDisjunction->terms.size();
 
         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
         m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = alternativeFrameLocation;
 
         m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
         m_currentAlternativeIndex = beginTerm + 1;
@@ -1795,12 +1797,12 @@
 
     void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
-        int beginTerm = m_bodyDisjunction->terms.size();
+        unsigned beginTerm = m_bodyDisjunction->terms.size();
 
         m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, false, invert, 0));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = frameLocation;
         m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.last().frameLocation = alternativeFrameLocation;
 
         m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
         m_currentAlternativeIndex = beginTerm + 1;
@@ -1836,10 +1838,9 @@
     unsigned popParenthesesStack()
     {
         ASSERT(m_parenthesesStack.size());
-        int stackEnd = m_parenthesesStack.size() - 1;
-        unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
-        m_currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
-        m_parenthesesStack.shrink(stackEnd);
+        unsigned beginTerm = m_parenthesesStack.last().beginTerm;
+        m_currentAlternativeIndex = m_parenthesesStack.last().savedAlternativeIndex;
+        m_parenthesesStack.removeLast();
 
         ASSERT(beginTerm < m_bodyDisjunction->terms.size());
         ASSERT(m_currentAlternativeIndex < m_bodyDisjunction->terms.size());
@@ -1847,11 +1848,11 @@
         return beginTerm;
     }
 
-    void closeAlternative(int beginTerm)
+    void closeAlternative(unsigned beginTerm)
     {
-        int origBeginTerm = beginTerm;
+        unsigned origBeginTerm = beginTerm;
         ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
-        int endIndex = m_bodyDisjunction->terms.size();
+        unsigned endIndex = m_bodyDisjunction->terms.size();
 
         unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
 
@@ -1874,10 +1875,10 @@
 
     void closeBodyAlternative()
     {
-        int beginTerm = 0;
-        int origBeginTerm = 0;
+        unsigned beginTerm = 0;
+        unsigned origBeginTerm = 0;
         ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
-        int endIndex = m_bodyDisjunction->terms.size();
+        unsigned endIndex = m_bodyDisjunction->terms.size();
 
         unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
 
@@ -1992,7 +1993,7 @@
 
     void alternativeBodyDisjunction(bool onceThrough)
     {
-        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        unsigned newAlternativeIndex = m_bodyDisjunction->terms.size();
         m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
         m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction(onceThrough));
 
@@ -2001,7 +2002,7 @@
 
     void alternativeDisjunction()
     {
-        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        unsigned newAlternativeIndex = m_bodyDisjunction->terms.size();
         m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
         m_bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
 
@@ -2008,10 +2009,10 @@
         m_currentAlternativeIndex = newAlternativeIndex;
     }
 
-    void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
+    Optional<ErrorCode> WARN_UNUSED_RETURN emitDisjunction(PatternDisjunction* disjunction, Checked<unsigned, RecordOverflow> inputCountAlreadyChecked, unsigned parenthesesInputCountAlreadyChecked)
     {
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
-            unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
+            auto currentCountAlreadyChecked = inputCountAlreadyChecked;
 
             PatternAlternative* alternative = disjunction->m_alternatives[alt].get();
 
@@ -2029,33 +2030,35 @@
             if (countToCheck) {
                 checkInput(countToCheck);
                 currentCountAlreadyChecked += countToCheck;
+                if (currentCountAlreadyChecked.hasOverflowed())
+                    return ErrorCode::OffsetTooLarge;
             }
 
             for (auto& term : alternative->m_terms) {
                 switch (term.type) {
                 case PatternTerm::TypeAssertionBOL:
-                    assertionBOL(currentCountAlreadyChecked - term.inputPosition);
+                    assertionBOL((currentCountAlreadyChecked - term.inputPosition).unsafeGet());
                     break;
 
                 case PatternTerm::TypeAssertionEOL:
-                    assertionEOL(currentCountAlreadyChecked - term.inputPosition);
+                    assertionEOL((currentCountAlreadyChecked - term.inputPosition).unsafeGet());
                     break;
 
                 case PatternTerm::TypeAssertionWordBoundary:
-                    assertionWordBoundary(term.invert(), currentCountAlreadyChecked - term.inputPosition);
+                    assertionWordBoundary(term.invert(), (currentCountAlreadyChecked - term.inputPosition).unsafeGet());
                     break;
 
                 case PatternTerm::TypePatternCharacter:
-                    atomPatternCharacter(term.patternCharacter, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType);
+                    atomPatternCharacter(term.patternCharacter, (currentCountAlreadyChecked - term.inputPosition).unsafeGet(), term.frameLocation, term.quantityMaxCount, term.quantityType);
                     break;
 
                 case PatternTerm::TypeCharacterClass:
-                    atomCharacterClass(term.characterClass, term.invert(), currentCountAlreadyChecked- term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType);
+                    atomCharacterClass(term.characterClass, term.invert(), (currentCountAlreadyChecked - term.inputPosition).unsafeGet(), term.frameLocation, term.quantityMaxCount, term.quantityType);
                     break;
 
                 case PatternTerm::TypeBackReference:
-                    atomBackReference(term.backReferenceSubpatternId, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityMaxCount, term.quantityType);
-                        break;
+                    atomBackReference(term.backReferenceSubpatternId, (currentCountAlreadyChecked - term.inputPosition).unsafeGet(), term.frameLocation, term.quantityMaxCount, term.quantityType);
+                    break;
 
                 case PatternTerm::TypeForwardReference:
                     break;
@@ -2069,22 +2072,22 @@
                             disjunctionAlreadyCheckedCount = term.parentheses.disjunction->m_minimumSize;
                         else
                             alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
-                        ASSERT(currentCountAlreadyChecked >= term.inputPosition);
-                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        unsigned delegateEndInputOffset = (currentCountAlreadyChecked - term.inputPosition).unsafeGet();
                         atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, alternativeFrameLocation);
-                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
+                        if (auto error = emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount))
+                            return error;
                         atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType);
                     } else if (term.parentheses.isTerminal) {
-                        ASSERT(currentCountAlreadyChecked >= term.inputPosition);
-                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        unsigned delegateEndInputOffset = (currentCountAlreadyChecked - term.inputPosition).unsafeGet();
                         atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesTerminal);
-                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
+                        if (auto error = emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount))
+                            return error;
                         atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType);
                     } else {
-                        ASSERT(currentCountAlreadyChecked >= term.inputPosition);
-                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        unsigned delegateEndInputOffset = (currentCountAlreadyChecked - term.inputPosition).unsafeGet();
                         atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, 0);
-                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
+                        if (auto error = emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0))
+                            return error;
                         atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityMinCount, term.quantityMaxCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
                     }
                     break;
@@ -2092,22 +2095,25 @@
 
                 case PatternTerm::TypeParentheticalAssertion: {
                     unsigned alternativeFrameLocation = term.frameLocation + YarrStackSpaceForBackTrackInfoParentheticalAssertion;
-
-                    ASSERT(currentCountAlreadyChecked >= term.inputPosition);
-                    unsigned positiveInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                    unsigned positiveInputOffset = (currentCountAlreadyChecked - term.inputPosition).unsafeGet();
                     unsigned uncheckAmount = 0;
                     if (positiveInputOffset > term.parentheses.disjunction->m_minimumSize) {
                         uncheckAmount = positiveInputOffset - term.parentheses.disjunction->m_minimumSize;
                         uncheckInput(uncheckAmount);
                         currentCountAlreadyChecked -= uncheckAmount;
+                        if (currentCountAlreadyChecked.hasOverflowed())
+                            return ErrorCode::OffsetTooLarge;
                     }
 
                     atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invert(), term.frameLocation, alternativeFrameLocation);
-                    emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset - uncheckAmount);
+                    if (auto error = emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset - uncheckAmount))
+                        return error;
                     atomParentheticalAssertionEnd(0, term.frameLocation, term.quantityMaxCount, term.quantityType);
                     if (uncheckAmount) {
                         checkInput(uncheckAmount);
                         currentCountAlreadyChecked += uncheckAmount;
+                        if (currentCountAlreadyChecked.hasOverflowed())
+                            return ErrorCode::OffsetTooLarge;
                     }
                     break;
                 }
@@ -2118,6 +2124,7 @@
                 }
             }
         }
+        return WTF::nullopt;
     }
 #ifndef NDEBUG
     void dumpDisjunction(ByteDisjunction* disjunction, unsigned nesting = 0)
@@ -2383,14 +2390,14 @@
 private:
     YarrPattern& m_pattern;
     std::unique_ptr<ByteDisjunction> m_bodyDisjunction;
-    unsigned m_currentAlternativeIndex;
+    unsigned m_currentAlternativeIndex { 0 };
     Vector<ParenthesesStackEntry> m_parenthesesStack;
     Vector<std::unique_ptr<ByteDisjunction>> m_allParenthesesInfo;
 };
 
-std::unique_ptr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocator* allocator, ConcurrentJSLock* lock)
+std::unique_ptr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocator* allocator, ErrorCode& errorCode, ConcurrentJSLock* lock)
 {
-    return ByteCompiler(pattern).compile(allocator, lock);
+    return ByteCompiler(pattern).compile(allocator, lock, errorCode);
 }
 
 unsigned interpret(BytecodePattern* bytecode, const String& input, unsigned start, unsigned* output)

Modified: releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.h (247000 => 247001)


--- releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.h	2019-07-01 11:04:11 UTC (rev 247000)
+++ releases/WebKitGTK/webkit-2.24/Source/_javascript_Core/yarr/YarrInterpreter.h	2019-07-01 11:04:16 UTC (rev 247001)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "ConcurrentJSLock.h"
+#include "YarrErrorCode.h"
 #include "YarrPattern.h"
 
 namespace WTF {
@@ -388,7 +389,7 @@
     Vector<std::unique_ptr<CharacterClass>> m_userCharacterClasses;
 };
 
-JS_EXPORT_PRIVATE std::unique_ptr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*, ConcurrentJSLock* = nullptr);
+JS_EXPORT_PRIVATE std::unique_ptr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*, ErrorCode&, ConcurrentJSLock* = nullptr);
 JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const String& input, unsigned start, unsigned* output);
 unsigned interpret(BytecodePattern*, const LChar* input, unsigned length, unsigned start, unsigned* output);
 unsigned interpret(BytecodePattern*, const UChar* input, unsigned length, unsigned start, unsigned* output);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to