Ignore:
Timestamp:
Jul 16, 2015, 7:27:22 PM (10 years ago)
Author:
[email protected]
Message:

RegExp::match() should set m_state to ByteCode if compilation fails.
https://bugs.webkit.org/show_bug.cgi?id=147023

Reviewed by Michael Saboff.

A RegExp has a YarrCodeBlock that has 4 MacroAssemblerCodeRefs for compiled code.
If one of these compilations succeeds, RegExp::m_state will be set to JITCode.
Subsequently, if RegExp tries to compile another one of these but fails, m_state
will be left untouched i.e. it still says JITCode. As a result, when
RegExp::match() later tries to execute the non-existant compiled code, it will
crash.

The fix is to downgrade m_state to ByteCode if RegExp ever fails to compile.
This failure should be rare. We'll do the minimal work here to fix the issue and
keep an eye on the perf bots. If perf regresses, we can do some optimization work then.

This issue is difficult to test for since it either requires a low memory condition
to trigger a failed RegExp compilation at the right moment, or for the RegExp to
succeed compilation in the MatchedOnly mode but fail in IncludeSubpatterns mode.
Instead, I manually tested it by instrumenting RegExp::compile() to fail once in every
10 compilation attempts.

  • runtime/RegExp.cpp:

(JSC::RegExp::compile):
(JSC::RegExp::compileMatchOnly):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r184291 r186920  
    290290    if (!pattern.m_containsBackreferences && !pattern.containsUnsignedLengthPattern() && vm->canUseRegExpJIT()) {
    291291        Yarr::jitCompile(pattern, charSize, vm, m_regExpJITCode);
    292 #if ENABLE(YARR_JIT_DEBUG)
    293         if (!m_regExpJITCode.isFallBack())
    294             m_state = JITCode;
    295         else
    296             m_state = ByteCode;
    297 #else
    298292        if (!m_regExpJITCode.isFallBack()) {
    299293            m_state = JITCode;
    300294            return;
    301295        }
    302 #endif
    303296    }
    304297#else
     
    306299#endif
    307300
     301    m_state = ByteCode;
    308302    m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
    309303}
     
    415409    if (!pattern.m_containsBackreferences && !pattern.containsUnsignedLengthPattern() && vm->canUseRegExpJIT()) {
    416410        Yarr::jitCompile(pattern, charSize, vm, m_regExpJITCode, Yarr::MatchOnly);
    417 #if ENABLE(YARR_JIT_DEBUG)
    418         if (!m_regExpJITCode.isFallBack())
    419             m_state = JITCode;
    420         else
    421             m_state = ByteCode;
    422 #else
    423411        if (!m_regExpJITCode.isFallBack()) {
    424412            m_state = JITCode;
    425413            return;
    426414        }
    427 #endif
    428415    }
    429416#else
     
    431418#endif
    432419
     420    m_state = ByteCode;
    433421    m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
    434422}
Note: See TracChangeset for help on using the changeset viewer.