Skip to content
Permalink
Browse files
Add support to throw OOM if MarkedArgumentBuffer may overflow.
https://bugs.webkit.org/show_bug.cgi?id=179092
<rdar://problem/35116160>

Reviewed by Saam Barati.

Source/JavaScriptCore:

The test for overflowing a MarkedArgumentBuffer will run for a ridiculously long
time, which renders it unsuitable for automated tests.  Instead, I've run a
test manually to verify that an OutOfMemoryError will be thrown when an overflow
occurs.

The MarkedArgumentBuffer's destructor will now assert that the client has indeed
checked for an overflow after invoking methods that may result in an overflow i.e.
the destructor checks that MarkedArgumentBuffer::hasOverflowed() has been called.
This is only done on debug builds.

* API/JSObjectRef.cpp:
(JSObjectMakeFunction):
(JSObjectMakeArray):
(JSObjectMakeDate):
(JSObjectMakeRegExp):
(JSObjectCallAsFunction):
(JSObjectCallAsConstructor):
* dfg/DFGOperations.cpp:
* inspector/InjectedScriptManager.cpp:
(Inspector::InjectedScriptManager::createInjectedScript):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::scopeChain const):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::executeProgram):
* jsc.cpp:
(functionDollarAgentReceiveBroadcast):
* runtime/ArgList.cpp:
(JSC::MarkedArgumentBuffer::slowEnsureCapacity):
(JSC::MarkedArgumentBuffer::expandCapacity):
(JSC::MarkedArgumentBuffer::slowAppend):
* runtime/ArgList.h:
(JSC::MarkedArgumentBuffer::~MarkedArgumentBuffer):
(JSC::MarkedArgumentBuffer::appendWithAction):
(JSC::MarkedArgumentBuffer::append):
(JSC::MarkedArgumentBuffer::appendWithCrashOnOverflow):
(JSC::MarkedArgumentBuffer::hasOverflowed):
(JSC::MarkedArgumentBuffer::setNeedsOverflowCheck):
(JSC::MarkedArgumentBuffer::clearNeedsOverflowCheck):
* runtime/ArrayPrototype.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/GetterSetter.cpp:
(JSC::callSetter):
* runtime/IteratorOperations.cpp:
(JSC::iteratorNext):
(JSC::iteratorClose):
* runtime/JSBoundFunction.cpp:
(JSC::boundThisNoArgsFunctionCall):
(JSC::boundFunctionCall):
(JSC::boundThisNoArgsFunctionConstruct):
(JSC::boundFunctionConstruct):
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayViewFromIterator):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoFuncSlice):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::haveABadTime):
* runtime/JSInternalPromise.cpp:
(JSC::JSInternalPromise::then):
* runtime/JSJob.cpp:
(JSC::JSJobMicrotask::run):
* runtime/JSMapIterator.cpp:
(JSC::JSMapIterator::createPair):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::provideFetch):
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::requestImportModule):
* runtime/JSONObject.cpp:
(JSC::Stringifier::toJSONImpl):
(JSC::Stringifier::appendStringifiedValue):
(JSC::Walker::callReviver):
* runtime/JSObject.cpp:
(JSC::ordinarySetSlow):
(JSC::callToPrimitiveFunction):
(JSC::JSObject::hasInstance):
* runtime/JSPromise.cpp:
(JSC::JSPromise::initialize):
(JSC::JSPromise::resolve):
* runtime/JSPromiseDeferred.cpp:
(JSC::newPromiseCapability):
(JSC::callFunction):
* runtime/JSSetIterator.cpp:
(JSC::JSSetIterator::createPair):
* runtime/LiteralParser.cpp:
(JSC::LiteralParser<CharType>::parse):
* runtime/MapConstructor.cpp:
(JSC::constructMap):
* runtime/ObjectConstructor.cpp:
(JSC::defineProperties):
* runtime/ProxyObject.cpp:
(JSC::performProxyGet):
(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::performPut):
(JSC::performProxyCall):
(JSC::performProxyConstruct):
(JSC::ProxyObject::performDelete):
(JSC::ProxyObject::performPreventExtensions):
(JSC::ProxyObject::performIsExtensible):
(JSC::ProxyObject::performDefineOwnProperty):
(JSC::ProxyObject::performGetOwnPropertyNames):
(JSC::ProxyObject::performSetPrototype):
(JSC::ProxyObject::performGetPrototype):
* runtime/ReflectObject.cpp:
(JSC::reflectObjectConstruct):
* runtime/SetConstructor.cpp:
(JSC::constructSet):
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
(JSC::replaceUsingStringSearch):
* runtime/WeakMapConstructor.cpp:
(JSC::constructWeakMap):
* runtime/WeakSetConstructor.cpp:
(JSC::constructWeakSet):
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):

Source/WebCore:

No new tests.  The test for overflowing a MarkedArgumentBuffer will run for a
ridiculously long time, which renders it unsuitable for automated tests.

* Modules/plugins/QuickTimePluginReplacement.mm:
(WebCore::QuickTimePluginReplacement::installReplacement):
* bindings/js/JSCustomElementInterface.cpp:
(WebCore::constructCustomElementSynchronously):
(WebCore::JSCustomElementInterface::upgradeElement):
(WebCore::JSCustomElementInterface::invokeCallback):
* bindings/js/JSCustomXPathNSResolver.cpp:
(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
* bindings/js/JSDOMBuiltinConstructorBase.cpp:
(WebCore::JSDOMBuiltinConstructorBase::callFunctionWithCurrentArguments):
* bindings/js/JSDOMConvertSequences.h:
(WebCore::JSConverter<IDLSequence<T>>::convert):
(WebCore::JSConverter<IDLFrozenArray<T>>::convert):
* bindings/js/JSDOMConvertWebGL.cpp:
(WebCore::convertToJSValue):
* bindings/js/JSDOMIterator.h:
(WebCore::jsPair):
(WebCore::iteratorForEach):
* bindings/js/JSDOMMapLike.cpp:
(WebCore::forwardFunctionCallToBackingMap):
(WebCore::forwardForEachCallToBackingMap):
* bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::DeferredPromise::callFunction):
(WebCore::createRejectedPromiseWithTypeError):
* bindings/js/JSErrorHandler.cpp:
(WebCore::JSErrorHandler::handleEvent):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/JSLazyEventListener.cpp:
(WebCore::JSLazyEventListener::initializeJSFunction const):
* bindings/js/JSPluginElementFunctions.cpp:
(WebCore::callPlugin):
* bindings/js/JSReadableStreamPrivateConstructors.cpp:
(WebCore::constructJSReadableStreamReaderGeneric):
* bindings/js/ReadableStream.cpp:
(WebCore::ReadableStream::create):
(WebCore::ReadableStream::pipeTo):
(WebCore::ReadableStream::tee):
(WebCore::ReadableStream::lock):
(WebCore::checkReadableStream):
* bindings/js/ReadableStreamDefaultController.cpp:
(WebCore::ReadableStreamDefaultController::invoke):
* bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::executeFunctionInContext):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::recordObject):
(WebCore::CloneSerializer::serialize):
(WebCore::CloneDeserializer::readTerminal):
(WebCore::CloneDeserializer::deserialize):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateCallbackImplementationContent):
* bindings/scripts/test/JS/JSTestCallbackFunction.cpp:
(WebCore::JSTestCallbackFunction::handleEvent):
* bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp:
(WebCore::JSTestCallbackFunctionRethrow::handleEvent):
* bindings/scripts/test/JS/JSTestCallbackFunctionWithThisObject.cpp:
(WebCore::JSTestCallbackFunctionWithThisObject::handleEvent):
* bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp:
(WebCore::JSTestCallbackFunctionWithTypedefs::handleEvent):
* bindings/scripts/test/JS/JSTestCallbackInterface.cpp:
(WebCore::JSTestCallbackInterface::callbackWithNoParam):
(WebCore::JSTestCallbackInterface::callbackWithArrayParam):
(WebCore::JSTestCallbackInterface::callbackWithSerializedScriptValueParam):
(WebCore::JSTestCallbackInterface::callbackWithStringList):
(WebCore::JSTestCallbackInterface::callbackWithBoolean):
(WebCore::JSTestCallbackInterface::callbackRequiresThisToPass):
(WebCore::JSTestCallbackInterface::callbackWithAReturnValue):
(WebCore::JSTestCallbackInterface::callbackThatRethrowsExceptions):
(WebCore::JSTestCallbackInterface::callbackThatSkipsInvokeCheck):
(WebCore::JSTestCallbackInterface::callbackWithThisObject):
* bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp:
(WebCore::JSTestVoidCallbackFunction::handleEvent):
* bridge/NP_jsobject.cpp:
* bridge/objc/WebScriptObject.mm:
(-[WebScriptObject callWebScriptMethod:withArguments:]):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::updateCaptionContainer):
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
(WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
(WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::didAddUserAgentShadowRoot):
* testing/Internals.cpp:
(WebCore::Internals::cloneArrayBuffer):



Canonical link: https://commits.webkit.org/195256@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224309 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Mark Lam committed Nov 2, 2017
1 parent 94d2dcd commit bb10620b0b1b5b3494d4b3d8bdbedf35d049a501
Showing 67 changed files with 533 additions and 61 deletions.
@@ -151,6 +151,12 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa
for (unsigned i = 0; i < parameterCount; i++)
args.append(jsString(exec, parameterNames[i]->string()));
args.append(jsString(exec, body->string()));
if (UNLIKELY(args.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

auto sourceURLString = sourceURL ? sourceURL->string() : String();
JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, SourceOrigin { sourceURLString }, sourceURLString, TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber()));
@@ -175,6 +181,12 @@ JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSVa
MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(exec, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

result = constructArray(exec, static_cast<ArrayAllocationProfile*>(0), argList);
} else
@@ -200,6 +212,12 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal
MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(exec, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), JSValue(), argList);
if (handleExceptionIfNeeded(scope, exec, exception) == ExceptionStatus::DidThrow)
@@ -243,6 +261,12 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV
MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; ++i)
argList.append(toJS(exec, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList);
if (handleExceptionIfNeeded(scope, exec, exception) == ExceptionStatus::DidThrow)
@@ -581,6 +605,12 @@ JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObject
MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(exec, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

CallData callData;
CallType callType = jsObject->methodTable(vm)->getCallData(jsObject, callData);
@@ -622,6 +652,12 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
MarkedArgumentBuffer argList;
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(exec, arguments[i]));
if (UNLIKELY(argList.hasOverflowed())) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
throwOutOfMemoryError(exec, throwScope);
handleExceptionIfNeeded(scope, exec, exception);
return 0;
}

JSObjectRef result = toRef(profiledConstruct(exec, ProfilingReason::API, jsObject, constructType, constructData, argList));
if (handleExceptionIfNeeded(scope, exec, exception) == ExceptionStatus::DidThrow)
@@ -1,3 +1,131 @@
2017-11-01 Mark Lam <mark.lam@apple.com>

Add support to throw OOM if MarkedArgumentBuffer may overflow.
https://bugs.webkit.org/show_bug.cgi?id=179092
<rdar://problem/35116160>

Reviewed by Saam Barati.

The test for overflowing a MarkedArgumentBuffer will run for a ridiculously long
time, which renders it unsuitable for automated tests. Instead, I've run a
test manually to verify that an OutOfMemoryError will be thrown when an overflow
occurs.

The MarkedArgumentBuffer's destructor will now assert that the client has indeed
checked for an overflow after invoking methods that may result in an overflow i.e.
the destructor checks that MarkedArgumentBuffer::hasOverflowed() has been called.
This is only done on debug builds.

* API/JSObjectRef.cpp:
(JSObjectMakeFunction):
(JSObjectMakeArray):
(JSObjectMakeDate):
(JSObjectMakeRegExp):
(JSObjectCallAsFunction):
(JSObjectCallAsConstructor):
* dfg/DFGOperations.cpp:
* inspector/InjectedScriptManager.cpp:
(Inspector::InjectedScriptManager::createInjectedScript):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::scopeChain const):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::executeProgram):
* jsc.cpp:
(functionDollarAgentReceiveBroadcast):
* runtime/ArgList.cpp:
(JSC::MarkedArgumentBuffer::slowEnsureCapacity):
(JSC::MarkedArgumentBuffer::expandCapacity):
(JSC::MarkedArgumentBuffer::slowAppend):
* runtime/ArgList.h:
(JSC::MarkedArgumentBuffer::~MarkedArgumentBuffer):
(JSC::MarkedArgumentBuffer::appendWithAction):
(JSC::MarkedArgumentBuffer::append):
(JSC::MarkedArgumentBuffer::appendWithCrashOnOverflow):
(JSC::MarkedArgumentBuffer::hasOverflowed):
(JSC::MarkedArgumentBuffer::setNeedsOverflowCheck):
(JSC::MarkedArgumentBuffer::clearNeedsOverflowCheck):
* runtime/ArrayPrototype.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/GetterSetter.cpp:
(JSC::callSetter):
* runtime/IteratorOperations.cpp:
(JSC::iteratorNext):
(JSC::iteratorClose):
* runtime/JSBoundFunction.cpp:
(JSC::boundThisNoArgsFunctionCall):
(JSC::boundFunctionCall):
(JSC::boundThisNoArgsFunctionConstruct):
(JSC::boundFunctionConstruct):
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayViewFromIterator):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoFuncSlice):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::haveABadTime):
* runtime/JSInternalPromise.cpp:
(JSC::JSInternalPromise::then):
* runtime/JSJob.cpp:
(JSC::JSJobMicrotask::run):
* runtime/JSMapIterator.cpp:
(JSC::JSMapIterator::createPair):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::provideFetch):
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::requestImportModule):
* runtime/JSONObject.cpp:
(JSC::Stringifier::toJSONImpl):
(JSC::Stringifier::appendStringifiedValue):
(JSC::Walker::callReviver):
* runtime/JSObject.cpp:
(JSC::ordinarySetSlow):
(JSC::callToPrimitiveFunction):
(JSC::JSObject::hasInstance):
* runtime/JSPromise.cpp:
(JSC::JSPromise::initialize):
(JSC::JSPromise::resolve):
* runtime/JSPromiseDeferred.cpp:
(JSC::newPromiseCapability):
(JSC::callFunction):
* runtime/JSSetIterator.cpp:
(JSC::JSSetIterator::createPair):
* runtime/LiteralParser.cpp:
(JSC::LiteralParser<CharType>::parse):
* runtime/MapConstructor.cpp:
(JSC::constructMap):
* runtime/ObjectConstructor.cpp:
(JSC::defineProperties):
* runtime/ProxyObject.cpp:
(JSC::performProxyGet):
(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::performPut):
(JSC::performProxyCall):
(JSC::performProxyConstruct):
(JSC::ProxyObject::performDelete):
(JSC::ProxyObject::performPreventExtensions):
(JSC::ProxyObject::performIsExtensible):
(JSC::ProxyObject::performDefineOwnProperty):
(JSC::ProxyObject::performGetOwnPropertyNames):
(JSC::ProxyObject::performSetPrototype):
(JSC::ProxyObject::performGetPrototype):
* runtime/ReflectObject.cpp:
(JSC::reflectObjectConstruct):
* runtime/SetConstructor.cpp:
(JSC::constructSet):
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
(JSC::replaceUsingStringSearch):
* runtime/WeakMapConstructor.cpp:
(JSC::constructWeakMap):
* runtime/WeakSetConstructor.cpp:
(JSC::constructWeakSet):
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):

2017-11-01 Michael Saboff <msaboff@apple.com>

Integer overflow in code generated by LoadVarargs processing in DFG and FTL.
@@ -2406,6 +2406,7 @@ JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)

MarkedArgumentBuffer arguments;
arguments.append(iterable);
ASSERT(!arguments.hasOverflowed());
JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
RETURN_IF_EXCEPTION(throwScope, nullptr);
array = jsCast<JSArray*>(arrayResult);
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007-2017 Apple Inc. All rights reserved.
* Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
* Copyright (C) 2012 Google Inc. All rights reserved.
*
@@ -158,6 +158,7 @@ JSC::JSObject* InjectedScriptManager::createInjectedScript(const String& source,
args.append(m_injectedScriptHost->wrapper(scriptState, globalObject));
args.append(globalThisValue);
args.append(jsNumber(id));
ASSERT(!args.hasOverflowed());

JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args);
scope.clearException();
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2014-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -180,6 +180,9 @@ JSValue JSJavaScriptCallFrame::functionName(ExecState* exec) const

JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const
{
VM& vm = exec->vm();
auto scope = DECLARE_THROW_SCOPE(vm);

if (!impl().scopeChain())
return jsNull();

@@ -195,6 +198,10 @@ JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const
list.append(iter.get());
++iter;
} while (iter != end);
if (UNLIKELY(list.hasOverflowed())) {
throwOutOfMemoryError(exec, scope);
return { };
}

return constructArray(exec, nullptr, globalObject(), list);
}
@@ -862,6 +862,7 @@ JSValue Interpreter::executeProgram(const SourceCode& source, CallFrame* callFra
return throwException(callFrame, throwScope, createNotAFunctionError(callFrame, function));
MarkedArgumentBuffer jsonArg;
jsonArg.append(JSONPValue);
ASSERT(!jsonArg.hasOverflowed());
JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
RETURN_IF_EXCEPTION(throwScope, JSValue());
@@ -2911,6 +2911,8 @@ EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec
MarkedArgumentBuffer args;
args.append(jsBuffer);
args.append(jsNumber(message->index()));
if (UNLIKELY(args.hasOverflowed()))
return JSValue::encode(throwOutOfMemoryError(exec, scope));
scope.release();
return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
}
@@ -65,21 +65,30 @@ void MarkedArgumentBuffer::markLists(SlotVisitor& visitor, ListSet& markSet)

void MarkedArgumentBuffer::slowEnsureCapacity(size_t requestedCapacity)
{
int newCapacity = Checked<int>(requestedCapacity).unsafeGet();
expandCapacity(newCapacity);
setNeedsOverflowCheck();
auto checkedNewCapacity = Checked<int, RecordOverflow>(requestedCapacity);
if (UNLIKELY(checkedNewCapacity.hasOverflowed()))
return this->overflowed();
expandCapacity(checkedNewCapacity.unsafeGet());
}

void MarkedArgumentBuffer::expandCapacity()
{
int newCapacity = (Checked<int>(m_capacity) * 2).unsafeGet();
expandCapacity(newCapacity);
setNeedsOverflowCheck();
auto checkedNewCapacity = Checked<int, RecordOverflow>(m_capacity) * 2;
if (UNLIKELY(checkedNewCapacity.hasOverflowed()))
return this->overflowed();
expandCapacity(checkedNewCapacity.unsafeGet());
}

void MarkedArgumentBuffer::expandCapacity(int newCapacity)
{
setNeedsOverflowCheck();
ASSERT(m_capacity < newCapacity);
size_t size = (Checked<size_t>(newCapacity) * sizeof(EncodedJSValue)).unsafeGet();
EncodedJSValue* newBuffer = static_cast<EncodedJSValue*>(fastMalloc(size));
auto checkedSize = Checked<size_t, RecordOverflow>(newCapacity) * sizeof(EncodedJSValue);
if (UNLIKELY(checkedSize.hasOverflowed()))
return this->overflowed();
EncodedJSValue* newBuffer = static_cast<EncodedJSValue*>(fastMalloc(checkedSize.unsafeGet()));
for (int i = 0; i < m_size; ++i) {
newBuffer[i] = m_buffer[i];
addMarkSet(JSValue::decode(m_buffer[i]));
@@ -97,6 +106,10 @@ void MarkedArgumentBuffer::slowAppend(JSValue v)
ASSERT(m_size <= m_capacity);
if (m_size == m_capacity)
expandCapacity();
if (UNLIKELY(Base::hasOverflowed())) {
ASSERT(m_needsOverflowCheck);
return;
}

slotFor(m_size) = JSValue::encode(v);
++m_size;

0 comments on commit bb10620

Please sign in to comment.