Changeset 218869 in webkit


Ignore:
Timestamp:
Jun 28, 2017 12:11:57 AM (7 years ago)
Author:
mark.lam@apple.com
Message:

Ensure that computed new stack pointer values do not underflow.
https://bugs.webkit.org/show_bug.cgi?id=173700
<rdar://problem/32926032>

Reviewed by Filip Pizlo and Saam Barati.

  1. Added a RELEASE_ASSERT to BytecodeGenerator::generate() to ensure that m_numCalleeLocals is sane.
  1. Added underflow checks in LLInt code and VarargsFrame code.
  1. Introduce minimumReservedZoneSize, which is hardcoded to 16K. Ensure that Options::reservedZoneSize() is at least minimumReservedZoneSize. Ensure that Options::softReservedZoneSize() is at least greater than Options::reservedZoneSize() by minimumReservedZoneSize.
  1. Ensure that stack checks emitted by JIT tiers include an underflow check if and only if the max size of the frame is greater than Options::reservedZoneSize().

By design, we are guaranteed to have at least Options::reservedZoneSize() bytes
of memory at the bottom (end) of the stack. This means that, at any time, the
frame pointer must be at least Options::reservedZoneSize() bytes away from the
end of the stack. Hence, if the max frame size is less than
Options::reservedZoneSize(), there's no way that frame pointer - max
frame size can underflow, and we can elide the underflow check.

Note that we use Options::reservedZoneSize() instead of
Options::softReservedZoneSize() for determine if we need an underflow check.
This is because the softStackLimit that is used for stack checks can be set
based on Options::reservedZoneSize() during error handling (e.g. when creating
strings for instantiating the Error object). Hence, the guaranteed minimum of
distance between the frame pointer and the end of the stack is
Options::reservedZoneSize() and nor Options::softReservedZoneSize().

Note also that we ensure that Options::reservedZoneSize() is at least
minimumReservedZoneSize (i.e. 16K). In typical deployments,
Options::reservedZoneSize() may be larger. Using Options::reservedZoneSize()
instead of minimumReservedZoneSize gives us more chances to elide underflow
checks.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::requiredRegisterCountForExecutionAndExit):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::lower):

  • jit/JIT.cpp:

(JSC::JIT::compileWithoutLinking):

  • jit/SetupVarargsFrame.cpp:

(JSC::emitSetupVarargsFrameFastCase):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/MinimumReservedZoneSize.h: Added.
  • runtime/Options.cpp:

(JSC::recomputeDependentOptions):

  • runtime/VM.cpp:

(JSC::VM::updateStackLimits):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::callWebAssemblyFunction):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r218868 r218869  
     12017-06-28  Mark Lam  <mark.lam@apple.com>
     2
     3        Ensure that computed new stack pointer values do not underflow.
     4        https://bugs.webkit.org/show_bug.cgi?id=173700
     5        <rdar://problem/32926032>
     6
     7        Reviewed by Filip Pizlo and Saam Barati.
     8
     9        1. Added a RELEASE_ASSERT to BytecodeGenerator::generate() to ensure that
     10           m_numCalleeLocals is sane.
     11
     12        2. Added underflow checks in LLInt code and VarargsFrame code.
     13
     14        3. Introduce minimumReservedZoneSize, which is hardcoded to 16K.
     15           Ensure that Options::reservedZoneSize() is at least minimumReservedZoneSize.
     16           Ensure that Options::softReservedZoneSize() is at least greater than
     17           Options::reservedZoneSize() by minimumReservedZoneSize.
     18
     19        4. Ensure that stack checks emitted by JIT tiers include an underflow check if
     20           and only if the max size of the frame is greater than Options::reservedZoneSize().
     21
     22           By design, we are guaranteed to have at least Options::reservedZoneSize() bytes
     23           of memory at the bottom (end) of the stack.  This means that, at any time, the
     24           frame pointer must be at least Options::reservedZoneSize() bytes away from the
     25           end of the stack.  Hence, if the max frame size is less than
     26           Options::reservedZoneSize(), there's no way that frame pointer - max
     27           frame size can underflow, and we can elide the underflow check.
     28
     29           Note that we use Options::reservedZoneSize() instead of
     30           Options::softReservedZoneSize() for determine if we need an underflow check.
     31           This is because the softStackLimit that is used for stack checks can be set
     32           based on Options::reservedZoneSize() during error handling (e.g. when creating
     33           strings for instantiating the Error object).  Hence, the guaranteed minimum of
     34           distance between the frame pointer and the end of the stack is
     35           Options::reservedZoneSize() and nor Options::softReservedZoneSize().
     36
     37           Note also that we ensure that Options::reservedZoneSize() is at least
     38           minimumReservedZoneSize (i.e. 16K).  In typical deployments,
     39           Options::reservedZoneSize() may be larger.  Using Options::reservedZoneSize()
     40           instead of minimumReservedZoneSize gives us more chances to elide underflow
     41           checks.
     42
     43        * JavaScriptCore.xcodeproj/project.pbxproj:
     44        * bytecompiler/BytecodeGenerator.cpp:
     45        (JSC::BytecodeGenerator::generate):
     46        * dfg/DFGGraph.cpp:
     47        (JSC::DFG::Graph::requiredRegisterCountForExecutionAndExit):
     48        * dfg/DFGJITCompiler.cpp:
     49        (JSC::DFG::JITCompiler::compile):
     50        (JSC::DFG::JITCompiler::compileFunction):
     51        * ftl/FTLLowerDFGToB3.cpp:
     52        (JSC::FTL::DFG::LowerDFGToB3::lower):
     53        * jit/JIT.cpp:
     54        (JSC::JIT::compileWithoutLinking):
     55        * jit/SetupVarargsFrame.cpp:
     56        (JSC::emitSetupVarargsFrameFastCase):
     57        * llint/LLIntSlowPaths.cpp:
     58        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     59        * llint/LowLevelInterpreter.asm:
     60        * llint/LowLevelInterpreter32_64.asm:
     61        * llint/LowLevelInterpreter64.asm:
     62        * runtime/MinimumReservedZoneSize.h: Added.
     63        * runtime/Options.cpp:
     64        (JSC::recomputeDependentOptions):
     65        * runtime/VM.cpp:
     66        (JSC::VM::updateStackLimits):
     67        * wasm/WasmB3IRGenerator.cpp:
     68        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
     69        * wasm/js/WebAssemblyFunction.cpp:
     70        (JSC::callWebAssemblyFunction):
     71
    1722017-06-27  JF Bastien  <jfbastien@apple.com>
    273
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r218784 r218869  
    24392439                FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */; };
    24402440                FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2441                FE2A87601F02381600EB31B2 /* MinimumReservedZoneSize.h in Headers */ = {isa = PBXBuildFile; fileRef = FE2A875F1F02381600EB31B2 /* MinimumReservedZoneSize.h */; };
    24412442                FE2E6A7B1D6EA62C0060F896 /* ThrowScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE2E6A7A1D6EA5FE0060F896 /* ThrowScope.cpp */; };
    24422443                FE3022D21E3D73A500BAC493 /* SigillCrashAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE3022D01E3D739600BAC493 /* SigillCrashAnalyzer.cpp */; };
     
    50985099                FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntCLoop.cpp; path = llint/LLIntCLoop.cpp; sourceTree = "<group>"; };
    50995100                FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCLoop.h; path = llint/LLIntCLoop.h; sourceTree = "<group>"; };
     5101                FE2A875F1F02381600EB31B2 /* MinimumReservedZoneSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MinimumReservedZoneSize.h; sourceTree = "<group>"; };
    51005102                FE2E6A7A1D6EA5FE0060F896 /* ThrowScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThrowScope.cpp; sourceTree = "<group>"; };
    51015103                FE3022D01E3D739600BAC493 /* SigillCrashAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SigillCrashAnalyzer.cpp; sourceTree = "<group>"; };
     
    69426944                                90213E3C123A40C200D422F3 /* MemoryStatistics.h */,
    69436945                                7C008CE5187631B600955C24 /* Microtask.h */,
     6946                                FE2A875F1F02381600EB31B2 /* MinimumReservedZoneSize.h */,
    69446947                                E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */,
    69456948                                E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */,
     
    88188821                                0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
    88198822                                0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
     8823                                FE2A87601F02381600EB31B2 /* MinimumReservedZoneSize.h in Headers */,
    88208824                                53C6FEEF1E8ADFA900B18425 /* WasmOpcodeOrigin.h in Headers */,
    88218825                                0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r218861 r218869  
    194194        performGeneratorification(m_codeBlock.get(), m_instructions, m_generatorFrameSymbolTable.get(), m_generatorFrameSymbolTableIndex);
    195195
     196    RELEASE_ASSERT(static_cast<unsigned>(m_codeBlock->numCalleeLocals()) < static_cast<unsigned>(FirstConstantRegisterIndex));
    196197    m_codeBlock->setInstructions(std::make_unique<UnlinkedInstructionStream>(m_instructions));
    197198
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r217108 r218869  
    11/*
    2  * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    11511151unsigned Graph::requiredRegisterCountForExecutionAndExit()
    11521152{
     1153    // FIXME: We should make sure that frameRegisterCount() and requiredRegisterCountForExit()
     1154    // never overflows. https://bugs.webkit.org/show_bug.cgi?id=173852
    11531155    return std::max(frameRegisterCount(), requiredRegisterCountForExit());
    11541156}
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r218794 r218869  
    11/*
    2  * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    355355}
    356356
     357static void emitStackOverflowCheck(JITCompiler& jit, MacroAssembler::JumpList& stackOverflow)
     358{
     359    int frameTopOffset = virtualRegisterForLocal(jit.graph().requiredRegisterCountForExecutionAndExit() - 1).offset() * sizeof(Register);
     360    unsigned maxFrameSize = -frameTopOffset;
     361
     362    jit.addPtr(MacroAssembler::TrustedImm32(frameTopOffset), GPRInfo::callFrameRegister, GPRInfo::regT1);
     363    if (UNLIKELY(maxFrameSize > Options::reservedZoneSize()))
     364        stackOverflow.append(jit.branchPtr(MacroAssembler::Above, GPRInfo::regT1, GPRInfo::callFrameRegister));
     365    stackOverflow.append(jit.branchPtr(MacroAssembler::Above, MacroAssembler::AbsoluteAddress(jit.vm()->addressOfSoftStackLimit()), GPRInfo::regT1));
     366}
     367
    357368void JITCompiler::compile()
    358369{
     
    362373
    363374    // Plant a check that sufficient space is available in the JSStack.
    364     addPtr(TrustedImm32(virtualRegisterForLocal(m_graph.requiredRegisterCountForExecutionAndExit() - 1).offset() * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
    365     Jump stackOverflow = branchPtr(Above, AbsoluteAddress(vm()->addressOfSoftStackLimit()), GPRInfo::regT1);
     375    JumpList stackOverflow;
     376    emitStackOverflowCheck(*this, stackOverflow);
    366377
    367378    addPtr(TrustedImm32(m_graph.stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, stackPointerRegister);
     
    425436    Label fromArityCheck(this);
    426437    // Plant a check that sufficient space is available in the JSStack.
    427     addPtr(TrustedImm32(virtualRegisterForLocal(m_graph.requiredRegisterCountForExecutionAndExit() - 1).offset() * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
    428     Jump stackOverflow = branchPtr(Above, AbsoluteAddress(vm()->addressOfSoftStackLimit()), GPRInfo::regT1);
     438    JumpList stackOverflow;
     439    emitStackOverflowCheck(*this, stackOverflow);
    429440
    430441    // Move the stack pointer down to accommodate locals
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r218794 r218869  
    215215
    216216                unsigned ftlFrameSize = params.proc().frameSize();
    217 
    218                 jit.addPtr(MacroAssembler::TrustedImm32(-std::max(exitFrameSize, ftlFrameSize)), fp, scratch);
    219                 MacroAssembler::Jump stackOverflow = jit.branchPtr(MacroAssembler::Above, addressOfStackLimit, scratch);
     217                unsigned maxFrameSize = std::max(exitFrameSize, ftlFrameSize);
     218
     219                jit.addPtr(MacroAssembler::TrustedImm32(-maxFrameSize), fp, scratch);
     220                MacroAssembler::JumpList stackOverflow;
     221                if (UNLIKELY(maxFrameSize > Options::reservedZoneSize()))
     222                    stackOverflow.append(jit.branchPtr(MacroAssembler::Above, scratch, fp));
     223                stackOverflow.append(jit.branchPtr(MacroAssembler::Above, addressOfStackLimit, scratch));
    220224
    221225                params.addLatePath([=] (CCallHelpers& jit) {
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r218794 r218869  
    662662    }
    663663
    664     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, regT1);
    665     Jump stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfSoftStackLimit()), regT1);
     664    int frameTopOffset = stackPointerOffsetFor(m_codeBlock) * sizeof(Register);
     665    unsigned maxFrameSize = -frameTopOffset;
     666    addPtr(TrustedImm32(frameTopOffset), callFrameRegister, regT1);
     667    JumpList stackOverflow;
     668    if (UNLIKELY(maxFrameSize > Options::reservedZoneSize()))
     669        stackOverflow.append(branchPtr(Above, regT1, callFrameRegister));
     670    stackOverflow.append(branchPtr(Above, AbsoluteAddress(m_vm->addressOfSoftStackLimit()), regT1));
    666671
    667672    move(regT1, stackPointerRegister);
  • trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp

    r214531 r218869  
    11/*
    2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8383    emitSetVarargsFrame(jit, scratchGPR1, true, numUsedSlotsGPR, scratchGPR2);
    8484
     85    slowCase.append(jit.branchPtr(CCallHelpers::Above, scratchGPR2, GPRInfo::callFrameRegister));
    8586    slowCase.append(jit.branchPtr(CCallHelpers::Above, CCallHelpers::AbsoluteAddress(vm.addressOfSoftStackLimit()), scratchGPR2));
    8687
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r218868 r218869  
    511511    // throw the StackOverflowError unconditionally.
    512512#if !ENABLE(JIT)
    513     ASSERT(!vm.interpreter->cloopStack().containsAddress(exec->topOfFrame()));
    514     if (LIKELY(vm.ensureStackCapacityFor(exec->topOfFrame())))
    515         LLINT_RETURN_TWO(pc, 0);
     513    Register* topOfFrame = exec->topOfFrame();
     514    if (LIKELY(topOfFrame < exec)) {
     515        ASSERT(!vm.interpreter->cloopStack().containsAddress(topOfFrame));
     516        if (LIKELY(vm.ensureStackCapacityFor(topOfFrame)))
     517            LLINT_RETURN_TWO(pc, 0);
     518    }
    516519#endif
    517520
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r217840 r218869  
    995995    getFrameRegisterSizeForCodeBlock(t1, t0)
    996996    subp cfr, t0, t0
     997    bpa t0, cfr, .needStackCheck
    997998    loadp CodeBlock::m_vm[t1], t2
    998999    if C_LOOP
     
    10021003    end
    10031004
     1005.needStackCheck:
    10041006    # Stack height check failed - need to call a slow_path.
    10051007    # Set up temporary stack pointer for call including callee saves
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r213107 r218869  
    149149    lshiftp 3, t4
    150150    subp sp, t4, t3
     151    bpa t3, sp, .throwStackOverflow
    151152
    152153    # Ensure that we have enough additional stack capacity for the incoming args,
     
    173174    end
    174175
     176.throwStackOverflow:
    175177    subp 8, sp # Align stack for cCall2() to make a call.
    176178    move vm, a0
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r213107 r218869  
    137137    lshiftp 3, t4
    138138    subp sp, t4, t3
     139    bpa t3, sp, .throwStackOverflow
    139140
    140141    # Ensure that we have enough additional stack capacity for the incoming args,
     
    161162    end
    162163
     164.throwStackOverflow:
    163165    move vm, a0
    164166    move protoCallFrame, a1
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r217993 r218869  
    3030#include "LLIntCommon.h"
    3131#include "LLIntData.h"
     32#include "MinimumReservedZoneSize.h"
    3233#include "SigillCrashAnalyzer.h"
    3334#include <algorithm>
     
    497498    if (Options::useSigillCrashAnalyzer())
    498499        enableSigillCrashAnalyzer();
     500
     501    if (Options::reservedZoneSize() < minimumReservedZoneSize)
     502        Options::reservedZoneSize() = minimumReservedZoneSize;
     503    if (Options::softReservedZoneSize() < Options::reservedZoneSize() + minimumReservedZoneSize)
     504        Options::softReservedZoneSize() = Options::reservedZoneSize() + minimumReservedZoneSize;
    499505}
    500506
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r218794 r218869  
    7979#include "Lexer.h"
    8080#include "Lookup.h"
     81#include "MinimumReservedZoneSize.h"
    8182#include "ModuleProgramCodeBlock.h"
    8283#include "NativeStdFunctionCell.h"
     
    671672#endif
    672673
     674    const StackBounds& stack = wtfThreadData().stack();
    673675    size_t reservedZoneSize = Options::reservedZoneSize();
     676    // We should have already ensured that Options::reservedZoneSize() >= minimumReserveZoneSize at
     677    // options initialization time, and the option value should not have been changed thereafter.
     678    // We don't have the ability to assert here that it hasn't changed, but we can at least assert
     679    // that the value is sane.
     680    RELEASE_ASSERT(reservedZoneSize >= minimumReservedZoneSize);
     681
    674682    if (m_stackPointerAtVMEntry) {
    675         ASSERT(wtfThreadData().stack().isGrowingDownward());
     683        ASSERT(stack.isGrowingDownward());
    676684        char* startOfStack = reinterpret_cast<char*>(m_stackPointerAtVMEntry);
    677         m_softStackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), m_currentSoftReservedZoneSize);
    678         m_stackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), reservedZoneSize);
     685        m_softStackLimit = stack.recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), m_currentSoftReservedZoneSize);
     686        m_stackLimit = stack.recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), reservedZoneSize);
    679687    } else {
    680         m_softStackLimit = wtfThreadData().stack().recursionLimit(m_currentSoftReservedZoneSize);
    681         m_stackLimit = wtfThreadData().stack().recursionLimit(reservedZoneSize);
     688        m_softStackLimit = stack.recursionLimit(m_currentSoftReservedZoneSize);
     689        m_stackLimit = stack.recursionLimit(reservedZoneSize);
    682690    }
    683691
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r218216 r218869  
    417417            ));
    418418            const int32_t checkSize = m_makesCalls ? (wasmFrameSize + extraFrameSize).unsafeGet() : wasmFrameSize.unsafeGet();
     419            bool needUnderflowCheck = static_cast<unsigned>(checkSize) > Options::reservedZoneSize();
    419420            // This allows leaf functions to not do stack checks if their frame size is within
    420421            // certain limits since their caller would have already done the check.
    421             if (m_makesCalls || wasmFrameSize >= minimumParentCheckSize) {
     422            if (m_makesCalls || wasmFrameSize >= minimumParentCheckSize || needUnderflowCheck) {
    422423                jit.loadPtr(CCallHelpers::Address(context, Context::offsetOfCachedStackLimit()), scratch2);
    423424                jit.addPtr(CCallHelpers::TrustedImm32(-checkSize), fp, scratch1);
    424                 auto overflow = jit.branchPtr(CCallHelpers::Below, scratch1, scratch2);
     425                MacroAssembler::JumpList overflow;
     426                if (UNLIKELY(needUnderflowCheck))
     427                    overflow.append(jit.branchPtr(CCallHelpers::Above, scratch1, fp));
     428                overflow.append(jit.branchPtr(CCallHelpers::Below, scratch1, scratch2));
    425429                jit.addLinkTask([overflow] (LinkBuffer& linkBuffer) {
    426430                    linkBuffer.link(overflow, CodeLocationLabel(Thunks::singleton().stub(throwStackOverflowFromWasmThunkGenerator).code()));
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r217645 r218869  
    135135        const intptr_t frameSize = (boxedArgs.size() + CallFrame::headerSizeInRegisters) * sizeof(Register);
    136136        const intptr_t stackSpaceUsed = 2 * frameSize; // We're making two calls. One to the wrapper, and one to the actual wasm code.
    137         if (UNLIKELY((sp - stackSpaceUsed) < bitwise_cast<intptr_t>(vm.softStackLimit())))
     137        if (UNLIKELY((sp < stackSpaceUsed) || ((sp - stackSpaceUsed) < bitwise_cast<intptr_t>(vm.softStackLimit()))))
    138138            return JSValue::encode(throwException(exec, scope, createStackOverflowError(exec)));
    139139    }
Note: See TracChangeset for help on using the changeset viewer.