Skip to content

Commit 3c544f1

Browse files
committed
[JSC] Add assertions for MarkedArgumentBuffer size
https://bugs.webkit.org/show_bug.cgi?id=245286 <rdar://99272310> Reviewed by Alexey Shvayka. 1. Add MarkedArgumentBuffer size assertions to places with fixed-sized MarkedArgumentBuffer arguments. 2. Suppress warning in JSRemoteFunction.cpp when we return in the middle of MarkedArgumentBuffer construction due to different exception. In this case, we do not need to check since we don't use constructed MarkedArgumentBuffer. * Source/JavaScriptCore/API/JSAPIGlobalObject.mm: (JSC::JSAPIGlobalObject::moduleLoaderFetch): * Source/JavaScriptCore/runtime/JSModuleLoader.cpp: (JSC::JSModuleLoader::dependencyKeysIfEvaluated): * Source/JavaScriptCore/runtime/JSPromise.cpp: (JSC::JSPromise::resolvedPromise): * Source/JavaScriptCore/runtime/JSRemoteFunction.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/TemporalCalendarPrototype.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/VM.cpp: (JSC::VM::callPromiseRejectionCallback): * Source/JavaScriptCore/tools/JSDollarVM.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/wasm/WasmOperations.cpp: (JSC::Wasm::JSC_DEFINE_JIT_OPERATION): * Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp: (WebCore::AudioWorkletProcessor::process): * Source/WebCore/bindings/js/JSDOMMapLike.cpp: (WebCore::setToBackingMap): * Source/WebCore/bindings/js/JSDOMPromise.cpp: (WebCore::DOMPromise::whenPromiseIsSettled): * Source/WebCore/bindings/js/JSDOMSetLike.cpp: (WebCore::addToBackingSet): * Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp: (WebCore::ReadableStreamDefaultController::close): (WebCore::ReadableStreamDefaultController::error): (WebCore::ReadableStreamDefaultController::enqueue): * Source/WebCore/bindings/js/ScriptController.cpp: (WebCore::ScriptController::callInWorld): (WebCore::ScriptController::executeAsynchronousUserAgentScriptInWorld): Canonical link: https://commits.webkit.org/254571@main
1 parent ce7674d commit 3c544f1

15 files changed

Lines changed: 36 additions & 4 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//@ runDefault("--watchdog=10", "--watchdog-exception-ok", "--useShadowRealm=1")
2+
for (let i = 0; i < 100; i++) {
3+
let f = new ShadowRealm().evaluate(`new Proxy(()=>{}, {});`);
4+
f.apply(undefined, new Array(10_000));
5+
}

‎Source/JavaScriptCore/API/JSAPIGlobalObject.mm‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,6 @@
198198
JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)];
199199
id script = valueToObject(context, toRef(globalObject, callFrame->argument(0)));
200200

201-
MarkedArgumentBuffer args;
202-
203201
auto rejectPromise = [&] (String message) {
204202
strongPromise.get()->reject(globalObject, createTypeError(globalObject, message));
205203
return encodedJSUndefined();

‎Source/JavaScriptCore/runtime/JSModuleLoader.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ JSArray* JSModuleLoader::dependencyKeysIfEvaluated(JSGlobalObject* globalObject,
126126

127127
MarkedArgumentBuffer arguments;
128128
arguments.append(key);
129+
ASSERT(!arguments.hasOverflowed());
129130

130131
JSValue result = call(globalObject, function, callData, this, arguments);
131132
RETURN_IF_EXCEPTION(scope, nullptr);

‎Source/JavaScriptCore/runtime/JSPromise.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ JSPromise* JSPromise::resolvedPromise(JSGlobalObject* globalObject, JSValue valu
154154

155155
MarkedArgumentBuffer arguments;
156156
arguments.append(value);
157+
ASSERT(!arguments.hasOverflowed());
157158
auto result = call(globalObject, function, callData, globalObject->promiseConstructor(), arguments);
158159
RETURN_IF_EXCEPTION(scope, nullptr);
159160
ASSERT(result.inherits<JSPromise>());

‎Source/JavaScriptCore/runtime/JSRemoteFunction.cpp‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,17 @@ JSC_DEFINE_HOST_FUNCTION(remoteFunctionCallGeneric, (JSGlobalObject* globalObjec
132132
JSGlobalObject* targetGlobalObject = targetFunction->globalObject();
133133

134134
MarkedArgumentBuffer args;
135+
auto clearArgOverflowCheckAndReturnAbortValue = [&] () -> EncodedJSValue {
136+
// This is only called because we'll be imminently returning due to an
137+
// exception i.e. we won't be using the args, and we don't care if they
138+
// overflowed. However, we still need to call overflowCheckNotNeeded()
139+
// to placate an ASSERT in the MarkedArgumentBuffer destructor.
140+
args.overflowCheckNotNeeded();
141+
return { };
142+
};
135143
for (unsigned i = 0; i < callFrame->argumentCount(); ++i) {
136144
JSValue wrappedValue = wrapArgument(globalObject, targetGlobalObject, callFrame->uncheckedArgument(i));
137-
RETURN_IF_EXCEPTION(scope, { });
145+
RETURN_IF_EXCEPTION(scope, clearArgOverflowCheckAndReturnAbortValue());
138146
args.append(wrappedValue);
139147
}
140148
if (UNLIKELY(args.hasOverflowed())) {

‎Source/JavaScriptCore/runtime/TemporalCalendarPrototype.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,16 @@ JSC_DEFINE_HOST_FUNCTION(temporalCalendarPrototypeFuncFields, (JSGlobalObject* g
183183
shouldAddEraAndEraYear = true;
184184
}
185185
fieldNames.append(value);
186+
if (UNLIKELY(fieldNames.hasOverflowed()))
187+
throwStackOverflowError(globalObject, scope);
186188
});
187189
RETURN_IF_EXCEPTION(scope, { });
188190

189191
if (shouldAddEraAndEraYear) {
190192
fieldNames.append(jsNontrivialString(vm, vm.propertyNames->era.impl()));
191193
fieldNames.append(jsNontrivialString(vm, vm.propertyNames->eraYear.impl()));
194+
if (UNLIKELY(fieldNames.hasOverflowed()))
195+
throwStackOverflowError(globalObject, scope);
192196
}
193197

194198
RELEASE_AND_RETURN(scope, JSValue::encode(constructArray(globalObject, static_cast<ArrayAllocationProfile*>(nullptr), fieldNames)));

‎Source/JavaScriptCore/runtime/VM.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ void VM::callPromiseRejectionCallback(Strong<JSPromise>& promise)
12261226
MarkedArgumentBuffer args;
12271227
args.append(promise.get());
12281228
args.append(promise->result(*this));
1229+
ASSERT(!args.hasOverflowed());
12291230
call(promise->globalObject(), callback, callData, jsNull(), args);
12301231
scope.clearException();
12311232
}

‎Source/JavaScriptCore/tools/JSDollarVM.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3097,6 +3097,7 @@ JSC_DEFINE_HOST_FUNCTION(functionCreateWasmStreamingCompilerForCompile, (JSGloba
30973097
auto compiler = WasmStreamingCompiler::create(vm, globalObject, Wasm::CompilerMode::Validation, nullptr);
30983098
MarkedArgumentBuffer args;
30993099
args.append(compiler);
3100+
ASSERT(!args.hasOverflowed());
31003101
call(globalObject, callback, jsUndefined(), args, "You shouldn't see this..."_s);
31013102
if (UNLIKELY(scope.exception()))
31023103
scope.clearException();
@@ -3124,6 +3125,7 @@ JSC_DEFINE_HOST_FUNCTION(functionCreateWasmStreamingCompilerForInstantiate, (JSG
31243125
auto compiler = WasmStreamingCompiler::create(vm, globalObject, Wasm::CompilerMode::FullCompile, importObject);
31253126
MarkedArgumentBuffer args;
31263127
args.append(compiler);
3128+
ASSERT(!args.hasOverflowed());
31273129
call(globalObject, callback, jsUndefined(), args, "You shouldn't see this..."_s);
31283130
if (UNLIKELY(scope.exception()))
31293131
scope.clearException();

‎Source/JavaScriptCore/wasm/WasmOperations.cpp‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,11 @@ JSC_DEFINE_JIT_OPERATION(operationIterateResults, void, (CallFrame* callFrame, I
533533
MarkedArgumentBuffer buffer;
534534
JSValue result = JSValue::decode(encResult);
535535
forEachInIterable(globalObject, result, [&] (VM&, JSGlobalObject*, JSValue value) -> void {
536-
if (buffer.size() < signature->returnCount())
536+
if (buffer.size() < signature->returnCount()) {
537537
buffer.append(value);
538+
if (UNLIKELY(buffer.hasOverflowed()))
539+
throwOutOfMemoryError(globalObject, scope);
540+
}
538541
++iterationCount;
539542
});
540543
RETURN_IF_EXCEPTION(scope, void());

‎Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ bool AudioWorkletProcessor::process(const Vector<RefPtr<AudioBus>>& inputs, Vect
251251

252252
MarkedArgumentBuffer args;
253253
buildJSArguments(vm, globalObject, args, inputs, outputs, paramValuesMap);
254+
ASSERT(!args.hasOverflowed());
254255

255256
NakedPtr<JSC::Exception> returnedException;
256257
auto result = JSCallbackData::invokeCallback(globalObject, wrapper(), jsUndefined(), args, JSCallbackData::CallbackType::Object, Identifier::fromString(vm, "process"_s), returnedException);

0 commit comments

Comments
 (0)