Changeset 288476 in webkit for trunk/Source/JavaScriptCore/yarr


Ignore:
Timestamp:
Jan 24, 2022, 3:20:23 PM (3 years ago)
Author:
Mikhail R. Gadelha
Message:

[JSC][32bit] Fix regexp crash on ARMv7
https://bugs.webkit.org/show_bug.cgi?id=234476

Reviewed by Yusuke Suzuki.

This patch fixes several regexp crashes on ARMv7 due to an incorrect
offset to retrieve the 5th argument from the stack: in ARMv7, only
4 arguments are passed via registers r0-r3i, and any other argument is
placed on the stack, however, YarrJIT was trying to get the 5th arg
from a fixed offset, so because the generateEnter() method pushed
register into the stack, the offset was wrong. This patch fixes how
the offset is calculated for MIPS and ARMv7.

This patch also introduces some small changes:

  1. Added static_asserts that the YarrJIT calls do indeed have 5 arguments

and that the 5th argument has the type that we expect (MatchingContextHolder*).

  1. Removed an unnecessary pointer from the MatchingContextHolder

constructor.

  1. Fixed some warnings in the YarrJIT code here and there.
  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileRegExpTestInline):

  • runtime/RegExpInlines.h:

(JSC::RegExp::matchInline):

  • yarr/YarrJIT.cpp:
  • yarr/YarrMatchingContextHolder.h:

(JSC::Yarr::MatchingContextHolder::MatchingContextHolder):

Location:
trunk/Source/JavaScriptCore/yarr
Files:
4 edited

Legend:

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

    r288401 r288476  
    2828#include "YarrJIT.h"
    2929
     30#include "CCallHelpers.h"
    3031#include "LinkBuffer.h"
    3132#include "Options.h"
     
    187188class YarrGenerator final : public YarrJITInfo {
    188189
    189 #ifdef  JIT_UNICODE_EXPRESSIONS
    190     const MacroAssembler::TrustedImm32 surrogateTagMask = MacroAssembler::TrustedImm32(0xfffffc00);
    191 #endif
    192 
    193190#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
    194191    struct ParenContextSizes {
     
    604601
    605602        // Is the character a leading surrogate?
    606         m_jit.and32(YarrJITDefaultRegisters::surrogateTagMask, resultReg, m_regs.unicodeTemp);
     603        m_jit.and32(m_regs.surrogateTagMask, resultReg, m_regs.unicodeTemp);
    607604        notUnicode.append(m_jit.branch32(MacroAssembler::NotEqual, m_regs.unicodeTemp, m_regs.leadingSurrogateTag));
    608605
     
    613610        // Is the character a trailing surrogate?
    614611        m_jit.load16Unaligned(MacroAssembler::Address(m_regs.regUnicodeInputAndTrail), m_regs.regUnicodeInputAndTrail);
    615         m_jit.and32(YarrJITDefaultRegisters::surrogateTagMask, m_regs.regUnicodeInputAndTrail, m_regs.unicodeTemp);
     612        m_jit.and32(m_regs.surrogateTagMask, m_regs.regUnicodeInputAndTrail, m_regs.unicodeTemp);
    616613        notUnicode.append(m_jit.branch32(MacroAssembler::NotEqual, m_regs.unicodeTemp, m_regs.trailingSurrogateTag));
    617614
     
    39623959    void generateEnter()
    39633960    {
     3961        auto pushInEnter = [&](GPRReg gpr) {
     3962            m_jit.push(gpr);
     3963            m_pushCountInEnter += 1;
     3964        };
     3965
     3966        auto pushPairInEnter = [&](GPRReg gpr1, GPRReg gpr2) {
     3967            m_jit.pushPair(gpr1, gpr2);
     3968            m_pushCountInEnter += 2;
     3969        };
     3970
    39643971#if CPU(X86_64)
    3965         m_jit.push(X86Registers::ebp);
    3966         m_jit.move(MacroAssembler::stackPointerRegister, X86Registers::ebp);
     3972        UNUSED_VARIABLE(pushPairInEnter);
     3973        m_jit.emitFunctionPrologue();
    39673974
    39683975        if (m_pattern.m_saveInitialStartValue)
    3969             m_jit.push(X86Registers::ebx);
     3976            pushInEnter(X86Registers::ebx);
    39703977
    39713978#if OS(WINDOWS)
    3972         m_jit.push(X86Registers::edi);
     3979        pushInEnter(X86Registers::edi);
    39733980#endif
    39743981#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
    39753982        if (m_containsNestedSubpatterns) {
    39763983#if OS(WINDOWS)
    3977             m_jit.push(X86Registers::esi);
    3978 #endif
    3979             m_jit.push(X86Registers::r12);
     3984            pushInEnter(X86Registers::esi);
     3985#endif
     3986            pushInEnter(X86Registers::r12);
    39803987        }
    39813988#endif
    39823989
    39833990        if (m_decodeSurrogatePairs) {
    3984             m_jit.push(X86Registers::r13);
    3985             m_jit.push(X86Registers::r14);
    3986             m_jit.push(X86Registers::r15);
     3991            pushInEnter(X86Registers::r13);
     3992            pushInEnter(X86Registers::r14);
     3993            pushInEnter(X86Registers::r15);
    39873994        }
    39883995#if OS(WINDOWS)
    39893996        if (m_compileMode == JITCompileMode::IncludeSubpatterns)
    3990             m_jit.loadPtr(MacroAssembler::Address(X86Registers::ebp, 6 * sizeof(void*)), m_regs.output);
     3997            m_jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, 6 * sizeof(void*)), m_regs.output);
    39913998        // rcx is the pointer to the allocated space for result in x64 Windows.
    3992         m_jit.push(X86Registers::ecx);
     3999        pushInEnter(X86Registers::ecx);
    39934000#endif
    39944001#elif CPU(ARM64)
     4002        UNUSED_VARIABLE(pushInEnter);
    39954003        if (!Options::useJITCage())
    39964004            m_jit.tagReturnAddress();
    39974005        if (m_decodeSurrogatePairs) {
    39984006            if (!Options::useJITCage())
    3999                 m_jit.pushPair(MacroAssembler::framePointerRegister, MacroAssembler::linkRegister);
     4007                pushPairInEnter(MacroAssembler::framePointerRegister, MacroAssembler::linkRegister);
    40004008            m_jit.move(MacroAssembler::TrustedImm32(0x10000), m_regs.supplementaryPlanesBase);
    40014009            m_jit.move(MacroAssembler::TrustedImm32(0xd800), m_regs.leadingSurrogateTag);
     
    40034011        }
    40044012#elif CPU(ARM_THUMB2)
    4005         m_jit.push(ARMRegisters::r4);
    4006         m_jit.push(ARMRegisters::r5);
    4007         m_jit.push(ARMRegisters::r6);
    4008         m_jit.push(ARMRegisters::r8);
    4009         m_jit.push(ARMRegisters::r10);
     4013        UNUSED_VARIABLE(pushPairInEnter);
     4014        pushInEnter(ARMRegisters::r4);
     4015        pushInEnter(ARMRegisters::r5);
     4016        pushInEnter(ARMRegisters::r6);
     4017        pushInEnter(ARMRegisters::r8);
     4018        pushInEnter(ARMRegisters::r10);
    40104019#elif CPU(RISCV64)
     4020        UNUSED_VARIABLE(pushInEnter);
    40114021        if (m_decodeSurrogatePairs)
    4012             m_jit.pushPair(MacroAssembler::framePointerRegister, MacroAssembler::linkRegister);
    4013 #elif CPU(MIPS)
    4014         // Do nothing.
     4022            pushPairInEnter(MacroAssembler::framePointerRegister, MacroAssembler::linkRegister);
     4023#else
     4024        UNUSED_VARIABLE(pushInEnter);
     4025        UNUSED_VARIABLE(pushPairInEnter);
    40154026#endif
    40164027    }
     
    40534064        if (m_pattern.m_saveInitialStartValue)
    40544065            m_jit.pop(X86Registers::ebx);
    4055         m_jit.pop(X86Registers::ebp);
     4066        m_jit.emitFunctionEpilogue();
    40564067#elif CPU(ARM64)
    40574068        if (m_decodeSurrogatePairs) {
     
    40684079        if (m_decodeSurrogatePairs)
    40694080            m_jit.popPair(MacroAssembler::framePointerRegister, MacroAssembler::linkRegister);
    4070 #elif CPU(MIPS)
    4071         // Do nothing
    4072 #endif
     4081#endif
     4082
    40734083#if CPU(ARM64E)
    40744084        if (Options::useJITCage())
     
    40874097
    40884098public:
    4089     YarrGenerator(MacroAssembler& jit, const VM* vm, YarrCodeBlock* codeBlock, const YarrJITRegs& regs, YarrPattern& pattern, const String& patternString, CharSize charSize, JITCompileMode compileMode)
     4099    YarrGenerator(CCallHelpers& jit, const VM* vm, YarrCodeBlock* codeBlock, const YarrJITRegs& regs, YarrPattern& pattern, const String& patternString, CharSize charSize, JITCompileMode compileMode)
    40904100        : m_jit(jit)
    40914101        , m_vm(vm)
     
    41064116    }
    41074117
    4108     YarrGenerator(MacroAssembler& jit, const VM* vm, YarrBoyerMoyerData* yarrBMData, const YarrJITRegs& regs, YarrPattern& pattern, const String& patternString, CharSize charSize, JITCompileMode compileMode)
     4118    YarrGenerator(CCallHelpers& jit, const VM* vm, YarrBoyerMoyerData* yarrBMData, const YarrJITRegs& regs, YarrPattern& pattern, const String& patternString, CharSize charSize, JITCompileMode compileMode)
    41094119        : m_jit(jit)
    41104120        , m_vm(vm)
     
    41404150    }
    41414151
     4152    template<typename OperationType>
     4153    static constexpr void functionChecks()
     4154    {
     4155        static_assert(FunctionTraits<OperationType>::cCallArity() == 5, "YarrJITCode takes 5 arguments");
     4156        static_assert(std::is_same<MatchingContextHolder*, typename FunctionTraits<OperationType>::template ArgumentType<4>>::value, "MatchingContextHolder* is expected as the function 5th argument");
     4157    }
     4158
    41424159    void compile(YarrCodeBlock& codeBlock)
    41434160    {
     
    41924209            // Check stack size
    41934210            m_jit.addPtr(MacroAssembler::TrustedImm32(-callFrameSizeInBytes), MacroAssembler::stackPointerRegister, m_regs.regT0);
     4211
     4212            // Make sure that the JITed functions have 5 parameters and that the 5th argument is a MatchingContextHolder*
     4213            functionChecks<YarrCodeBlock::YarrJITCode8>();
     4214            functionChecks<YarrCodeBlock::YarrJITCode16>();
     4215            functionChecks<YarrCodeBlock::YarrJITCodeMatchOnly8>();
     4216            functionChecks<YarrCodeBlock::YarrJITCodeMatchOnly16>();
    41944217#if CPU(X86_64) && OS(WINDOWS)
    41954218            // matchingContext is the 5th argument, it is found on the stack.
    41964219            MacroAssembler::RegisterID matchingContext = m_regs.regT1;
    4197             m_jit.loadPtr(MacroAssembler::Address(X86Registers::ebp, 7 * sizeof(void*)), matchingContext);
     4220            m_jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, 7 * sizeof(void*)), matchingContext);
    41984221#elif CPU(ARM_THUMB2) || CPU(MIPS)
    4199             // matchingContext is the 5th argument, it is found on the stack.
     4222            // Not enough argument registers: try to load the 5th argument from the stack
    42004223            MacroAssembler::RegisterID matchingContext = m_regs.regT1;
    4201             m_jit.loadPtr(MacroAssembler::Address(MacroAssembler::stackPointerRegister, 4 * sizeof(void*)), matchingContext);
     4224
     4225            // The argument will be in an offset that depends on the arch and the number of registers we pushed into the stack
     4226            // POKE_ARGUMENT_OFFSET: MIPS reserves space in the stack for all arguments, so we add +4 offset
     4227            // m_pushCountInEnter: number of registers pushed into the stack (see generateEnter())
     4228            unsigned offset = POKE_ARGUMENT_OFFSET + m_pushCountInEnter;
     4229            m_jit.loadPtr(MacroAssembler::Address(MacroAssembler::stackPointerRegister, offset * sizeof(void*)), matchingContext);
    42024230#else
    42034231            MacroAssembler::RegisterID matchingContext = m_regs.matchingContext;
     
    46194647
    46204648private:
    4621     MacroAssembler& m_jit;
     4649    CCallHelpers& m_jit;
    46224650    const VM* m_vm;
    46234651    YarrCodeBlock* m_codeBlock;
     
    46734701   
    46744702    std::unique_ptr<YarrDisassembler> m_disassembler;
     4703
     4704    // Member is used to count the number of GPR pushed into the stack when
     4705    // entering JITed code. It is used to figure out if an function argument
     4706    // offset in the stack if there wasn't enough registers to pass it, e.g.,
     4707    // ARMv7 and MIPS only use 4 registers to pass function arguments.
     4708    unsigned m_pushCountInEnter { 0 };
    46754709};
    46764710
     
    47074741void jitCompile(YarrPattern& pattern, String& patternString, CharSize charSize, VM* vm, YarrCodeBlock& codeBlock, JITCompileMode mode)
    47084742{
    4709     MacroAssembler masm;
     4743    CCallHelpers masm;
    47104744
    47114745    ASSERT(mode == JITCompileMode::MatchOnly || mode == JITCompileMode::IncludeSubpatterns);
     
    47284762#endif
    47294763
    4730 void jitCompileInlinedTest(StackCheck* m_compilationThreadStackChecker, const String& patternString, OptionSet<Yarr::Flags> flags, CharSize charSize, const VM* vm, YarrBoyerMoyerData& boyerMooreData, MacroAssembler& jit, YarrJITRegisters& jitRegisters)
     4764void jitCompileInlinedTest(StackCheck* m_compilationThreadStackChecker, const String& patternString, OptionSet<Yarr::Flags> flags, CharSize charSize, const VM* vm, YarrBoyerMoyerData& boyerMooreData, CCallHelpers& jit, YarrJITRegisters& jitRegisters)
    47314765{
    47324766    Yarr::ErrorCode errorCode;
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.h

    r288401 r288476  
    4444namespace JSC {
    4545
    46 class VM;
     46class CCallHelpers;
    4747class ExecutablePool;
    4848class MacroAssembler;
     49class VM;
    4950
    5051namespace Yarr {
     
    272273    WTF_MAKE_NONCOPYABLE(YarrCodeBlock);
    273274
    274     using YarrJITCode8 = SlowPathReturnType (*)(const LChar* input, UCPURegister start, UCPURegister length, int* output, MatchingContextHolder& matchingContext) YARR_CALL;
    275     using YarrJITCode16 = SlowPathReturnType (*)(const UChar* input, UCPURegister start, UCPURegister length, int* output, MatchingContextHolder& matchingContext) YARR_CALL;
    276     using YarrJITCodeMatchOnly8 = SlowPathReturnType (*)(const LChar* input, UCPURegister start, UCPURegister length, void*, MatchingContextHolder& matchingContext) YARR_CALL;
    277     using YarrJITCodeMatchOnly16 = SlowPathReturnType (*)(const UChar* input, UCPURegister start, UCPURegister length, void*, MatchingContextHolder& matchingContext) YARR_CALL;
    278 
    279275public:
     276    using YarrJITCode8 = SlowPathReturnType (*)(const LChar* input, UCPURegister start, UCPURegister length, int* output, MatchingContextHolder*) YARR_CALL;
     277    using YarrJITCode16 = SlowPathReturnType (*)(const UChar* input, UCPURegister start, UCPURegister length, int* output, MatchingContextHolder*) YARR_CALL;
     278    using YarrJITCodeMatchOnly8 = SlowPathReturnType (*)(const LChar* input, UCPURegister start, UCPURegister length, void*, MatchingContextHolder*) YARR_CALL;
     279    using YarrJITCodeMatchOnly16 = SlowPathReturnType (*)(const UChar* input, UCPURegister start, UCPURegister length, void*, MatchingContextHolder*) YARR_CALL;
     280
    280281    YarrCodeBlock() = default;
    281282
     
    327328    InlineStats& get16BitInlineStats() { return  m_matchOnly16Stats; }
    328329
    329     MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output, MatchingContextHolder& matchingContext)
     330    MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output, MatchingContextHolder* matchingContext)
    330331    {
    331332        ASSERT(has8BitCode());
    332333#if CPU(ARM64E)
    333334        if (Options::useJITCage())
    334             return MatchResult(vmEntryToYarrJIT(input, start, length, output, &matchingContext, retagCodePtr<Yarr8BitPtrTag, YarrEntryPtrTag>(m_ref8.code().executableAddress())));
     335            return MatchResult(vmEntryToYarrJIT(input, start, length, output, matchingContext, retagCodePtr<Yarr8BitPtrTag, YarrEntryPtrTag>(m_ref8.code().executableAddress())));
    335336#endif
    336337        return MatchResult(untagCFunctionPtr<YarrJITCode8, Yarr8BitPtrTag>(m_ref8.code().executableAddress())(input, start, length, output, matchingContext));
    337338    }
    338339
    339     MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output, MatchingContextHolder& matchingContext)
     340    MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output, MatchingContextHolder* matchingContext)
    340341    {
    341342        ASSERT(has16BitCode());
    342343#if CPU(ARM64E)
    343344        if (Options::useJITCage())
    344             return MatchResult(vmEntryToYarrJIT(input, start, length, output, &matchingContext, retagCodePtr<Yarr16BitPtrTag, YarrEntryPtrTag>(m_ref16.code().executableAddress())));
     345            return MatchResult(vmEntryToYarrJIT(input, start, length, output, matchingContext, retagCodePtr<Yarr16BitPtrTag, YarrEntryPtrTag>(m_ref16.code().executableAddress())));
    345346#endif
    346347        return MatchResult(untagCFunctionPtr<YarrJITCode16, Yarr16BitPtrTag>(m_ref16.code().executableAddress())(input, start, length, output, matchingContext));
    347348    }
    348349
    349     MatchResult execute(const LChar* input, unsigned start, unsigned length, MatchingContextHolder& matchingContext)
     350    MatchResult execute(const LChar* input, unsigned start, unsigned length, MatchingContextHolder* matchingContext)
    350351    {
    351352        ASSERT(has8BitCodeMatchOnly());
    352353#if CPU(ARM64E)
    353354        if (Options::useJITCage())
    354             return MatchResult(vmEntryToYarrJIT(input, start, length, nullptr, &matchingContext, retagCodePtr<YarrMatchOnly8BitPtrTag, YarrEntryPtrTag>(m_matchOnly8.code().executableAddress())));
     355            return MatchResult(vmEntryToYarrJIT(input, start, length, nullptr, matchingContext, retagCodePtr<YarrMatchOnly8BitPtrTag, YarrEntryPtrTag>(m_matchOnly8.code().executableAddress())));
    355356#endif
    356357        return MatchResult(untagCFunctionPtr<YarrJITCodeMatchOnly8, YarrMatchOnly8BitPtrTag>(m_matchOnly8.code().executableAddress())(input, start, length, nullptr, matchingContext));
    357358    }
    358359
    359     MatchResult execute(const UChar* input, unsigned start, unsigned length, MatchingContextHolder& matchingContext)
     360    MatchResult execute(const UChar* input, unsigned start, unsigned length, MatchingContextHolder* matchingContext)
    360361    {
    361362        ASSERT(has16BitCodeMatchOnly());
    362363#if CPU(ARM64E)
    363364        if (Options::useJITCage())
    364             return MatchResult(vmEntryToYarrJIT(input, start, length, nullptr, &matchingContext, retagCodePtr<YarrMatchOnly16BitPtrTag, YarrEntryPtrTag>(m_matchOnly16.code().executableAddress())));
     365            return MatchResult(vmEntryToYarrJIT(input, start, length, nullptr, matchingContext, retagCodePtr<YarrMatchOnly16BitPtrTag, YarrEntryPtrTag>(m_matchOnly16.code().executableAddress())));
    365366#endif
    366367        return MatchResult(untagCFunctionPtr<YarrJITCodeMatchOnly16, YarrMatchOnly16BitPtrTag>(m_matchOnly16.code().executableAddress())(input, start, length, nullptr, matchingContext));
     
    440441class YarrJITRegisters;
    441442
    442 void jitCompileInlinedTest(StackCheck*, const String&, OptionSet<Yarr::Flags>, CharSize, const VM*, YarrBoyerMoyerData&, MacroAssembler&, YarrJITRegisters&);
     443void jitCompileInlinedTest(StackCheck*, const String&, OptionSet<Yarr::Flags>, CharSize, const VM*, YarrBoyerMoyerData&, CCallHelpers&, YarrJITRegisters&);
    443444#endif
    444445
  • trunk/Source/JavaScriptCore/yarr/YarrJITRegisters.h

    r288401 r288476  
    207207    const MacroAssembler::TrustedImm32 leadingSurrogateTag = MacroAssembler::TrustedImm32(0xd800);
    208208    const MacroAssembler::TrustedImm32 trailingSurrogateTag = MacroAssembler::TrustedImm32(0xdc00);
     209    const MacroAssembler::TrustedImm32 surrogateTagMask = MacroAssembler::TrustedImm32(0xfffffc00);
    209210};
    210211#endif
  • trunk/Source/JavaScriptCore/yarr/YarrMatchingContextHolder.h

    r288401 r288476  
    3838namespace Yarr {
    3939
    40 class YarrCodeBlock;
    41 
    4240class MatchingContextHolder {
    4341    WTF_FORBID_HEAP_ALLOCATION;
    4442public:
    45     MatchingContextHolder(VM&, YarrCodeBlock*, RegExp*, MatchFrom);
     43    MatchingContextHolder(VM&, bool, RegExp*, MatchFrom);
    4644    ~MatchingContextHolder();
    4745
     
    6260};
    6361
    64 inline MatchingContextHolder::MatchingContextHolder(VM& vm, YarrCodeBlock* yarrCodeBlock, RegExp* regExp, MatchFrom matchFrom)
     62inline MatchingContextHolder::MatchingContextHolder(VM& vm, bool usesPatternContextBuffer, RegExp* regExp, MatchFrom matchFrom)
    6563    : m_vm(vm)
    6664    , m_matchFrom(matchFrom)
     
    7573
    7674#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
    77     if (yarrCodeBlock && yarrCodeBlock->usesPatternContextBuffer()) {
     75    if (usesPatternContextBuffer) {
    7876        m_patternContextBuffer = m_vm.acquireRegExpPatternContexBuffer();
    7977        m_patternContextBufferSize = VM::patternContextBufferSize;
    8078    }
    8179#else
    82     UNUSED_PARAM(yarrCodeBlock);
     80    UNUSED_PARAM(usesPatternContextBuffer);
    8381#endif
    8482}
Note: See TracChangeset for help on using the changeset viewer.