Bug 1721718 - wasm: Add OOM checks on getOrCreatePrototype for wasm objects. r=jseward

Differential Revision: https://phabricator.services.mozilla.com/D120533
This commit is contained in:
Ryan Hunt 2021-08-06 18:51:37 +00:00
Родитель ea243fb10a
Коммит 4282ade2e1
4 изменённых файлов: 67 добавлений и 32 удалений

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

@ -0,0 +1 @@
|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); include:wasm.js

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

@ -0,0 +1,29 @@
// |jit-test| skip-if: !('oomTest' in this)
oomTest(() => {
let memory = new WebAssembly.Memory({initial: 0});
assertEq(Object.getPrototypeOf(memory), WebAssembly.Memory.prototype, "prototype");
});
oomTest(() => {
let global = new WebAssembly.Global({value: 'i32'});
assertEq(Object.getPrototypeOf(global), WebAssembly.Global.prototype, "prototype");
});
oomTest(() => {
let table = new WebAssembly.Table({element: 'anyfunc', initial: 0});
assertEq(Object.getPrototypeOf(table), WebAssembly.Table.prototype, "prototype");
});
oomTest(() => {
let bytecode = wasmTextToBinary('(module)');
let module = new WebAssembly.Module(bytecode);
assertEq(Object.getPrototypeOf(module), WebAssembly.Module.prototype, "prototype");
});
oomTest(() => {
let bytecode = wasmTextToBinary('(module)');
let module = new WebAssembly.Module(bytecode);
let instance = new WebAssembly.Instance(module, {});
assertEq(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype, "prototype");
});

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

@ -1041,6 +1041,19 @@ static JSObject* CreateWasmConstructor(JSContext* cx, JSProtoKey key) {
return NewNativeConstructor(cx, Class::construct, 1, className); return NewNativeConstructor(cx, Class::construct, 1, className);
} }
static JSObject* GetWasmConstructorPrototype(JSContext* cx,
const CallArgs& callArgs,
JSProtoKey key) {
RootedObject proto(cx);
if (!GetPrototypeFromBuiltinConstructor(cx, callArgs, key, &proto)) {
return nullptr;
}
if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, key);
}
return proto;
}
// ============================================================================ // ============================================================================
// WebAssembly.Module class and methods // WebAssembly.Module class and methods
@ -1581,13 +1594,11 @@ bool WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp) {
return false; return false;
} }
RootedObject proto(cx); RootedObject proto(
if (!GetPrototypeFromBuiltinConstructor(cx, callArgs, JSProto_WasmModule, cx, GetWasmConstructorPrototype(cx, callArgs, JSProto_WasmModule));
&proto)) {
return false;
}
if (!proto) { if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmModule); ReportOutOfMemory(cx);
return false;
} }
RootedObject moduleObj(cx, WasmModuleObject::create(cx, *module, proto)); RootedObject moduleObj(cx, WasmModuleObject::create(cx, *module, proto));
@ -1861,15 +1872,12 @@ bool WasmInstanceObject::construct(JSContext* cx, unsigned argc, Value* vp) {
return false; return false;
} }
RootedObject instanceProto(cx); RootedObject proto(
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmInstance, cx, GetWasmConstructorPrototype(cx, args, JSProto_WasmInstance));
&instanceProto)) { if (!proto) {
ReportOutOfMemory(cx);
return false; return false;
} }
if (!instanceProto) {
instanceProto =
GlobalObject::getOrCreatePrototype(cx, JSProto_WasmInstance);
}
Rooted<ImportValues> imports(cx); Rooted<ImportValues> imports(cx);
if (!GetImports(cx, *module, importObj, imports.address())) { if (!GetImports(cx, *module, importObj, imports.address())) {
@ -1877,7 +1885,7 @@ bool WasmInstanceObject::construct(JSContext* cx, unsigned argc, Value* vp) {
} }
RootedWasmInstanceObject instanceObj(cx); RootedWasmInstanceObject instanceObj(cx);
if (!module->instantiate(cx, imports.get(), instanceProto, &instanceObj)) { if (!module->instantiate(cx, imports.get(), proto, &instanceObj)) {
return false; return false;
} }
@ -2418,13 +2426,11 @@ bool WasmMemoryObject::construct(JSContext* cx, unsigned argc, Value* vp) {
return false; return false;
} }
RootedObject proto(cx); RootedObject proto(cx,
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmMemory, GetWasmConstructorPrototype(cx, args, JSProto_WasmMemory));
&proto)) {
return false;
}
if (!proto) { if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmMemory); ReportOutOfMemory(cx);
return false;
} }
RootedWasmMemoryObject memoryObj(cx, RootedWasmMemoryObject memoryObj(cx,
@ -2955,13 +2961,11 @@ bool WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp) {
return false; return false;
} }
RootedObject proto(cx); RootedObject proto(cx,
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmTable, GetWasmConstructorPrototype(cx, args, JSProto_WasmTable));
&proto)) {
return false;
}
if (!proto) { if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmTable); ReportOutOfMemory(cx);
return false;
} }
// The rest of the runtime expects table limits to be within a 32-bit range. // The rest of the runtime expects table limits to be within a 32-bit range.
@ -3406,13 +3410,11 @@ bool WasmGlobalObject::construct(JSContext* cx, unsigned argc, Value* vp) {
} }
} }
RootedObject proto(cx); RootedObject proto(cx,
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WasmGlobal, GetWasmConstructorPrototype(cx, args, JSProto_WasmGlobal));
&proto)) {
return false;
}
if (!proto) { if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_WasmGlobal); ReportOutOfMemory(cx);
return false;
} }
WasmGlobalObject* global = WasmGlobalObject* global =

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

@ -1141,6 +1141,7 @@ static bool CreateExportObject(
propertyAttr |= JSPROP_READONLY | JSPROP_PERMANENT; propertyAttr |= JSPROP_READONLY | JSPROP_PERMANENT;
} }
if (!exportObj) { if (!exportObj) {
ReportOutOfMemory(cx);
return false; return false;
} }
@ -1261,6 +1262,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports,
maybeDebug = cx->make_unique<DebugState>(*code, *this); maybeDebug = cx->make_unique<DebugState>(*code, *this);
if (!maybeDebug) { if (!maybeDebug) {
ReportOutOfMemory(cx);
return false; return false;
} }
} else { } else {
@ -1288,6 +1290,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports,
// final pre-requisite for a live instance. // final pre-requisite for a live instance.
if (!cx->realm()->wasm.registerInstance(cx, instance)) { if (!cx->realm()->wasm.registerInstance(cx, instance)) {
ReportOutOfMemory(cx);
return false; return false;
} }