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
- trunk/JSTests/ChangeLog
- trunk/JSTests/wasm/assert.js
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp
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
