Bug 1368844: Check WebAssembly.{Memory,Table} sizes against internal limits; r=luke

MozReview-Commit-ID: GZSVjza1RfL

--HG--
extra : rebase_source : 6605bb3f911a87ce0b46920873a9db73880bec0a
This commit is contained in:
Benjamin Bouvier 2017-05-31 17:23:12 +02:00
Родитель 064920e81e
Коммит 54b6961485
5 изменённых файлов: 34 добавлений и 16 удалений

Просмотреть файл

@ -131,14 +131,17 @@ wasmEvalText('(module (import $foo "a" "" (result f64)))', {a:{"":()=>{}}});
wasmValidateText('(module (memory 0))'); wasmValidateText('(module (memory 0))');
wasmValidateText('(module (memory 1))'); wasmValidateText('(module (memory 1))');
wasmFailValidateText('(module (memory 65536))', /initial memory size too big/); wasmValidateText('(module (memory 16384))');
wasmFailValidateText('(module (memory 16385))', /initial memory size too big/);
wasmEvalText('(module (memory 0 65536))')
wasmFailValidateText('(module (memory 0 65537))', /maximum memory size too big/);
// May OOM, but must not crash: // May OOM, but must not crash:
try { try {
wasmEvalText('(module (memory 65535))'); wasmEvalText('(module (memory 16384))');
} catch (e) { } catch (e) {
assertEq(String(e).indexOf("out of memory") != -1 || assertEq(String(e).indexOf("out of memory") !== -1, true);
String(e).indexOf("memory size too big") != -1, true);
} }
var buf = wasmEvalText('(module (memory 1) (export "memory" memory))').exports.memory.buffer; var buf = wasmEvalText('(module (memory 1) (export "memory" memory))').exports.memory.buffer;

Просмотреть файл

@ -19,8 +19,27 @@ const tab2Elem = new Table({initial:2, element:"anyfunc"});
const tab3Elem = new Table({initial:3, element:"anyfunc"}); const tab3Elem = new Table({initial:3, element:"anyfunc"});
const tab4Elem = new Table({initial:4, element:"anyfunc"}); const tab4Elem = new Table({initial:4, element:"anyfunc"});
// Memory size consistency and internal limits.
assertErrorMessage(() => new Memory({initial:2, maximum:1}), RangeError, /bad Memory maximum size/); assertErrorMessage(() => new Memory({initial:2, maximum:1}), RangeError, /bad Memory maximum size/);
try {
new Memory({initial:16384});
} catch(e) {
assertEq(String(e).indexOf("out of memory") !== -1, true);
}
assertErrorMessage(() => new Memory({initial: 16385}), RangeError, /bad Memory initial size/);
new Memory({initial: 0, maximum: 65536});
assertErrorMessage(() => new Memory({initial: 0, maximum: 65537}), RangeError, /bad Memory maximum size/);
// Table size consistency and internal limits.
assertErrorMessage(() => new Table({initial:2, maximum:1, element:"anyfunc"}), RangeError, /bad Table maximum size/);
new Table({ initial: 10000000, element:"anyfunc" });
assertErrorMessage(() => new Table({initial:10000001, element:"anyfunc"}), RangeError, /bad Table initial size/);
new Table({ initial: 0, maximum: 2**32 - 1, element:"anyfunc" });
assertErrorMessage(() => new Table({initial:0, maximum: 2**32, element:"anyfunc"}), RangeError, /bad Table maximum size/);
const m1 = new Module(wasmTextToBinary('(module (import "foo" "bar") (import "baz" "quux"))')); const m1 = new Module(wasmTextToBinary('(module (import "foo" "bar") (import "baz" "quux"))'));
assertErrorMessage(() => new Instance(m1), TypeError, /second argument must be an object/); assertErrorMessage(() => new Instance(m1), TypeError, /second argument must be an object/);
assertErrorMessage(() => new Instance(m1, {foo:null}), TypeError, /import object field 'foo' is not an Object/); assertErrorMessage(() => new Instance(m1, {foo:null}), TypeError, /import object field 'foo' is not an Object/);

Просмотреть файл

@ -274,10 +274,6 @@ for (var foldOffsets = 0; foldOffsets <= 1; foldOffsets++) {
wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))', mismatchError("f32", "i32")); wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))', mismatchError("f32", "i32"));
wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))', mismatchError("f64", "i32")); wasmFailValidateText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))', mismatchError("f64", "i32"));
wasmEvalText('(module (memory 0 65535))')
wasmEvalText('(module (memory 0 65536))')
wasmFailValidateText('(module (memory 0 65537))', /maximum memory size too big/);
// Test high charge of registers // Test high charge of registers
function testRegisters() { function testRegisters() {
assertEq(wasmEvalText( assertEq(wasmEvalText(

Просмотреть файл

@ -710,6 +710,7 @@ ArrayBufferObject::createForWasm(JSContext* cx, uint32_t initialSize,
{ {
MOZ_ASSERT(initialSize % wasm::PageSize == 0); MOZ_ASSERT(initialSize % wasm::PageSize == 0);
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers()); MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
MOZ_RELEASE_ASSERT((initialSize / wasm::PageSize) <= wasm::MaxMemoryInitialPages);
// Prevent applications specifying a large max (like UINT32_MAX) from // Prevent applications specifying a large max (like UINT32_MAX) from
// unintentially OOMing the browser on 32-bit: they just want "a lot of // unintentially OOMing the browser on 32-bit: they just want "a lot of

Просмотреть файл

@ -423,8 +423,7 @@ ToNonWrappingUint32(JSContext* cx, HandleValue v, uint32_t max, const char* kind
return false; return false;
if (dbl < 0 || dbl > max) { if (dbl < 0 || dbl > max) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_UINT32, JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_UINT32, kind, noun);
kind, noun);
return false; return false;
} }
@ -434,8 +433,8 @@ ToNonWrappingUint32(JSContext* cx, HandleValue v, uint32_t max, const char* kind
} }
static bool static bool
GetLimits(JSContext* cx, HandleObject obj, uint32_t max, const char* kind, GetLimits(JSContext* cx, HandleObject obj, uint32_t maxInitial, uint32_t maxMaximum,
Limits* limits) const char* kind, Limits* limits)
{ {
JSAtom* initialAtom = Atomize(cx, "initial", strlen("initial")); JSAtom* initialAtom = Atomize(cx, "initial", strlen("initial"));
if (!initialAtom) if (!initialAtom)
@ -446,7 +445,7 @@ GetLimits(JSContext* cx, HandleObject obj, uint32_t max, const char* kind,
if (!GetProperty(cx, obj, obj, initialId, &initialVal)) if (!GetProperty(cx, obj, obj, initialId, &initialVal))
return false; return false;
if (!ToNonWrappingUint32(cx, initialVal, max, kind, "initial size", &limits->initial)) if (!ToNonWrappingUint32(cx, initialVal, maxInitial, kind, "initial size", &limits->initial))
return false; return false;
JSAtom* maximumAtom = Atomize(cx, "maximum", strlen("maximum")); JSAtom* maximumAtom = Atomize(cx, "maximum", strlen("maximum"));
@ -461,7 +460,7 @@ GetLimits(JSContext* cx, HandleObject obj, uint32_t max, const char* kind,
return false; return false;
limits->maximum.emplace(); limits->maximum.emplace();
if (!ToNonWrappingUint32(cx, maxVal, max, kind, "maximum size", limits->maximum.ptr())) if (!ToNonWrappingUint32(cx, maxVal, maxMaximum, kind, "maximum size", limits->maximum.ptr()))
return false; return false;
if (limits->initial > *limits->maximum) { if (limits->initial > *limits->maximum) {
@ -1343,7 +1342,7 @@ WasmMemoryObject::construct(JSContext* cx, unsigned argc, Value* vp)
RootedObject obj(cx, &args[0].toObject()); RootedObject obj(cx, &args[0].toObject());
Limits limits; Limits limits;
if (!GetLimits(cx, obj, UINT32_MAX / PageSize, "Memory", &limits)) if (!GetLimits(cx, obj, MaxMemoryInitialPages, MaxMemoryMaximumPages, "Memory", &limits))
return false; return false;
limits.initial *= PageSize; limits.initial *= PageSize;
@ -1654,7 +1653,7 @@ WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp)
} }
Limits limits; Limits limits;
if (!GetLimits(cx, obj, UINT32_MAX, "Table", &limits)) if (!GetLimits(cx, obj, MaxTableInitialLength, UINT32_MAX, "Table", &limits))
return false; return false;
RootedWasmTableObject table(cx, WasmTableObject::create(cx, limits)); RootedWasmTableObject table(cx, WasmTableObject::create(cx, limits));