blob: cca0cf3bc45d0f4dd33bd9ca59798954d2d45b18 [file] [log] [blame]
import * as assert from '../assert.js';
import Builder from '../Builder.js';
const memSizeInPages = 1;
const pageSizeInBytes = 64 * 1024;
const memoryDescription = { initial: memSizeInPages, maximum: memSizeInPages };
const emptyMemory = { initial: 0, maximum: 2 };
// FIXME Some corner cases are ill-specified: https://github.com/WebAssembly/design/issues/897
const assertMemoryAllZero = memory => {
const buffer = new Uint8Array(memory.buffer);
for (let idx = 0; idx < buffer.length; ++idx) {
const value = buffer[idx];
assert.eq(value, 0x00);
}
};
(function DataSection() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", memoryDescription).End()
.Data()
.Segment([0xff, 0x2a]).Offset(4).End()
.Segment([0xde, 0xad, 0xbe, 0xef]).Offset(24).End()
.Segment([0xca, 0xfe]).Offset(25).End() // Overwrite.
.Segment([]).Offset(4).End() // Empty.
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
const instance = new WebAssembly.Instance(module, { imp: { memory: memory } });
const buffer = new Uint8Array(memory.buffer);
for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
const value = buffer[idx];
switch (idx) {
case 4: assert.eq(value, 0xff); break;
case 5: assert.eq(value, 0x2a); break;
case 24: assert.eq(value, 0xde); break;
case 25: assert.eq(value, 0xca); break;
case 26: assert.eq(value, 0xfe); break;
case 27: assert.eq(value, 0xef); break;
default: assert.eq(value, 0x00); break;
}
}
})();
(function DataSectionWithoutMemory() {
const builder = (new Builder())
.Type().End()
.Data()
.Segment([0xff]).Offset(0).End()
.End();
const bin = builder.WebAssembly().get();
assert.throws(() => new WebAssembly.Module(bin), WebAssembly.CompileError, `WebAssembly.Module doesn't parse at byte 15 / 20: 0th Data segment has index 0 which exceeds the number of Memories 0`);
})();
(function EmptyDataSectionWithoutMemory() {
const builder = (new Builder())
.Type().End()
.Data()
.Segment([]).Offset(0).End()
.End();
const bin = builder.WebAssembly().get();
assert.throws(() => new WebAssembly.Module(bin), WebAssembly.CompileError, `WebAssembly.Module doesn't parse at byte 15 / 19: 0th Data segment has index 0 which exceeds the number of Memories 0`);
})();
(function DataSectionBiggerThanMemory() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", memoryDescription).End()
.Data()
.Segment(Array(memSizeInPages * pageSizeInBytes + 1).fill(0xff)).Offset(0).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), WebAssembly.LinkError, `Invalid data segment initialization: segment of 65537 bytes memory of 65536 bytes, at offset 0, segment is too big (evaluating 'new WebAssembly.Instance(module, { imp: { memory: memory } })')`);
assertMemoryAllZero(memory);
})();
(function DataSectionOffTheEnd() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", memoryDescription).End()
.Data()
.Segment([0xff]).Offset(memSizeInPages * pageSizeInBytes).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), WebAssembly.LinkError, `Invalid data segment initialization: segment of 1 bytes memory of 65536 bytes, at offset 65536, segment writes outside of memory (evaluating 'new WebAssembly.Instance(module, { imp: { memory: memory } })')`);
assertMemoryAllZero(memory);
})();
(function DataSectionPartlyOffTheEnd() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", memoryDescription).End()
.Data()
.Segment([0xff, 0xff]).Offset(memSizeInPages * pageSizeInBytes - 1).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), WebAssembly.LinkError, `Invalid data segment initialization: segment of 2 bytes memory of 65536 bytes, at offset 65535, segment writes outside of memory (evaluating 'new WebAssembly.Instance(module, { imp: { memory: memory } })')`);
assertMemoryAllZero(memory);
})();
(function DataSectionEmptyOffTheEnd() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", memoryDescription).End()
.Data()
.Segment([]).Offset(memSizeInPages * pageSizeInBytes).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
const instance = new WebAssembly.Instance(module, { imp: { memory: memory } });
assertMemoryAllZero(memory);
})();
(function DataSectionEmptyOffTheEndWithEmptyMemory() {
const builder = (new Builder())
.Type().End()
.Import().Memory("imp", "memory", emptyMemory).End()
.Data()
.Segment([]).Offset(memSizeInPages * pageSizeInBytes).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(emptyMemory);
assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), WebAssembly.LinkError, `Invalid data segment initialization: segment of 0 bytes memory of 0 bytes, at offset 65536, segment writes outside of memory`);
assertMemoryAllZero(memory);
})();
(function DataSectionSeenByStart() {
const offset = 1024;
const builder = (new Builder())
.Type().End()
.Import()
.Memory("imp", "memory", memoryDescription)
.Function("imp", "func", { params: ["i32"] })
.End()
.Function().End()
.Start("foo").End()
.Code()
.Function("foo", { params: [] })
.I32Const(offset)
.I32Load8U(0, 0)
.Call(0) // Calls func((i8.load(offset), align=2, offset=0). This should observe 0xff as set by the data section.
.End()
.End()
.Data()
.Segment([0xff]).Offset(offset).End()
.End();
const bin = builder.WebAssembly().get();
const module = new WebAssembly.Module(bin);
const memory = new WebAssembly.Memory(memoryDescription);
let value = 0;
const setter = v => value = v;
const instance = new WebAssembly.Instance(
module,
{
imp: {
memory: memory,
func: setter
}
});
assert.eq(value, 0xff);
const buffer = new Uint8Array(memory.buffer);
for (let idx = 0; idx < memSizeInPages * pageSizeInBytes; ++idx) {
const value = buffer[idx];
if (idx == offset)
assert.eq(value, 0xff);
else
assert.eq(value, 0x00);
}
})();