Bug 1292724 - Baldr: don't fail to validate i64 imports and exports; throw runtime errors (r=sunfish)

MozReview-Commit-ID: 8KDCNutTjnB

--HG--
extra : rebase_source : 7175217d7ad93d6c2a26b022052961c4aa48170b
This commit is contained in:
Luke Wagner 2016-08-26 12:51:13 -05:00
Родитель 3bef492837
Коммит f7ea839a1d
7 изменённых файлов: 36 добавлений и 47 удалений

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

@ -587,24 +587,6 @@ DecodeFunctionSection(Decoder& d, ModuleGeneratorData* init)
return true;
}
static bool
CheckTypeForJS(Decoder& d, const Sig& sig)
{
for (ValType argType : sig.args()) {
if (argType == ValType::I64 && !JitOptions.wasmTestMode)
return Fail(d, "cannot import/export i64 argument");
if (IsSimdType(argType))
return Fail(d, "cannot import/export SIMD argument");
}
if (sig.ret() == ExprType::I64 && !JitOptions.wasmTestMode)
return Fail(d, "cannot import/export i64 return type");
if (IsSimdType(sig.ret()))
return Fail(d, "cannot import/export SIMD return type");
return true;
}
static UniqueChars
MaybeDecodeName(Decoder& d)
{
@ -766,9 +748,6 @@ DecodeImport(Decoder& d, bool newFormat, ModuleGeneratorData* init, ImportVector
if (!DecodeSignatureIndex(d, *init, &sig))
return false;
if (!CheckTypeForJS(d, *sig))
return false;
if (!init->funcImports.emplaceBack(sig))
return false;
@ -806,8 +785,6 @@ DecodeImport(Decoder& d, bool newFormat, ModuleGeneratorData* init, ImportVector
const SigWithId* sig = nullptr;
if (!DecodeSignatureIndex(d, *init, &sig))
return false;
if (!CheckTypeForJS(d, *sig))
return false;
if (!init->funcImports.emplaceBack(sig))
return false;
break;
@ -1103,9 +1080,6 @@ DecodeExport(Decoder& d, bool newFormat, ModuleGenerator& mg, CStringSet* dupSet
if (funcIndex >= mg.numFuncSigs())
return Fail(d, "exported function index out of bounds");
if (!CheckTypeForJS(d, mg.funcSig(funcIndex)))
return false;
UniqueChars fieldName = DecodeExportName(d, dupSet);
if (!fieldName)
return false;
@ -1130,9 +1104,6 @@ DecodeExport(Decoder& d, bool newFormat, ModuleGenerator& mg, CStringSet* dupSet
if (funcIndex >= mg.numFuncSigs())
return Fail(d, "exported function index out of bounds");
if (!CheckTypeForJS(d, mg.funcSig(funcIndex)))
return false;
return mg.addFuncExport(Move(fieldName), funcIndex);
}
case DefinitionKind::Table: {

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

@ -133,7 +133,10 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
args[i].set(JS::CanonicalizedDoubleValue(*(double*)&argv[i]));
break;
case ValType::I64: {
MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
if (!JitOptions.wasmTestMode) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
return false;
}
RootedObject obj(cx, CreateI64Object(cx, *(int64_t*)&argv[i]));
if (!obj)
return false;
@ -160,6 +163,12 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
if (!Call(cx, fval, thisv, args, rval))
return false;
// Throw an error if returning i64 and not in test mode.
if (!JitOptions.wasmTestMode && fi.sig().ret() == ExprType::I64) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
return false;
}
// Don't try to optimize if the function has at least one i64 arg or if
// it returns an int64. GenerateJitExit relies on this, as does the
// type inference code below in this function.
@ -539,7 +548,10 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
return false;
break;
case ValType::I64:
MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
if (!JitOptions.wasmTestMode) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
return false;
}
if (!ReadI64Object(cx, v, (int64_t*)&exportArgs[i]))
return false;
break;
@ -655,7 +667,10 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
args.rval().set(Int32Value(*(int32_t*)retAddr));
break;
case ExprType::I64:
MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
if (!JitOptions.wasmTestMode) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64);
return false;
}
retObj = CreateI64Object(cx, *(int64_t*)retAddr);
if (!retObj)
return false;

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

@ -168,7 +168,6 @@ wasm::GenerateEntry(MacroAssembler& masm, const FuncExport& fe)
unsigned argOffset = iter.index() * sizeof(ExportArg);
Address src(argv, argOffset);
MIRType type = iter.mirType();
MOZ_ASSERT_IF(type == MIRType::Int64, JitOptions.wasmTestMode);
switch (iter->kind()) {
case ABIArg::GPR:
if (type == MIRType::Int32)
@ -283,7 +282,6 @@ wasm::GenerateEntry(MacroAssembler& masm, const FuncExport& fe)
masm.store32(ReturnReg, Address(argv, 0));
break;
case ExprType::I64:
MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
masm.store64(ReturnReg64, Address(argv, 0));
break;
case ExprType::F32:
@ -334,8 +332,6 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
Address dstAddr(masm.getStackPointer(), argOffset + i.index() * sizeof(Value));
MIRType type = i.mirType();
MOZ_ASSERT_IF(type == MIRType::Int64, JitOptions.wasmTestMode);
switch (i->kind()) {
case ABIArg::GPR:
if (type == MIRType::Int32) {
@ -520,7 +516,6 @@ wasm::GenerateInterpExit(MacroAssembler& masm, const FuncImport& fi, uint32_t fu
masm.load32(argv, ReturnReg);
break;
case ExprType::I64:
MOZ_ASSERT(JitOptions.wasmTestMode);
masm.call(SymbolicAddress::CallImport_I64);
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, JumpTarget::Throw);
masm.load64(argv, ReturnReg64);
@ -716,7 +711,6 @@ wasm::GenerateJitExit(MacroAssembler& masm, const FuncImport& fi)
/* -0 check */ false);
break;
case ExprType::I64:
MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm");
// We don't expect int64 to be returned from Ion yet, because of a
// guard in callImport.
masm.breakpoint();

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

@ -28,8 +28,6 @@ testConst('i32', '-0x80000000', -2147483648);
testConst('i32', '0xffffffff', -1);
{
assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
setJitCompilerOption('wasm.test-mode', 1);
testConst('i64', '0', 0);
@ -74,8 +72,6 @@ testConst('i32', '0xffffffff', -1);
testConstError('i64', 'not an i64');
setJitCompilerOption('wasm.test-mode', 0);
assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
}
testConst('f32', '0.0', 0.0);

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

@ -67,8 +67,15 @@ wasmEvalText('(module (func (result i32) (param i32) (i32.const 42)))');
wasmEvalText('(module (func (param f32)))');
wasmEvalText('(module (func (param f64)))');
assertErrorMessage(() => wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))'), TypeError, /i64 argument/);
assertErrorMessage(() => wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))'), TypeError, /i64 return type/);
var f = wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))');
assertErrorMessage(() => f(), TypeError, /i64/);
var f = wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))');
assertErrorMessage(() => f(), TypeError, /i64/);
var f = wasmEvalText('(module (import $imp "a" "b" (param i64) (result i32)) (func $f (call_import $imp (i64.const 0))) (export "" $f))', {a:{b:()=>{}}});
assertErrorMessage(() => f(), TypeError, /i64/);
var f = wasmEvalText('(module (import $imp "a" "b" (result i64)) (func $f (call_import $imp)) (export "" $f))', {a:{b:()=>{}}});
assertErrorMessage(() => f(), TypeError, /i64/);
setJitCompilerOption('wasm.test-mode', 1);
assertEqI64(wasmEvalText('(module (func (result i64) (i64.const 123)) (export "" 0))')(), {low: 123, high: 0});
@ -327,9 +334,6 @@ if (typeof evaluate === 'function')
evaluate(`Wasm.instantiateModule(wasmTextToBinary('(module)')) `, { fileName: null });
{
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /i64 argument/);
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /i64 return type/);
setJitCompilerOption('wasm.test-mode', 1);
let imp = {

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

@ -287,6 +287,14 @@ assertEq(e1.foo, tbl.get(1));
assertEq(tbl.get(0) === e1.foo, false);
assertEq(e1.foo === e2.foo, false);
// i64 is fully allowed for imported wasm functions
var code1 = textToBinary('(module (func $exp (param i64) (result i64) (i64.add (get_local 0) (i64.const 10))) (export "exp" $exp))');
var e1 = new Instance(new Module(code1)).exports;
var code2 = textToBinary('(module (import $i "a" "b" (param i64) (result i64)) (func $f (result i32) (i32.wrap/i64 (call_import $i (i64.const 42)))) (export "f" $f))');
var e2 = new Instance(new Module(code2), {a:{b:e1.exp}}).exports;
assertEq(e2.f(), 52);
// Non-existent export errors
assertErrorMessage(() => new Module(textToBinary('(module (export "a" 0))')), TypeError, /exported function index out of bounds/);

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

@ -356,6 +356,7 @@ MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG, 0, JSEXN_TYPEERR, "second argument, i
MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD, 1, JSEXN_TYPEERR, "import object field is not {0}")
MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 0, JSEXN_TYPEERR, "imported function signature mismatch")
MSG_DEF(JSMSG_WASM_BAD_SET_VALUE, 0, JSEXN_TYPEERR, "second argument must be null or an exported WebAssembly Function object")
MSG_DEF(JSMSG_WASM_BAD_I64, 0, JSEXN_TYPEERR, "cannot pass i64 to or from JS")
MSG_DEF(JSMSG_WASM_UNREACHABLE, 0, JSEXN_ERR, "unreachable executed")
MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW, 0, JSEXN_ERR, "integer overflow")
MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_ERR, "invalid conversion to integer")