haikuwebkit/Source/WTF/wtf/StackCheck.h

117 lines
4.4 KiB
C
Raw Permalink Normal View History

Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
/*
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
* Copyright (C) 2019-2020 Apple Inc. All rights reserved.
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <wtf/StackBounds.h>
#include <wtf/Threading.h>
namespace WTF {
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
// We only enable the reserved zone size check by default on ASSERT_ENABLED
// builds (which usually mean Debug builds). However, it is more valuable to
// run this test on Release builds. That said, we don't want to do pay this
// cost always because we may need to do stack checks on hot paths too.
// Note also that we're deliberately using RELEASE_ASSERTs if the verification
// is turned on. This makes it easier for us to turn this on for Release builds
// for a reserved zone size calibration test runs.
#define VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE ASSERT_ENABLED
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
class StackCheck {
WTF_MAKE_FAST_ALLOCATED;
public:
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
class Scope {
public:
Scope(StackCheck& checker)
: m_checker(checker)
{
m_checker.isSafeToRecurse();
#if VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE
RELEASE_ASSERT(checker.m_ownerThread == &Thread::current());
// Make sure that the stack interval between checks never exceed the
// reservedZone size. If the interval exceeds the reservedZone size,
// then we either need to:
// 1. break the interval into smaller pieces (i.e. insert more checks), or
// 2. use a larger reservedZone size.
Reduce use of reinterpret_cast<> in the codebase https://bugs.webkit.org/show_bug.cgi?id=226743 Reviewed by Darin Adler. Source/WebCore: * Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp: (WebCore::CDMSessionClearKey::generateKeyRequest): * Modules/fetch/FetchBody.cpp: (WebCore::FetchBody::take): * Modules/fetch/FetchBodyConsumer.cpp: (WebCore::FetchBodyConsumer::resolve): (WebCore::FetchBodyConsumer::takeAsBlob): (WebCore::FetchBodyConsumer::takeAsText): * Modules/mediastream/RTCDataChannelRemoteHandler.cpp: (WebCore::RTCDataChannelRemoteHandler::readyToSend): (WebCore::RTCDataChannelRemoteHandler::sendStringData): (WebCore::RTCDataChannelRemoteHandler::sendRawData): * Modules/webaudio/MediaStreamAudioSourceGStreamer.cpp: (WebCore::copyBusData): * Modules/webauthn/AuthenticatorResponseData.h: (WebCore::encodeArrayBuffer): (WebCore::decodeArrayBuffer): * Modules/websockets/WebSocketChannel.cpp: (WebCore::WebSocketChannel::startClosingHandshake): (WebCore::WebSocketChannel::processOutgoingFrameQueue): * Modules/websockets/WebSocketHandshake.cpp: (WebCore::WebSocketHandshake::getExpectedWebSocketAccept): (WebCore::headerHasValidHTTPVersion): * bindings/js/ScriptBufferSourceProvider.h: * bindings/js/SerializedScriptValue.cpp: (WebCore::CloneDeserializer::readString): * contentextensions/SerializedNFA.cpp: (WebCore::ContentExtensions::SerializedNFA::pointerAtOffsetInFile const): * dom/Node.cpp: (WebCore::hashPointer): * dom/TextEncoder.cpp: (WebCore::TextEncoder::encode const): * dom/TextEncoderStreamEncoder.cpp: (WebCore::TextEncoderStreamEncoder::flush): * editing/cocoa/WebContentReaderCocoa.mm: (WebCore::sanitizeMarkupWithArchive): * html/canvas/WebGLRenderingContextBase.cpp: (WebCore::WebGLRenderingContextBase::texImageArrayBufferViewHelper): * inspector/DOMPatchSupport.cpp: (WebCore::addStringToSHA1): * loader/TextResourceDecoder.cpp: (WebCore::TextResourceDecoder::textFromUTF8): * loader/cache/CachedScript.cpp: (WebCore::CachedScript::script): * page/cocoa/ResourceUsageOverlayCocoa.mm: (WebCore::showText): * platform/SharedBufferChunkReader.cpp: (WebCore::SharedBufferChunkReader::nextChunk): * platform/cf/SharedBufferCF.cpp: (WebCore::SharedBuffer::createCFData const): * platform/generic/KeyedEncoderGeneric.cpp: (WebCore::KeyedEncoderGeneric::encodeString): * platform/graphics/GraphicsContextGL.cpp: (WebCore::GraphicsContextGL::packImageData): * platform/graphics/ImageBufferBackend.cpp: (WebCore::ImageBufferBackend::getPixelBuffer const): (WebCore::ImageBufferBackend::putPixelBuffer): * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp: (WebCore::InbandTextTrackPrivateAVF::processNativeSamples): * platform/graphics/avfoundation/cf/CDMSessionAVFoundationCF.cpp: (WebCore::CDMSessionAVFoundationCF::generateKeyRequest): (WebCore::CDMSessionAVFoundationCF::update): * platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp: (WebCore::InbandTextTrackPrivateAVCF::readNativeSampleBuffer): * platform/graphics/displaylists/DisplayListItemBuffer.cpp: (WebCore::DisplayList::ItemBuffer::createItemBuffer): * platform/graphics/displaylists/DisplayListIterator.cpp: (WebCore::DisplayList::DisplayList::Iterator::updateCurrentItem): * platform/image-decoders/gif/GIFImageReader.h: (GIFImageReader::data const): * platform/mac/SSLKeyGeneratorMac.mm: (WebCore::signedPublicKeyAndChallengeString): * platform/mediastream/RealtimeMediaSourceCenter.cpp: (WebCore::addStringToSHA1): * platform/network/FormDataBuilder.cpp: (WebCore::FormDataBuilder::encodeStringAsFormData): * platform/network/SocketStreamHandle.cpp: (WebCore::SocketStreamHandle::sendHandshake): * platform/network/cf/ResourceRequestCFNet.cpp: (WebCore::ResourceRequest::doUpdatePlatformRequest): * platform/network/cf/ResourceRequestCFNet.h: (WebCore::httpHeaderValueUsingSuitableEncoding): * platform/network/cf/SocketStreamHandleImplCFNet.cpp: (WebCore::SocketStreamHandleImpl::platformSendInternal): * platform/network/curl/CurlCacheEntry.cpp: (WebCore::CurlCacheEntry::generateBaseFilename): * platform/sql/SQLiteStatement.cpp: (WebCore::SQLiteStatement::columnBlobView): * testing/MockCDMFactory.cpp: (WebCore::MockCDM::sanitizeResponse const): Source/WebDriver: * socket/HTTPParser.cpp: (WebDriver::HTTPParser::readLine): * socket/SessionHostSocket.cpp: (WebDriver::SessionHost::sendWebInspectorEvent): Source/WebKit: * GPUProcess/media/RemoteMediaPlayerProxy.cpp: (WebKit::RemoteMediaPlayerProxy::mediaPlayerInitializationDataEncountered): * GPUProcess/media/RemoteTextTrackProxy.cpp: (WebKit::RemoteTextTrackProxy::addDataCue): * GPUProcess/webrtc/RemoteMediaRecorder.cpp: (WebKit::RemoteMediaRecorder::fetchData): * NetworkProcess/cache/NetworkCacheDataCurl.cpp: (WebKit::NetworkCache::Data::apply const): * NetworkProcess/cache/NetworkCacheKey.cpp: (WebKit::NetworkCache::hashString): * NetworkProcess/soup/WebKitDirectoryInputStream.cpp: (webkitDirectoryInputStreamRead): * Platform/IPC/ArgumentCoders.cpp: (IPC::ArgumentCoder<CString>::encode): (IPC::ArgumentCoder<String>::encode): * Shared/API/c/cf/WKStringCF.mm: (WKStringCopyCFString): * Shared/API/c/cf/WKURLCF.mm: (WKURLCopyCFURL): * Shared/ShareableResource.cpp: (WebKit::ShareableResource::wrapInSharedBuffer): * Shared/SharedDisplayListHandle.h: (WebKit::SharedDisplayListHandle::data const): * Shared/WebCompiledContentRuleList.cpp: (WebKit::WebCompiledContentRuleList::conditionsApplyOnlyToDomain const): * UIProcess/API/APIWebAuthenticationAssertionResponse.cpp: (API::WebAuthenticationAssertionResponse::userHandle const): * UIProcess/API/C/WKPage.cpp: (dataFrom): * UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm: (WebKit::RedirectSOAuthorizationSession::completeInternal): * UIProcess/Inspector/socket/RemoteInspectorClient.cpp: (WebKit::RemoteInspectorClient::sendWebInspectorEvent): * WebProcess/Network/WebSocketChannel.cpp: (WebKit::WebSocketChannel::createMessageQueue): (WebKit::WebSocketChannel::didReceiveText): * WebProcess/Network/webrtc/RTCDataChannelRemoteManager.cpp: (WebKit::RTCDataChannelRemoteManager::sendData): (WebKit::RTCDataChannelRemoteManager::RemoteSourceConnection::didReceiveStringData): * WebProcess/Plugins/Netscape/NetscapePluginStream.cpp: (WebKit::NetscapePluginStream::sendJavaScriptStream): Source/WTF: * wtf/CryptographicallyRandomNumber.cpp: * wtf/FastMalloc.h: (WTF::FastAllocator::allocate): * wtf/SHA1.h: (WTF::SHA1::addBytes): * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::StackCheck): * wtf/URLHelpers.cpp: (WTF::URLHelpers::userVisibleURL): * wtf/URLParser.cpp: (WTF::URLParser::formURLDecode): * wtf/cf/URLCF.cpp: (WTF::URL::createCFURL const): * wtf/cocoa/URLCocoa.mm: (WTF::URL::createCFURL const): * wtf/persistence/PersistentCoders.cpp: (WTF::Persistence::Coder<CString>::encode): (WTF::Persistence::Coder<String>::encode): * wtf/text/CString.h: * wtf/text/WTFString.cpp: (WTF::String::latin1 const): * wtf/text/cf/StringImplCF.cpp: (WTF::StringImpl::createCFString): Canonical link: https://commits.webkit.org/238604@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@278619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-06-08 17:35:15 +00:00
uint8_t* currentStackCheckpoint = static_cast<uint8_t*>(currentStackPointer());
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
uint8_t* previousStackCheckpoint = m_checker.m_lastStackCheckpoint;
RELEASE_ASSERT(previousStackCheckpoint - currentStackCheckpoint > 0);
RELEASE_ASSERT(previousStackCheckpoint - currentStackCheckpoint < static_cast<ptrdiff_t>(m_checker.m_reservedZone));
m_savedLastStackCheckpoint = m_checker.m_lastStackCheckpoint;
m_checker.m_lastStackCheckpoint = currentStackCheckpoint;
#endif
}
#if VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE
~Scope()
{
m_checker.m_lastStackCheckpoint = m_savedLastStackCheckpoint;
}
#endif
bool isSafeToRecurse() { return m_checker.isSafeToRecurse(); }
private:
StackCheck& m_checker;
#if VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE
uint8_t* m_savedLastStackCheckpoint;
#endif
};
StackCheck(const StackBounds& bounds = Thread::current().stack(), size_t minReservedZone = defaultReservedZoneSize)
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
: m_stackLimit(bounds.recursionLimit(minReservedZone))
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
#if VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE
, m_ownerThread(&Thread::current())
Reduce use of reinterpret_cast<> in the codebase https://bugs.webkit.org/show_bug.cgi?id=226743 Reviewed by Darin Adler. Source/WebCore: * Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp: (WebCore::CDMSessionClearKey::generateKeyRequest): * Modules/fetch/FetchBody.cpp: (WebCore::FetchBody::take): * Modules/fetch/FetchBodyConsumer.cpp: (WebCore::FetchBodyConsumer::resolve): (WebCore::FetchBodyConsumer::takeAsBlob): (WebCore::FetchBodyConsumer::takeAsText): * Modules/mediastream/RTCDataChannelRemoteHandler.cpp: (WebCore::RTCDataChannelRemoteHandler::readyToSend): (WebCore::RTCDataChannelRemoteHandler::sendStringData): (WebCore::RTCDataChannelRemoteHandler::sendRawData): * Modules/webaudio/MediaStreamAudioSourceGStreamer.cpp: (WebCore::copyBusData): * Modules/webauthn/AuthenticatorResponseData.h: (WebCore::encodeArrayBuffer): (WebCore::decodeArrayBuffer): * Modules/websockets/WebSocketChannel.cpp: (WebCore::WebSocketChannel::startClosingHandshake): (WebCore::WebSocketChannel::processOutgoingFrameQueue): * Modules/websockets/WebSocketHandshake.cpp: (WebCore::WebSocketHandshake::getExpectedWebSocketAccept): (WebCore::headerHasValidHTTPVersion): * bindings/js/ScriptBufferSourceProvider.h: * bindings/js/SerializedScriptValue.cpp: (WebCore::CloneDeserializer::readString): * contentextensions/SerializedNFA.cpp: (WebCore::ContentExtensions::SerializedNFA::pointerAtOffsetInFile const): * dom/Node.cpp: (WebCore::hashPointer): * dom/TextEncoder.cpp: (WebCore::TextEncoder::encode const): * dom/TextEncoderStreamEncoder.cpp: (WebCore::TextEncoderStreamEncoder::flush): * editing/cocoa/WebContentReaderCocoa.mm: (WebCore::sanitizeMarkupWithArchive): * html/canvas/WebGLRenderingContextBase.cpp: (WebCore::WebGLRenderingContextBase::texImageArrayBufferViewHelper): * inspector/DOMPatchSupport.cpp: (WebCore::addStringToSHA1): * loader/TextResourceDecoder.cpp: (WebCore::TextResourceDecoder::textFromUTF8): * loader/cache/CachedScript.cpp: (WebCore::CachedScript::script): * page/cocoa/ResourceUsageOverlayCocoa.mm: (WebCore::showText): * platform/SharedBufferChunkReader.cpp: (WebCore::SharedBufferChunkReader::nextChunk): * platform/cf/SharedBufferCF.cpp: (WebCore::SharedBuffer::createCFData const): * platform/generic/KeyedEncoderGeneric.cpp: (WebCore::KeyedEncoderGeneric::encodeString): * platform/graphics/GraphicsContextGL.cpp: (WebCore::GraphicsContextGL::packImageData): * platform/graphics/ImageBufferBackend.cpp: (WebCore::ImageBufferBackend::getPixelBuffer const): (WebCore::ImageBufferBackend::putPixelBuffer): * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp: (WebCore::InbandTextTrackPrivateAVF::processNativeSamples): * platform/graphics/avfoundation/cf/CDMSessionAVFoundationCF.cpp: (WebCore::CDMSessionAVFoundationCF::generateKeyRequest): (WebCore::CDMSessionAVFoundationCF::update): * platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp: (WebCore::InbandTextTrackPrivateAVCF::readNativeSampleBuffer): * platform/graphics/displaylists/DisplayListItemBuffer.cpp: (WebCore::DisplayList::ItemBuffer::createItemBuffer): * platform/graphics/displaylists/DisplayListIterator.cpp: (WebCore::DisplayList::DisplayList::Iterator::updateCurrentItem): * platform/image-decoders/gif/GIFImageReader.h: (GIFImageReader::data const): * platform/mac/SSLKeyGeneratorMac.mm: (WebCore::signedPublicKeyAndChallengeString): * platform/mediastream/RealtimeMediaSourceCenter.cpp: (WebCore::addStringToSHA1): * platform/network/FormDataBuilder.cpp: (WebCore::FormDataBuilder::encodeStringAsFormData): * platform/network/SocketStreamHandle.cpp: (WebCore::SocketStreamHandle::sendHandshake): * platform/network/cf/ResourceRequestCFNet.cpp: (WebCore::ResourceRequest::doUpdatePlatformRequest): * platform/network/cf/ResourceRequestCFNet.h: (WebCore::httpHeaderValueUsingSuitableEncoding): * platform/network/cf/SocketStreamHandleImplCFNet.cpp: (WebCore::SocketStreamHandleImpl::platformSendInternal): * platform/network/curl/CurlCacheEntry.cpp: (WebCore::CurlCacheEntry::generateBaseFilename): * platform/sql/SQLiteStatement.cpp: (WebCore::SQLiteStatement::columnBlobView): * testing/MockCDMFactory.cpp: (WebCore::MockCDM::sanitizeResponse const): Source/WebDriver: * socket/HTTPParser.cpp: (WebDriver::HTTPParser::readLine): * socket/SessionHostSocket.cpp: (WebDriver::SessionHost::sendWebInspectorEvent): Source/WebKit: * GPUProcess/media/RemoteMediaPlayerProxy.cpp: (WebKit::RemoteMediaPlayerProxy::mediaPlayerInitializationDataEncountered): * GPUProcess/media/RemoteTextTrackProxy.cpp: (WebKit::RemoteTextTrackProxy::addDataCue): * GPUProcess/webrtc/RemoteMediaRecorder.cpp: (WebKit::RemoteMediaRecorder::fetchData): * NetworkProcess/cache/NetworkCacheDataCurl.cpp: (WebKit::NetworkCache::Data::apply const): * NetworkProcess/cache/NetworkCacheKey.cpp: (WebKit::NetworkCache::hashString): * NetworkProcess/soup/WebKitDirectoryInputStream.cpp: (webkitDirectoryInputStreamRead): * Platform/IPC/ArgumentCoders.cpp: (IPC::ArgumentCoder<CString>::encode): (IPC::ArgumentCoder<String>::encode): * Shared/API/c/cf/WKStringCF.mm: (WKStringCopyCFString): * Shared/API/c/cf/WKURLCF.mm: (WKURLCopyCFURL): * Shared/ShareableResource.cpp: (WebKit::ShareableResource::wrapInSharedBuffer): * Shared/SharedDisplayListHandle.h: (WebKit::SharedDisplayListHandle::data const): * Shared/WebCompiledContentRuleList.cpp: (WebKit::WebCompiledContentRuleList::conditionsApplyOnlyToDomain const): * UIProcess/API/APIWebAuthenticationAssertionResponse.cpp: (API::WebAuthenticationAssertionResponse::userHandle const): * UIProcess/API/C/WKPage.cpp: (dataFrom): * UIProcess/Cocoa/SOAuthorization/RedirectSOAuthorizationSession.mm: (WebKit::RedirectSOAuthorizationSession::completeInternal): * UIProcess/Inspector/socket/RemoteInspectorClient.cpp: (WebKit::RemoteInspectorClient::sendWebInspectorEvent): * WebProcess/Network/WebSocketChannel.cpp: (WebKit::WebSocketChannel::createMessageQueue): (WebKit::WebSocketChannel::didReceiveText): * WebProcess/Network/webrtc/RTCDataChannelRemoteManager.cpp: (WebKit::RTCDataChannelRemoteManager::sendData): (WebKit::RTCDataChannelRemoteManager::RemoteSourceConnection::didReceiveStringData): * WebProcess/Plugins/Netscape/NetscapePluginStream.cpp: (WebKit::NetscapePluginStream::sendJavaScriptStream): Source/WTF: * wtf/CryptographicallyRandomNumber.cpp: * wtf/FastMalloc.h: (WTF::FastAllocator::allocate): * wtf/SHA1.h: (WTF::SHA1::addBytes): * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::StackCheck): * wtf/URLHelpers.cpp: (WTF::URLHelpers::userVisibleURL): * wtf/URLParser.cpp: (WTF::URLParser::formURLDecode): * wtf/cf/URLCF.cpp: (WTF::URL::createCFURL const): * wtf/cocoa/URLCocoa.mm: (WTF::URL::createCFURL const): * wtf/persistence/PersistentCoders.cpp: (WTF::Persistence::Coder<CString>::encode): (WTF::Persistence::Coder<String>::encode): * wtf/text/CString.h: * wtf/text/WTFString.cpp: (WTF::String::latin1 const): * wtf/text/cf/StringImplCF.cpp: (WTF::StringImpl::createCFString): Canonical link: https://commits.webkit.org/238604@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@278619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-06-08 17:35:15 +00:00
, m_lastStackCheckpoint(static_cast<uint8_t*>(currentStackPointer()))
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
, m_reservedZone(minReservedZone)
#endif
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
{ }
inline bool isSafeToRecurse() { return currentStackPointer() >= m_stackLimit; }
private:
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
#if ASAN_ENABLED
static constexpr size_t defaultReservedZoneSize = StackBounds::DefaultReservedZone * 2;
#else
static constexpr size_t defaultReservedZoneSize = StackBounds::DefaultReservedZone;
#endif
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
void* m_stackLimit;
Add stack checks to the DFG and FTL bytecode parser. https://bugs.webkit.org/show_bug.cgi?id=211547 <rdar://problem/62958880> Reviewed by Yusuke Suzuki. Source/JavaScriptCore: Inlining can cause some level of recursion of the DFG bytecode parser. We should do a stack check at each inlining check before recursing. If a stack overflow appears to be imminent, then just refuse to inline, and therefore, don't recurse deeper into the parser. This issue is more noticeable on ASan debug builds where stack frames can be humongous. Removed the SUPPRESS_ASAN on cloberrize() and the associated comment from r260692. It was a mis-diagnosis. The stack checks are what we need. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::handleInlining): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGGraph.h: Source/WTF: Added a StackCheck::Scope RAII object to help verify that the default reserved zone size is at least adequate for known work loads. If this the StackCheck::Scope assertions fail, then we either need more stack checks, or the reserved zone size needs to be increased. Note that the assertions are usually only on in Debug builds. Ideally, we would want to measure the reserved zone size with a Release build. To do that, we can just set VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE to 1 unconditionally in StackCheck.h and rebuild. * wtf/StackCheck.h: (WTF::StackCheck::Scope::Scope): (WTF::StackCheck::Scope::~Scope): (WTF::StackCheck::Scope::isSafeToRecurse): (WTF::StackCheck::StackCheck): Canonical link: https://commits.webkit.org/224491@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261325 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-07 19:25:32 +00:00
#if VERIFY_STACK_CHECK_RESERVED_ZONE_SIZE
Thread* m_ownerThread;
uint8_t* m_lastStackCheckpoint;
size_t m_reservedZone;
#endif
friend class Scope;
Add a stack overflow check in Yarr::ByteCompiler::emitDisjunction(). https://bugs.webkit.org/show_bug.cgi?id=203936 <rdar://problem/56624724> Reviewed by Saam Barati. JSTests: This issue originally manifested as incorrect-exception-assertion-in-operationRegExpExecNonGlobalOrSticky.js failing on iOS devices due to its smaller stack. We adapted the original test here using $vm.callWithStackSize() to reproduce the issue on x86_64 though it has a much larger physical stack to work with. This new test will crash while stepping on the guard page beyond the end of the stack if the fix is not applied. * stress/stack-overflow-in-yarr-byteCompile.js: Added. Source/JavaScriptCore: Basically, any functions below Yarr::ByteCompiler::compile() that recurses need to check if it's safe to recurse before doing so. This patch adds the stack checks in Yarr::ByteCompiler::compile() because it is the entry point to this sub-system, and Yarr::ByteCompiler::emitDisjunction() because it is the only function that recurses. All other functions called below compile() are either leaf functions or have shallow stack usage. Hence, their stack needs are covered by the DefaultReservedZone, and they do not need stack checks. This patch also does the following: 1. Added $vm.callWithStackSize() which can be used to call a test function near the end of the physical stack. This enables is to simulate the smaller stack size of more resource constrained devices. $vm.callWithStackSize() uses inline asm to adjust the stack pointer and does the callback via the JIT probe trampoline. 2. Added the --disableOptionsFreezingForTesting to the jsc shell to make it possible to disable freezing of JSC options. $vm.callWithStackSize() relies on this to modify the VM's stack limits. 3. Removed the inline modifier on VM::updateStackLimits() so that we can call it from $vm.callWithStackSize() as well. It is not a performance critical function and is rarely called. 4. Added a JSDollarVMHelper class that other parts of the system can declare as a friend. This gives $vm a backdoor into the private functions and fields of classes for its debugging work. In this patch, we're only using it to access VM::updateVMStackLimits(). * jsc.cpp: (CommandLine::parseArguments): * runtime/VM.cpp: (JSC::VM::updateStackLimits): * runtime/VM.h: * tools/JSDollarVM.cpp: (JSC::JSDollarVMHelper::JSDollarVMHelper): (JSC::JSDollarVMHelper::vmStackStart): (JSC::JSDollarVMHelper::vmStackLimit): (JSC::JSDollarVMHelper::vmSoftStackLimit): (JSC::JSDollarVMHelper::updateVMStackLimits): (JSC::callWithStackSizeProbeFunction): (JSC::functionCallWithStackSize): (JSC::JSDollarVM::finishCreation): (IGNORE_WARNINGS_BEGIN): Deleted. * yarr/YarrInterpreter.cpp: (JSC::Yarr::ByteCompiler::compile): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteCompiler::isSafeToRecurse): Source/WTF: 1. Add a StackCheck utility class so that we don't have to keep reinventing this every time we need to add stack checking somewhere. 2. Rename some arguments and constants in StackBounds to be more descriptive of what they actually are. * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/StackBounds.h: (WTF::StackBounds::recursionLimit const): * wtf/StackCheck.h: Added. (WTF::StackCheck::StackCheck): (WTF::StackCheck::isSafeToRecurse): Canonical link: https://commits.webkit.org/217331@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 16:58:49 +00:00
};
} // namespace WTF
using WTF::StackCheck;