Ignore:
Timestamp:
Mar 26, 2020, 4:27:57 PM (5 years ago)
Author:
[email protected]
Message:

Refactor YARR Stack Overflow Checks
https://bugs.webkit.org/show_bug.cgi?id=209435
rdar://problem/58988252

Reviewed by Mark Lam.

JSTests:

Added a new test and removed a now obsolete test.

  • stress/regexp-compile-oom.js: Removed because the test is no longer valid.

Previously when therer where different stack check mechanisims we failed different.
This test was based on the different failure modes. With these changes, most of
the contain subtests no longer throw as this test expects.

  • stress/regexp-huge-oom.js: Added.

(shouldBe):
(shouldThrow):

Source/JavaScriptCore:

Refactored stack checks in YARR code including adding a stack check to the YARR JIT'ed code.
The C++ code including the parser, byte code compiler and interpreter now all use StackCheck.
The JIT'ed code needs a stack limit passed via a parameter since the JIT'ed code can be
called from the compiler thread when compiling DFG / FTL code.

Instead of adding a new parameter, consolidated the two pattern context buffer values, buffer
pointer and size, with the new stack limit into a new MatchingContextHolder, an RAII object.
The MatchingContextHolder constructor uses either the VM stack limit or the current thread's
stack limit depending on how it is called.

  • runtime/RegExp.cpp:

(JSC::RegExp::finishCreation):
(JSC::RegExp::byteCodeCompileIfNecessary):
(JSC::RegExp::compile):
(JSC::RegExp::matchConcurrently):
(JSC::RegExp::compileMatchOnly):

  • runtime/RegExp.h:
  • runtime/RegExpInlines.h:

(JSC::RegExp::matchInline):
(JSC::PatternContextBufferHolder::PatternContextBufferHolder): Deleted.
(JSC::PatternContextBufferHolder::~PatternContextBufferHolder): Deleted.
(JSC::PatternContextBufferHolder::buffer): Deleted.
(JSC::PatternContextBufferHolder::size): Deleted.
(): Deleted.

  • yarr/Yarr.h:
  • yarr/YarrInterpreter.cpp:

(JSC::Yarr::Interpreter::matchDisjunction):
(JSC::Yarr::Interpreter::isSafeToRecurse):

  • yarr/YarrJIT.cpp:

(JSC::Yarr::MatchingContextHolder::MatchingContextHolder):
(JSC::Yarr::MatchingContextHolder::~MatchingContextHolder):
(JSC::Yarr::YarrGenerator::initParenContextFreeList):
(JSC::Yarr::YarrGenerator::alignCallFrameSizeInBytes):
(JSC::Yarr::YarrGenerator::compile):
(JSC::Yarr::YarrGenerator::initCallFrame): Deleted.

  • yarr/YarrJIT.h:

(JSC::Yarr::MatchingContextHolder::offsetOfStackLimit):
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBuffer):
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBufferSize):
(JSC::Yarr::YarrCodeBlock::execute):

  • yarr/YarrPattern.cpp:

(JSC::Yarr::YarrPatternConstructor::YarrPatternConstructor):
(JSC::Yarr::YarrPatternConstructor::isSafeToRecurse):
(JSC::Yarr::YarrPattern::compile):
(JSC::Yarr::YarrPattern::YarrPattern):
(JSC::Yarr::YarrPatternConstructor::isSafeToRecurse const): Deleted.

  • yarr/YarrPattern.h:

LayoutTests:

Updated test for improved stack overflow checking.

  • js/script-tests/stack-overflow-regexp.js:

(shouldThrow.recursiveCall):
(shouldThrow):
(recursiveCall):

  • js/stack-overflow-regexp-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp

    r259026 r259092  
    3434#include <wtf/DataLog.h>
    3535#include <wtf/Optional.h>
    36 #include <wtf/StackPointer.h>
     36#include <wtf/StackCheck.h>
    3737#include <wtf/Threading.h>
    3838#include <wtf/Vector.h>
     
    437437class YarrPatternConstructor {
    438438public:
    439     YarrPatternConstructor(YarrPattern& pattern, void* stackLimit)
     439    YarrPatternConstructor(YarrPattern& pattern)
    440440        : m_pattern(pattern)
    441441        , m_characterClassConstructor(pattern.ignoreCase(), pattern.unicode() ? CanonicalMode::Unicode : CanonicalMode::UCS2)
    442         , m_stackLimit(stackLimit)
    443442    {
    444443        auto body = makeUnique<PatternDisjunction>();
     
    11021101
    11031102private:
    1104     bool isSafeToRecurse() const
    1105     {
    1106         if (!m_stackLimit)
    1107             return true;
    1108         int8_t* curr = reinterpret_cast<int8_t*>(currentStackPointer());
    1109         int8_t* limit = reinterpret_cast<int8_t*>(m_stackLimit);
    1110         return curr >= limit;
    1111     }
     1103    inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); }
    11121104
    11131105    YarrPattern& m_pattern;
    11141106    PatternAlternative* m_alternative;
    11151107    CharacterClassConstructor m_characterClassConstructor;
    1116     void* m_stackLimit;
     1108    StackCheck m_stackCheck;
    11171109    ErrorCode m_error { ErrorCode::NoError };
    11181110    bool m_invertCharacterClass;
     
    11201112};
    11211113
    1122 ErrorCode YarrPattern::compile(const String& patternString, void* stackLimit)
     1114ErrorCode YarrPattern::compile(const String& patternString)
    11231115{
    1124     YarrPatternConstructor constructor(*this, stackLimit);
     1116    YarrPatternConstructor constructor(*this);
    11251117
    11261118    {
     
    11491141}
    11501142
    1151 YarrPattern::YarrPattern(const String& pattern, OptionSet<Flags> flags, ErrorCode& error, void* stackLimit)
     1143YarrPattern::YarrPattern(const String& pattern, OptionSet<Flags> flags, ErrorCode& error)
    11521144    : m_containsBackreferences(false)
    11531145    , m_containsBOL(false)
     
    11581150{
    11591151    ASSERT(m_flags != Flags::DeletedValue);
    1160     error = compile(pattern, stackLimit);
     1152    error = compile(pattern);
    11611153}
    11621154
Note: See TracChangeset for help on using the changeset viewer.