Commit 515fef86 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Perform signature check on exception import.

This checks the type signature during import against the expected
signature. For this the {WasmExceptionObject} now contains a serialized
version of the signature.

R=clemensh@chromium.org
TEST=mjsunit/wasm/exceptions-import
BUG=v8:8091

Change-Id: I5a34ef87eccf4d2ed3a784620796ec009623fd90
Reviewed-on: https://chromium-review.googlesource.com/1219509Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55789}
parent cecd2ed5
......@@ -1751,9 +1751,16 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
index, module_name, import_name);
return -1;
}
Handle<WasmExceptionObject> imported_exception =
Handle<WasmExceptionObject>::cast(value);
if (!imported_exception->IsSignatureEqual(
module_->exceptions[import.index].sig)) {
ReportLinkError("imported exception does not match the expected type",
index, module_name, import_name);
return -1;
}
// TODO(mstarzinger): Actually add imported exceptions to the instance
// exception table, making sure to preserve object identity. Also check
// against the expected signature.
// exception table, making sure to preserve object identity.
break;
}
default:
......@@ -2035,9 +2042,7 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
const WasmException& exception = module_->exceptions[exp.index];
Handle<WasmExceptionObject> wrapper = exception_wrappers_[exp.index];
if (wrapper.is_null()) {
wrapper = WasmExceptionObject::New(isolate_);
// TODO(mstarzinger): Store exception signature in wrapper.
USE(exception);
wrapper = WasmExceptionObject::New(isolate_, exception.sig);
exception_wrappers_[exp.index] = wrapper;
}
desc.set_value(wrapper);
......
......@@ -210,6 +210,10 @@ ImportedFunctionEntry::ImportedFunctionEntry(
DCHECK_LT(index, instance->module()->num_imported_functions);
}
// WasmExceptionObject
ACCESSORS(WasmExceptionObject, serialized_signature, PodArray<wasm::ValueType>,
kSerializedSignatureOffset)
// WasmExportedFunctionData
ACCESSORS(WasmExportedFunctionData, wrapper_code, Code, kWrapperCodeOffset)
ACCESSORS(WasmExportedFunctionData, instance, WasmInstanceObject,
......
......@@ -1344,16 +1344,43 @@ Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
}
// static
Handle<WasmExceptionObject> WasmExceptionObject::New(Isolate* isolate) {
Handle<WasmExceptionObject> WasmExceptionObject::New(
Isolate* isolate, const wasm::FunctionSig* sig) {
Handle<JSFunction> exception_cons(
isolate->native_context()->wasm_exception_constructor(), isolate);
Handle<JSObject> exception_object =
isolate->factory()->NewJSObject(exception_cons, TENURED);
Handle<WasmExceptionObject> exception =
Handle<WasmExceptionObject>::cast(exception_object);
// Serialize the signature.
DCHECK_EQ(0, sig->return_count());
DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
int sig_size = static_cast<int>(sig->parameter_count());
Handle<PodArray<wasm::ValueType>> serialized_sig =
PodArray<wasm::ValueType>::New(isolate, sig_size, TENURED);
int index = 0; // Index into the {PodArray} above.
for (wasm::ValueType param : sig->parameters()) {
serialized_sig->set(index++, param);
}
exception->set_serialized_signature(*serialized_sig);
return exception;
}
bool WasmExceptionObject::IsSignatureEqual(const wasm::FunctionSig* sig) {
DCHECK_EQ(0, sig->return_count());
DCHECK_LE(sig->parameter_count(), std::numeric_limits<int>::max());
int sig_size = static_cast<int>(sig->parameter_count());
if (sig_size != serialized_signature()->length()) return false;
for (int index = 0; index < sig_size; ++index) {
if (sig->GetParam(index) != serialized_signature()->get(index)) {
return false;
}
}
return true;
}
bool WasmExportedFunction::IsWasmExportedFunction(Object* object) {
if (!object->IsJSFunction()) return false;
JSFunction* js_function = JSFunction::cast(object);
......
......@@ -477,14 +477,23 @@ class WasmExceptionObject : public JSObject {
public:
DECL_CAST(WasmExceptionObject)
DECL_ACCESSORS(serialized_signature, PodArray<wasm::ValueType>)
// Layout description.
#define WASM_EXCEPTION_OBJECT_FIELDS(V) V(kSize, 0)
#define WASM_EXCEPTION_OBJECT_FIELDS(V) \
V(kSerializedSignatureOffset, kPointerSize) \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
WASM_EXCEPTION_OBJECT_FIELDS)
#undef WASM_EXCEPTION_OBJECT_FIELDS
static Handle<WasmExceptionObject> New(Isolate* isolate);
// Checks whether the given {sig} has the same parameter types as the
// serialized signature stored within this exception object.
bool IsSignatureEqual(const wasm::FunctionSig* sig);
static Handle<WasmExceptionObject> New(Isolate* isolate,
const wasm::FunctionSig* sig);
};
// A WASM function that is wrapped and exported to JavaScript.
......
......@@ -81,10 +81,9 @@ function NewExportedException() {
let builder = new WasmModuleBuilder();
let except = builder.addImportedException("m", "ex", kSig_v_i);
// TODO(mstarzinger): Enable once proper signature check is performed.
//assertThrows(
// () => builder.instantiate({ m: { ex: exported }}), WebAssembly.LinkError,
// /imported exception does not match expected type/);
assertThrows(
() => builder.instantiate({ m: { ex: exported }}), WebAssembly.LinkError,
/imported exception does not match the expected type/);
})();
(function TestImportModuleGetImports() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment