Title: [219969] trunk/JSTests
Revision
219969
Author
[email protected]
Date
2017-07-26 16:29:25 -0700 (Wed, 26 Jul 2017)

Log Message

WebAssembly: test throwing out of the start function
https://bugs.webkit.org/show_bug.cgi?id=165714
<rdar://problem/29760251>

Reviewed by Keith Miller.

* wasm/assert.js:
* wasm/function-tests/trap-from-start.js: Added.
(StartTraps):
* wasm/function-tests/trap-from-start-async.js: Added.
(async.StartTrapsAsync):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (219968 => 219969)


--- trunk/JSTests/ChangeLog	2017-07-26 22:57:06 UTC (rev 219968)
+++ trunk/JSTests/ChangeLog	2017-07-26 23:29:25 UTC (rev 219969)
@@ -1,3 +1,17 @@
+2017-07-26  JF Bastien  <[email protected]>
+
+        WebAssembly: test throwing out of the start function
+        https://bugs.webkit.org/show_bug.cgi?id=165714
+        <rdar://problem/29760251>
+
+        Reviewed by Keith Miller.
+
+        * wasm/assert.js:
+        * wasm/function-tests/trap-from-start.js: Added.
+        (StartTraps):
+        * wasm/function-tests/trap-from-start-async.js: Added.
+        (async.StartTrapsAsync):
+
 2017-07-21  Yusuke Suzuki  <[email protected]>
 
         [FTL] Arguments elimination is suppressed by unreachable blocks

Modified: trunk/JSTests/wasm/assert.js (219968 => 219969)


--- trunk/JSTests/wasm/assert.js	2017-07-26 22:57:06 UTC (rev 219968)
+++ trunk/JSTests/wasm/assert.js	2017-07-26 23:29:25 UTC (rev 219969)
@@ -135,6 +135,28 @@
     _fail(`Expected to throw a ${type.name} with message "${message}"`);
 };
 
+export async function throwsAsync(promise, type, message) {
+    try {
+        await promise;
+    } catch (e) {
+        if (e instanceof type) {
+            if (e.message === 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;
+            }
+        }
+        _fail(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`);
+    }
+    _fail(`Expected to throw a ${type.name} with message "${message}"`);
+}
+
 const _instanceof = (obj, type, msg) => {
     if (!(obj instanceof type))
         _fail(`Expected a ${typeof(type)}, got ${typeof obj}`);

Added: trunk/JSTests/wasm/function-tests/trap-from-start-async.js (0 => 219969)


--- trunk/JSTests/wasm/function-tests/trap-from-start-async.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/trap-from-start-async.js	2017-07-26 23:29:25 UTC (rev 219969)
@@ -0,0 +1,83 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const memoryInfo = { initial: 2 };
+const tableInfo = { element: "anyfunc", initial: 8 };
+
+async function StartTrapsAsync() {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory("imp", "memory", memoryInfo)
+            .Table("imp", "table", tableInfo)
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Start("startMeUp").End()
+        .Element()
+          .Element({ offset: 4, functionIndices: [0, 1] })
+        .End()
+        .Code()
+            .Function("startMeUp", { params: [] })
+                .I32Const(0).I32Load(2, 0).I32Const(0xfeedface).I32Store(2, 0)
+                .I32Const(4).I32Load(2, 0).I32Const(0xc0fec0fe).I32Store(2, 0) // This will trap.
+                // This is unreachable:
+                .I32Const(42).Call(0) // Calls func(42).
+            .End()
+        .End()
+        .Data()
+          .Segment([0xef, 0xbe, 0xad, 0xde]).Offset(1024).End()
+        .End();
+
+    const memory = new WebAssembly.Memory(memoryInfo);
+    const buffer = new Uint32Array(memory.buffer);
+
+    const table = new WebAssembly.Table(tableInfo);
+
+    // The instance will use these as addresses for stores.
+    buffer[0] = 128;
+    buffer[1] = 0xc0defefe; // This is out of bounds.
+
+    // This function shouldn't get called because the trap occurs before the call.
+    let value = 0;
+    const func = v => value = v;
+
+    const module = new WebAssembly.Module(builder.WebAssembly().get());
+    const imp = { imp: { memory, table, func } };
+
+    const promise = WebAssembly.instantiate(module, imp);
+    await assert.throwsAsync(promise, WebAssembly.RuntimeError, `Out of bounds memory access`);
+
+    assert.eq(value, 0);
+
+    for (let i = 0; i < buffer.length; ++i) {
+        switch (i) {
+        case   0: assert.eq(buffer[i], 128);        break; // Initial ArrayBuffer store.
+        case   1: assert.eq(buffer[i], 0xc0defefe); break; // Initial ArrayBuffer store.
+        case  32: assert.eq(buffer[i], 0xfeedface); break; // First store from start function.
+        case 256: assert.eq(buffer[i], 0xdeadbeef); break; // Data segment.
+        default:  assert.eq(buffer[i], 0);          break; // The rest.
+        }
+    }
+
+    for (let i = 0; i < table.length; ++i) {
+        switch (i) {
+        case 4:  assert.isObject(table.get(i)); break;
+        case 5:  assert.isObject(table.get(i)); break;
+        default: assert.eq(table.get(i), null); break;
+        }
+    }
+
+    // Call the imported `func`.
+    table.get(4)(0xf00f);
+    assert.eq(value, 0xf00f);
+    value = 0;
+
+    // Call the start function again on the instance. The instance is otherwise inaccessible!
+    buffer[32] = 0; // Reset the location which will be set by the first store.
+    assert.throws(() => table.get(5)(), WebAssembly.RuntimeError, `Out of bounds memory access`);
+    assert.eq(buffer[32], 0xfeedface); // The first store should still succeed.
+    assert.eq(value, 0);
+}
+
+assert.asyncTest(StartTrapsAsync());

Added: trunk/JSTests/wasm/function-tests/trap-from-start.js (0 => 219969)


--- trunk/JSTests/wasm/function-tests/trap-from-start.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/trap-from-start.js	2017-07-26 23:29:25 UTC (rev 219969)
@@ -0,0 +1,80 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const memoryInfo = { initial: 2 };
+const tableInfo = { element: "anyfunc", initial: 8 };
+
+(function StartTraps() {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory("imp", "memory", memoryInfo)
+            .Table("imp", "table", tableInfo)
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Start("startMeUp").End()
+        .Element()
+          .Element({ offset: 4, functionIndices: [0, 1] })
+        .End()
+        .Code()
+            .Function("startMeUp", { params: [] })
+                .I32Const(0).I32Load(2, 0).I32Const(0xfeedface).I32Store(2, 0)
+                .I32Const(4).I32Load(2, 0).I32Const(0xc0fec0fe).I32Store(2, 0) // This will trap.
+                // This is unreachable:
+                .I32Const(42).Call(0) // Calls func(42).
+            .End()
+        .End()
+        .Data()
+          .Segment([0xef, 0xbe, 0xad, 0xde]).Offset(1024).End()
+        .End();
+
+    const memory = new WebAssembly.Memory(memoryInfo);
+    const buffer = new Uint32Array(memory.buffer);
+
+    const table = new WebAssembly.Table(tableInfo);
+
+    // The instance will use these as addresses for stores.
+    buffer[0] = 128;
+    buffer[1] = 0xc0defefe; // This is out of bounds.
+
+    // This function shouldn't get called because the trap occurs before the call.
+    let value = 0;
+    const func = v => value = v;
+
+    const module = new WebAssembly.Module(builder.WebAssembly().get());
+    const imp = { imp: { memory, table, func } };
+
+    assert.throws(() => new WebAssembly.Instance(module, imp), WebAssembly.RuntimeError, `Out of bounds memory access`);
+
+    assert.eq(value, 0);
+
+    for (let i = 0; i < buffer.length; ++i) {
+        switch (i) {
+        case   0: assert.eq(buffer[i], 128);        break; // Initial ArrayBuffer store.
+        case   1: assert.eq(buffer[i], 0xc0defefe); break; // Initial ArrayBuffer store.
+        case  32: assert.eq(buffer[i], 0xfeedface); break; // First store from start function.
+        case 256: assert.eq(buffer[i], 0xdeadbeef); break; // Data segment.
+        default:  assert.eq(buffer[i], 0);          break; // The rest.
+        }
+    }
+
+    for (let i = 0; i < table.length; ++i) {
+        switch (i) {
+        case 4:  assert.isObject(table.get(i)); break;
+        case 5:  assert.isObject(table.get(i)); break;
+        default: assert.eq(table.get(i), null); break;
+        }
+    }
+
+    // Call the imported `func`.
+    table.get(4)(0xf00f);
+    assert.eq(value, 0xf00f);
+    value = 0;
+
+    // Call the start function again on the instance. The instance is otherwise inaccessible!
+    buffer[32] = 0; // Reset the location which will be set by the first store.
+    assert.throws(() => table.get(5)(), WebAssembly.RuntimeError, `Out of bounds memory access`);
+    assert.eq(buffer[32], 0xfeedface); // The first store should still succeed.
+    assert.eq(value, 0);
+})();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to