Skip to content
Permalink
Browse files
[JSC] Fix WebAssembly.Tag.getArg's thrown error type
https://bugs.webkit.org/show_bug.cgi?id=247223
rdar://101705666

Reviewed by Alexey Shvayka.

1. We should use toNonWrappingUint32 to get Uint32 for getArg index
2. We should throw RangeError instead of TypeError for out of bounds getArg

https://webassembly.github.io/exception-handling/js-api/#dom-exception-getarg

* LayoutTests/imported/w3c/web-platform-tests/wasm/compile_worker.js:
* LayoutTests/imported/w3c/web-platform-tests/wasm/create_multiple_memory.worker.js:
* LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/exception/getArg.tentative.any.js:
(test):
* LayoutTests/imported/w3c/web-platform-tests/wasm/resources/load_wasm.js:
* LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/origin.sub.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/origin.sub.any.js:
* LayoutTests/imported/w3c/web-platform-tests/wasm/webapi/origin.sub.any.worker-expected.txt:
* Source/JavaScriptCore/wasm/js/WebAssemblyExceptionPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::getTag): Deleted.

Canonical link: https://commits.webkit.org/256158@main
  • Loading branch information
Constellation committed Oct 31, 2022
1 parent 5ac9a1b commit b1248207241a66f6361f4a2f035f18cc7caed4ae
Show file tree
Hide file tree
Showing 12 changed files with 36 additions and 26 deletions.
@@ -17,6 +17,6 @@ assert.eq(exception.getArg(tag, 0), 1);
assert.eq(exception.getArg(tag, 1), 2.5);
assert.eq(exception.getArg(tag, 2), parameters);

assert.throws(() => exception.getArg(tag, 3), TypeError, "WebAssembly.Exception.getArg(): Index out of range");
assert.throws(() => exception.getArg(tag, 3), RangeError, "WebAssembly.Exception.getArg(): Index out of range");

assert.eq(WebAssembly.Exception.prototype.__proto__, Object.prototype)
@@ -202,7 +202,7 @@ function TestGetArgHelper(types_str, types, values) {
/First argument must be a WebAssembly.Tag/);
//assertThrows(() => exception.getArg(tag, undefined), TypeError,
///Index must be convertible to a valid number/);
assertThrows(() => exception.getArg(tag, 0xFFFFFFFF), TypeError,
assertThrows(() => exception.getArg(tag, 0xFFFFFFFF), RangeError,
/Index out of range/);
let wrong_tag = new WebAssembly.Tag({parameters: ['i32']});
assertThrows(() => exception.getArg(wrong_tag, 0), TypeError,
@@ -1,4 +1,4 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -1,4 +1,4 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -20,7 +20,7 @@ test(() => {
test(() => {
const tag = new WebAssembly.Tag({ parameters: [] });
const exn = new WebAssembly.Exception(tag, []);
assert_throws_js(TypeError, () => exn.getArg(tag, 1));
assert_throws_js(RangeError, () => exn.getArg(tag, 1));
}, "Index out of bounds");

test(() => {
@@ -1,4 +1,4 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -1,3 +1,7 @@
Blocked access to external URL http://www.localhost:8800/wasm/incrementer.wasm
CONSOLE MESSAGE: Fetch API cannot load http://www.localhost:8800/wasm/incrementer.wasm due to access control checks.
Blocked access to external URL http://www.localhost:8800/wasm/incrementer.wasm
CONSOLE MESSAGE: Fetch API cannot load http://www.localhost:8800/wasm/incrementer.wasm due to access control checks.

PASS Opaque response: compileStreaming
PASS Opaque redirect response: compileStreaming
@@ -2,7 +2,7 @@

for (const method of ["compileStreaming", "instantiateStreaming"]) {
promise_test(t => {
const url = "http://{{hosts[alt][]}}:{{ports[http][0]}}/wasm/incrementer.wasm";
const url = "http://{{domains[www]}}:{{ports[http][0]}}/wasm/incrementer.wasm";
const response = fetch(url, { "mode": "no-cors" });
return promise_rejects_js(t, TypeError, WebAssembly[method](response));
}, `Opaque response: ${method}`);
@@ -1,3 +1,5 @@
Blocked access to external URL http://www.localhost:8800/wasm/incrementer.wasm
Blocked access to external URL http://www.localhost:8800/wasm/incrementer.wasm

PASS Opaque response: compileStreaming
PASS Opaque redirect response: compileStreaming
@@ -0,0 +1,6 @@

PASS Opaque response: compileStreaming
PASS Opaque redirect response: compileStreaming
PASS Opaque response: instantiateStreaming
PASS Opaque redirect response: instantiateStreaming

@@ -0,0 +1,6 @@

PASS Opaque response: compileStreaming
PASS Opaque redirect response: compileStreaming
PASS Opaque response: instantiateStreaming
PASS Opaque redirect response: instantiateStreaming

@@ -91,13 +91,6 @@ ALWAYS_INLINE static JSWebAssemblyException* getException(JSGlobalObject* global
return nullptr;
}

ALWAYS_INLINE static JSWebAssemblyTag* getTag(JSValue tagValue)
{
if (!tagValue.isCell())
return nullptr;
return jsDynamicCast<JSWebAssemblyTag*>(tagValue.asCell());
}

JSC_DEFINE_HOST_FUNCTION(webAssemblyExceptionProtoFuncGetArg, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
@@ -106,26 +99,25 @@ JSC_DEFINE_HOST_FUNCTION(webAssemblyExceptionProtoFuncGetArg, (JSGlobalObject* g
const auto& formatMessage = [&](const auto& message) {
return makeString("WebAssembly.Exception.getArg(): ", message);
};
const auto& typeError = [&](const auto& message) {
return throwVMTypeError(globalObject, throwScope, formatMessage(message));
};

JSWebAssemblyException* jsException = getException(globalObject, callFrame->thisValue());
RETURN_IF_EXCEPTION(throwScope, { });

if (UNLIKELY(callFrame->argumentCount() < 2))
return JSValue::encode(throwException(globalObject, throwScope, createNotEnoughArgumentsError(globalObject)));

JSWebAssemblyTag* tag = getTag(callFrame->argument(0));
if (!tag)
return typeError("First argument must be a WebAssembly.Tag");
JSWebAssemblyTag* tag = jsDynamicCast<JSWebAssemblyTag*>(callFrame->argument(0));
if (UNLIKELY(!tag))
return throwVMTypeError(globalObject, throwScope, formatMessage("First argument must be a WebAssembly.Tag"_s));

uint32_t index = toNonWrappingUint32(globalObject, callFrame->argument(1));
RETURN_IF_EXCEPTION(throwScope, { });

if (jsException->tag() != tag->tag())
return typeError("First argument does not match the exception tag");
if (UNLIKELY(jsException->tag() != tag->tag()))
return throwVMTypeError(globalObject, throwScope, formatMessage("First argument does not match the exception tag"_s));

uint32_t index = callFrame->argument(1).toUInt32(globalObject);
if (index >= tag->tag().parameterCount())
return typeError("Index out of range");
if (UNLIKELY(index >= tag->tag().parameterCount()))
return throwVMRangeError(globalObject, throwScope, formatMessage("Index out of range"_s));

RELEASE_AND_RETURN(throwScope, JSValue::encode(jsException->getArg(globalObject, index)));
}
@@ -141,7 +133,7 @@ JSC_DEFINE_HOST_FUNCTION(webAssemblyExceptionProtoFuncIs, (JSGlobalObject* globa
if (UNLIKELY(callFrame->argumentCount() < 1))
return JSValue::encode(throwException(globalObject, throwScope, createNotEnoughArgumentsError(globalObject)));

JSWebAssemblyTag* tag = getTag(callFrame->argument(0));
JSWebAssemblyTag* tag = jsDynamicCast<JSWebAssemblyTag*>(callFrame->argument(0));
if (!tag)
return throwVMTypeError(globalObject, throwScope, "WebAssembly.Exception.is(): First argument must be a WebAssembly.Tag"_s);

0 comments on commit b124820

Please sign in to comment.