WebAssembly compilation from DataView
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Mar 2018 23:12:44 +0000 (23:12 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Mar 2018 23:12:44 +0000 (23:12 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230119 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/wasm/regress/183342.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/wasm/WasmModuleParser.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp

index 5d5858d..09f6bc6 100644 (file)
@@ -1,3 +1,15 @@
+2018-03-30  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly: support DataView compilation
+        https://bugs.webkit.org/show_bug.cgi?id=183342
+
+        Reviewed by Mark Lam.
+
+        Test WebAssembly compilation using a DataView with offset.
+
+        * wasm/regress/183342.js: Added.
+        (attempt.catch):
+
 2018-03-30  Filip Pizlo  <fpizlo@apple.com>
 
         Bytecode generator should not get_from_scope something that may be a hole into a variable that is already live
diff --git a/JSTests/wasm/regress/183342.js b/JSTests/wasm/regress/183342.js
new file mode 100644 (file)
index 0000000..3e485fd
--- /dev/null
@@ -0,0 +1,57 @@
+const verbose = false;
+
+{
+    // The simplest module with a DataView offset.
+    let buffer = new Uint8Array(16);
+    buffer[ 8] = 0x00; // \0
+    buffer[ 9] = 0x61; // a
+    buffer[10] = 0x73; // s
+    buffer[11] = 0x6d; // m
+    buffer[12] = 0x01; // version
+    buffer[13] = 0x00; // version
+    buffer[14] = 0x00; // version
+    buffer[15] = 0x00; // version
+    const view = new DataView(buffer.buffer, 8);
+    const module = new WebAssembly.Module(view);
+    const instance = new WebAssembly.Instance(module);
+}
+
+{
+    // A bunch of random offsets into large buffers with mostly valid content.
+    const headerSize = 16;
+    const roundToHeaderSize = s => Math.round(s / headerSize) * headerSize;
+    for (let attempt = 0; attempt < 100; ++attempt) {
+        const bufferSize = Math.max(roundToHeaderSize(Math.random() * 0xffff), headerSize * 2);
+        let buffer = new Uint8Array(bufferSize);
+        for (let i = 0; i < bufferSize; i += headerSize) {
+            buffer[ 0 + i] = 0x00; // \0
+            buffer[ 1 + i] = 0x61; // a
+            buffer[ 2 + i] = 0x73; // s
+            buffer[ 3 + i] = 0x6d; // m
+            buffer[ 4 + i] = 0x01; // version
+            buffer[ 5 + i] = 0x00; // version
+            buffer[ 6 + i] = 0x00; // version
+            buffer[ 7 + i] = 0x00; // version
+            buffer[ 8 + i] = 0x00; // ID = custom
+            buffer[ 9 + i] = 0x80 | Math.round(Math.random() * 0x7f); // section byte size, LEB128
+            buffer[10 + i] = 0x80 | Math.round(Math.random() * 0x7f); // section byte size, LEB128
+            buffer[11 + i] = 0x00 | Math.round(Math.random() * 0x7f); // section byte size, LEB128
+            buffer[12 + i] = 0x04; // custom section name length, LEB128
+            buffer[13 + i] = 0x42; // B
+            buffer[14 + i] = 0x4f; // O
+            buffer[15 + i] = 0X4f; // O
+            buffer[16 + i] = 0x4d; // M
+        }
+        const viewOffset = roundToHeaderSize(Math.random() * bufferSize);
+        if (verbose)
+            print("Buffer size: ", bufferSize, " view offset: ", viewOffset, " view size: ", bufferSize - viewOffset);
+        const view = new DataView(buffer.buffer, viewOffset);
+        try {
+            const module = new WebAssembly.Module(view);
+            const instance = new WebAssembly.Instance(module);
+        } catch (e) {
+            if (verbose)
+                print(e);
+        }
+    }
+}
index 68f2512..1428fe0 100644 (file)
@@ -1,3 +1,21 @@
+2018-03-30  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly: support DataView compilation
+        https://bugs.webkit.org/show_bug.cgi?id=183342
+
+        Reviewed by Mark Lam.
+
+        Compiling a module from a DataView was incorrectly dealing with
+        DataView's offset.
+
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parse):
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::getWasmBufferFromValue):
+        (JSC::createSourceBufferFromValue):
+        * wasm/js/WebAssemblyPrototype.cpp:
+        (JSC::webAssemblyValidateFunc):
+
 2018-03-30  Filip Pizlo  <fpizlo@apple.com>
 
         Bytecode generator should not get_from_scope something that may be a hole into a variable that is already live
index 382e6c1..649128a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -69,7 +69,7 @@ auto ModuleParser::parse() -> Result
         uint32_t sectionLength;
         WASM_PARSER_FAIL_IF(!validateOrder(previousKnownSection, section), "invalid section order, ", previousKnownSection, " followed by ", section);
         WASM_PARSER_FAIL_IF(!parseVarUInt32(sectionLength), "can't get ", section, " section's length");
-        WASM_PARSER_FAIL_IF(sectionLength > length() - m_offset, section, "section of size ", sectionLength, " would overflow Module's size");
+        WASM_PARSER_FAIL_IF(sectionLength > length() - m_offset, section, " section of size ", sectionLength, " would overflow Module's size");
 
         auto end = m_offset + sectionLength;
 
index afc5e16..bd06d3c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,7 +49,7 @@ ALWAYS_INLINE uint32_t toNonWrappingUint32(ExecState* exec, JSValue value)
     return static_cast<uint32_t>(doubleValue);
 }
 
-ALWAYS_INLINE uint8_t* getWasmBufferFromValue(ExecState* exec, JSValue value, size_t& byteOffset, size_t& byteSize)
+ALWAYS_INLINE std::pair<uint8_t*, size_t> getWasmBufferFromValue(ExecState* exec, JSValue value)
 {
     VM& vm = exec->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
@@ -59,26 +59,26 @@ ALWAYS_INLINE uint8_t* getWasmBufferFromValue(ExecState* exec, JSValue value, si
     if (!(arrayBuffer || arrayBufferView)) {
         throwException(exec, throwScope, createTypeError(exec,
             ASCIILiteral("first argument must be an ArrayBufferView or an ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(value)));
-        return nullptr;
+        return { nullptr, 0 };
     }
 
     if (arrayBufferView ? arrayBufferView->isNeutered() : arrayBuffer->impl()->isNeutered()) {
         throwException(exec, throwScope, createTypeError(exec,
             ASCIILiteral("underlying TypedArray has been detatched from the ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(value)));
-        return nullptr;
+        return { nullptr, 0 };
     }
 
-    byteOffset = arrayBufferView ? arrayBufferView->byteOffset() : 0;
-    byteSize = arrayBufferView ? arrayBufferView->length() : arrayBuffer->impl()->byteLength();
-    return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
+    uint8_t* base = arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
+    size_t byteSize = arrayBufferView ? arrayBufferView->length() : arrayBuffer->impl()->byteLength();
+    return { base, byteSize };
 }
 
 ALWAYS_INLINE Vector<uint8_t> createSourceBufferFromValue(VM& vm, ExecState* exec, JSValue value)
 {
     auto throwScope = DECLARE_THROW_SCOPE(vm);
-    size_t byteOffset;
+    uint8_t* data;
     size_t byteSize;
-    uint8_t* data = getWasmBufferFromValue(exec, value, byteOffset, byteSize);
+    std::tie(data, byteSize) = getWasmBufferFromValue(exec, value);
     RETURN_IF_EXCEPTION(throwScope, Vector<uint8_t>());
 
     Vector<uint8_t> result;
@@ -88,7 +88,7 @@ ALWAYS_INLINE Vector<uint8_t> createSourceBufferFromValue(VM& vm, ExecState* exe
     }
 
     result.grow(byteSize);
-    memcpy(result.data(), data + byteOffset, byteSize);
+    memcpy(result.data(), data, byteSize);
     return result;
 }
 
index f01e2e1..46441d3 100644 (file)
@@ -220,11 +220,11 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyValidateFunc(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    size_t byteOffset;
+    uint8_t* base;
     size_t byteSize;
-    uint8_t* base = getWasmBufferFromValue(exec, exec->argument(0), byteOffset, byteSize);
+    std::tie(base, byteSize) = getWasmBufferFromValue(exec, exec->argument(0));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    BBQPlan plan(&vm.wasmContext, base + byteOffset, byteSize, BBQPlan::Validation, Plan::dontFinalize());
+    BBQPlan plan(&vm.wasmContext, base, byteSize, BBQPlan::Validation, Plan::dontFinalize());
     // FIXME: We might want to throw an OOM exception here if we detect that something will OOM.
     // https://bugs.webkit.org/show_bug.cgi?id=166015
     return JSValue::encode(jsBoolean(plan.parseAndValidateModule()));