Title: [214438] trunk
Revision
214438
Author
[email protected]
Date
2017-03-27 16:24:31 -0700 (Mon, 27 Mar 2017)

Log Message

WebAssembly: misc memory testing
https://bugs.webkit.org/show_bug.cgi?id=170137

Reviewed by Keith Miller.

JSTests:

* wasm/assert.js: handle newlines in code we print out, avoid regex
* wasm/function-tests/memory-import-and-grow.js: Added.
(const.instantiate):
(const.test):
* wasm/function-tests/memory-section-and-import.js: Added.
(const.instantiate):

Source/_javascript_Core:

* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::WebAssemblyInstanceConstructor::createInstance): improve error messages

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (214437 => 214438)


--- trunk/JSTests/ChangeLog	2017-03-27 23:21:19 UTC (rev 214437)
+++ trunk/JSTests/ChangeLog	2017-03-27 23:24:31 UTC (rev 214438)
@@ -1,3 +1,17 @@
+2017-03-27  JF Bastien  <[email protected]>
+
+        WebAssembly: misc memory testing
+        https://bugs.webkit.org/show_bug.cgi?id=170137
+
+        Reviewed by Keith Miller.
+
+        * wasm/assert.js: handle newlines in code we print out, avoid regex
+        * wasm/function-tests/memory-import-and-grow.js: Added.
+        (const.instantiate):
+        (const.test):
+        * wasm/function-tests/memory-section-and-import.js: Added.
+        (const.instantiate):
+
 2017-03-23  Yusuke Suzuki  <[email protected]>
 
         [JSC] Use jsNontrivialString agressively for ToString(Int52)

Modified: trunk/JSTests/wasm/assert.js (214437 => 214438)


--- trunk/JSTests/wasm/assert.js	2017-03-27 23:21:19 UTC (rev 214437)
+++ trunk/JSTests/wasm/assert.js	2017-03-27 23:24:31 UTC (rev 214438)
@@ -111,9 +111,6 @@
         _fail(`Expected: "${lhs}" > "${rhs}"`, msg);
 };
 
-// Ignore source information at the end of the error message if the expected message didn't specify that information. Sometimes it changes, or it's tricky to get just right.
-const _sourceRe = new RegExp(/( \(evaluating '.*'\))|( \(In .*\))/);
-
 const _throws = (func, type, message, ...args) => {
     try {
         func(...args);
@@ -121,9 +118,16 @@
         if (e instanceof type) {
             if (e.message === message)
                 return e;
-            const cleanMessage = e.message.replace(_sourceRe, '');
-            if (cleanMessage === message)
-                return e;
+            // Ignore source information at the end of the error message if the
+            // expected message didn't specify that information. Sometimes it
+            // changes, or it's tricky to get just right.
+            const evaluatingIndex = e.message.indexOf(" (evaluating '");
+            if (evaluatingIndex !== -1) {
+                const cleanMessage = e.message.substring(0, evaluatingIndex);
+                if (cleanMessage === message)
+                    return e;
+            }
+            return e;
         }
         _fail(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`);
     }

Added: trunk/JSTests/wasm/function-tests/memory-import-and-grow.js (0 => 214438)


--- trunk/JSTests/wasm/function-tests/memory-import-and-grow.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/memory-import-and-grow.js	2017-03-27 23:24:31 UTC (rev 214438)
@@ -0,0 +1,131 @@
+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+const pageSize = 64 * 1024;
+
+const verbose = false;
+
+// https://github.com/WebAssembly/design/blob/master/Modules.md#imports
+// Says:
+//
+// A linear memory import includes the same set of fields defined in the Linear
+// Memory section: initial length and optional maximum length. The host
+// environment must only allow imports of WebAssembly linear memories that have
+// initial length greater-or-equal than the initial length declared in the
+// import and that have maximum length less-or-equal than the maximum length
+// declared in the import. This ensures that separate compilation can assume:
+// memory accesses below the declared initial length are always in-bounds,
+// accesses above the declared maximum length are always out-of-bounds and if
+// initial equals maximum, the length is fixed.
+
+const instantiate = (builder, importObject = undefined) => {
+    return new WebAssembly.Instance(
+        new WebAssembly.Module(
+            builder.WebAssembly().get()),
+        importObject);
+};
+
+const test = (memoryToImport, importedMemoryDeclaration, growMemoryToImportBy = undefined, growImportedMemoryDeclarationBy = undefined, expectedFinal) => {
+    const builder0 = (new Builder())
+          .Type().End()
+          .Function().End()
+          .Memory().InitialMaxPages(memoryToImport.initial, memoryToImport.maximum).End()
+          .Export()
+              .Function("current").Function("grow").Function("get")
+              .Memory("memory", 0)
+          .End()
+          .Code()
+              .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
+              .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
+              .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
+          .End();
+
+    const builder1 = (new Builder())
+          .Type().End()
+          .Import().Memory("imp", "memory", importedMemoryDeclaration).End()
+          .Function().End()
+          .Export()
+              .Function("current").Function("grow").Function("get")
+              .Memory("memory", 0)
+          .End()
+          .Code()
+              .Function("current", { params: [], ret: "i32" }).CurrentMemory(0).Return().End()
+              .Function("grow", { params: ["i32"], ret: "i32" }).GetLocal(0).GrowMemory(0).Return().End()
+              .Function("get", { params: ["i32"], ret: "i32" }).GetLocal(0).I32Load(2, 0).Return().End()
+          .End();
+
+    const i0 = instantiate(builder0);
+    const i1 = instantiate(builder1, { imp: { memory: i0.exports.memory } });
+    assert.eq(i0.exports.current(), i1.exports.current());
+    assert.eq(i0.exports.current(), memoryToImport.initial);
+
+    if (growMemoryToImportBy !== undefined) {
+        const grow = i0.exports.grow(growMemoryToImportBy);
+        if (verbose)
+            print(`currents: ${i0.exports.current()} and ${i1.exports.current()} -- grow result: ${grow}`);
+    }
+
+    if (growImportedMemoryDeclarationBy !== undefined) {
+        const grow = i1.exports.grow(growImportedMemoryDeclarationBy);
+        if (verbose)
+            print(`currents: ${i0.exports.current()} and ${i1.exports.current()} -- grow result: ${grow}`);
+    }
+
+    assert.eq(i0.exports.current(), i1.exports.current());
+    assert.eq(i0.exports.current(), expectedFinal);
+};
+
+const u = undefined;
+
+// Identical Just Works.
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, 0, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, 1, u, 3);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, 2, u, 4);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, 3, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, u, 0, 2);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, u, 1, 3);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, u, 2, 4);
+test({ initial: 2, maximum: 4 }, { initial: 2, maximum: 4 }, u, 3, 2);
+
+// Allowed: imported initial is greater than declared.
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, 0, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, 1, u, 3);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, 2, u, 4);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, 3, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, 0, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, 1, u, 3);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, 2, u, 4);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, 3, u, 2);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, u, 0, 2);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, u, 1, 3);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, u, 2, 4);
+test({ initial: 2, maximum: 4 }, { initial: 1, maximum: 4 }, u, 3, 2);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, u, 0, 2);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, u, 1, 3);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, u, 2, 4);
+test({ initial: 2, maximum: 4 }, { initial: 0, maximum: 4 }, u, 3, 2);
+
+// Allowed: imported maximum is lesser than declared.
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, 0, u, 2);
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, 1, u, 3);
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, 2, u, 2);
+test({ initial: 2, maximum: 2 }, { initial: 2, maximum: 4 }, 0, u, 2);
+test({ initial: 2, maximum: 2 }, { initial: 2, maximum: 4 }, 1, u, 2);
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, u, 0, 2);
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, u, 1, 3);
+test({ initial: 2, maximum: 3 }, { initial: 2, maximum: 4 }, u, 2, 2);
+test({ initial: 2, maximum: 2 }, { initial: 2, maximum: 4 }, u, 0, 2);
+test({ initial: 2, maximum: 2 }, { initial: 2, maximum: 4 }, u, 1, 2);
+
+// Allowed: no declared maximum, same as above.
+test({ initial: 2, maximum: 4 }, { initial: 2 }, 0, u, 2);
+
+// Disallowed: imported initial is lesser than declared.
+assert.throws(() => test({ initial: 1, maximum: 4 }, { initial: 2, maximum: 4 }, u, u, 2), WebAssembly.LinkError, `Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size`);
+assert.throws(() => test({ initial: 0, maximum: 4 }, { initial: 2, maximum: 4 }, u, u, 2), WebAssembly.LinkError, `Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size`);
+
+// Disallowed: imported maximum is greater than declared.
+assert.throws(() => test({ initial: 2, maximum: 5 }, { initial: 2, maximum: 4 }, u, u, 2), WebAssembly.LinkError, `Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size`);
+
+// Disallowed: no imported maximum, same as above.
+assert.throws(() => test({ initial: 2 }, { initial: 2, maximum: 4 }, 0, u, 2), WebAssembly.LinkError, `Memory import did not have a 'maximum' but the module requires that it does`);

Added: trunk/JSTests/wasm/function-tests/memory-section-and-import.js (0 => 214438)


--- trunk/JSTests/wasm/function-tests/memory-section-and-import.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/memory-section-and-import.js	2017-03-27 23:24:31 UTC (rev 214438)
@@ -0,0 +1,31 @@
+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+const instantiate = (builder, importObject = undefined) => {
+    return new WebAssembly.Instance(
+        new WebAssembly.Module(
+            builder.WebAssembly().get()),
+        importObject);
+};
+
+const initial = 0;
+const maximum = 2;
+
+const builder0 = (new Builder())
+      .Type().End()
+      .Function().End()
+      .Memory().InitialMaxPages(initial, maximum).End()
+      .Export()
+          .Memory("memory", 0)
+      .End()
+      .Code().End();
+
+const builder1 = (new Builder())
+      .Type().End()
+      .Import().Memory("imp", "memory", { initial: initial, maximum: maximum }).End()
+      .Function().End()
+      .Memory().InitialMaxPages(initial, maximum).End()
+      .Code().End();
+
+const i0 = instantiate(builder0);
+assert.throws(() => instantiate(builder1, { imp: { memory: i0.exports.memory } }), WebAssembly.CompileError, `WebAssembly.Module doesn't parse at byte 34 / 40: Memory section cannot exist if an Import has a memory`);

Modified: trunk/Source/_javascript_Core/ChangeLog (214437 => 214438)


--- trunk/Source/_javascript_Core/ChangeLog	2017-03-27 23:21:19 UTC (rev 214437)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-03-27 23:24:31 UTC (rev 214438)
@@ -1,3 +1,13 @@
+2017-03-27  JF Bastien  <[email protected]>
+
+        WebAssembly: misc memory testing
+        https://bugs.webkit.org/show_bug.cgi?id=170137
+
+        Reviewed by Keith Miller.
+
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::WebAssemblyInstanceConstructor::createInstance): improve error messages
+
 2017-03-27  Michael Saboff  <[email protected]>
 
         Add ARM64 system instructions to disassembler

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp (214437 => 214438)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2017-03-27 23:21:19 UTC (rev 214437)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2017-03-27 23:24:31 UTC (rev 214438)
@@ -168,16 +168,16 @@
             if (!table)
                 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import is not an instance of WebAssembly.Table")));
 
-            uint32_t expectedInitial = moduleInformation.tableInformation.initial();
-            uint32_t actualInitial = table->size();
-            if (actualInitial < expectedInitial)
+            uint32_t declaredInitial = moduleInformation.tableInformation.initial();
+            uint32_t importedInitial = table->size();
+            if (importedInitial < declaredInitial)
                 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import provided an 'initial' that is too small")));
 
-            if (std::optional<uint32_t> expectedMaximum = moduleInformation.tableInformation.maximum()) {
-                std::optional<uint32_t> actualMaximum = table->maximum();
-                if (!actualMaximum)
+            if (std::optional<uint32_t> declaredMaximum = moduleInformation.tableInformation.maximum()) {
+                std::optional<uint32_t> importedMaximum = table->maximum();
+                if (!importedMaximum)
                     return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import does not have a 'maximum' but the module requires that it does")));
-                if (*actualMaximum > *expectedMaximum)
+                if (*importedMaximum > *declaredMaximum)
                     return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Imported Table's 'maximum' is larger than the module's expected 'maximum'")));
             }
 
@@ -196,18 +196,18 @@
             if (!memory)
                 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import is not an instance of WebAssembly.Memory")));
 
-            Wasm::PageCount expectedInitial = moduleInformation.memory.initial();
-            Wasm::PageCount actualInitial = memory->memory().initial();
-            if (actualInitial < expectedInitial)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided an 'initial' that is too small")));
+            Wasm::PageCount declaredInitial = moduleInformation.memory.initial();
+            Wasm::PageCount importedInitial = memory->memory().initial();
+            if (importedInitial < declaredInitial)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size")));
 
-            if (Wasm::PageCount expectedMaximum = moduleInformation.memory.maximum()) {
-                Wasm::PageCount actualMaximum = memory->memory().maximum();
-                if (!actualMaximum)
+            if (Wasm::PageCount declaredMaximum = moduleInformation.memory.maximum()) {
+                Wasm::PageCount importedMaximum = memory->memory().maximum();
+                if (!importedMaximum)
                     return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import did not have a 'maximum' but the module requires that it does")));
 
-                if (actualMaximum > expectedMaximum)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory imports 'maximum' is larger than the module's expected 'maximum'")));
+                if (importedMaximum > declaredMaximum)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size")));
             }
 
             // ii. Append v to memories.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to