Bug 1289080: Don't allow call_indirect without a table and memory accesses without memory; r=luke

MozReview-Commit-ID: DkuyBiGsaxs

--HG--
extra : rebase_source : d051b7e8c9e7c32ba60a6e37bb4c6dc98dc36ef9
This commit is contained in:
Benjamin Bouvier 2016-07-25 14:54:50 +02:00
Родитель 185149d31c
Коммит feab551c2f
4 изменённых файлов: 86 добавлений и 10 удалений

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

@ -79,6 +79,12 @@ class FunctionDecoder
return iter().notYetImplemented("i64 NYI on this platform");
return true;
}
bool checkHasMemory() {
if (!mg().usesMemory())
return iter().fail("can't touch memory without memory");
return true;
}
};
} // end anonymous namespace
@ -146,6 +152,9 @@ DecodeCall(FunctionDecoder& f)
static bool
DecodeCallIndirect(FunctionDecoder& f)
{
if (!f.mg().numTables())
return f.iter().fail("can't call_indirect without a table");
uint32_t sigIndex;
uint32_t arity;
if (!f.iter().readCallIndirect(&sigIndex, &arity))
@ -398,53 +407,71 @@ DecodeExpr(FunctionDecoder& f)
return f.iter().readConversion(ValType::F32, ValType::F64, nullptr);
case Expr::I32Load8S:
case Expr::I32Load8U:
return f.iter().readLoad(ValType::I32, 1, nullptr);
return f.checkHasMemory() &&
f.iter().readLoad(ValType::I32, 1, nullptr);
case Expr::I32Load16S:
case Expr::I32Load16U:
return f.iter().readLoad(ValType::I32, 2, nullptr);
return f.checkHasMemory() &&
f.iter().readLoad(ValType::I32, 2, nullptr);
case Expr::I32Load:
return f.iter().readLoad(ValType::I32, 4, nullptr);
return f.checkHasMemory() &&
f.iter().readLoad(ValType::I32, 4, nullptr);
case Expr::I64Load8S:
case Expr::I64Load8U:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readLoad(ValType::I64, 1, nullptr);
case Expr::I64Load16S:
case Expr::I64Load16U:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readLoad(ValType::I64, 2, nullptr);
case Expr::I64Load32S:
case Expr::I64Load32U:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readLoad(ValType::I64, 4, nullptr);
case Expr::I64Load:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readLoad(ValType::I64, 8, nullptr);
case Expr::F32Load:
return f.iter().readLoad(ValType::F32, 4, nullptr);
return f.checkHasMemory() &&
f.iter().readLoad(ValType::F32, 4, nullptr);
case Expr::F64Load:
return f.iter().readLoad(ValType::F64, 8, nullptr);
return f.checkHasMemory() &&
f.iter().readLoad(ValType::F64, 8, nullptr);
case Expr::I32Store8:
return f.iter().readStore(ValType::I32, 1, nullptr, nullptr);
return f.checkHasMemory() &&
f.iter().readStore(ValType::I32, 1, nullptr, nullptr);
case Expr::I32Store16:
return f.iter().readStore(ValType::I32, 2, nullptr, nullptr);
return f.checkHasMemory() &&
f.iter().readStore(ValType::I32, 2, nullptr, nullptr);
case Expr::I32Store:
return f.iter().readStore(ValType::I32, 4, nullptr, nullptr);
return f.checkHasMemory() &&
f.iter().readStore(ValType::I32, 4, nullptr, nullptr);
case Expr::I64Store8:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readStore(ValType::I64, 1, nullptr, nullptr);
case Expr::I64Store16:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readStore(ValType::I64, 2, nullptr, nullptr);
case Expr::I64Store32:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readStore(ValType::I64, 4, nullptr, nullptr);
case Expr::I64Store:
return f.checkI64Support() &&
f.checkHasMemory() &&
f.iter().readStore(ValType::I64, 8, nullptr, nullptr);
case Expr::F32Store:
return f.iter().readStore(ValType::F32, 4, nullptr, nullptr);
return f.checkHasMemory() &&
f.iter().readStore(ValType::F32, 4, nullptr, nullptr);
case Expr::F64Store:
return f.iter().readStore(ValType::F64, 8, nullptr, nullptr);
return f.checkHasMemory() &&
f.iter().readStore(ValType::F64, 8, nullptr, nullptr);
case Expr::Br:
return f.iter().readBr(nullptr, nullptr, nullptr);
case Expr::BrIf:

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

@ -153,6 +153,7 @@ class MOZ_STACK_CLASS ModuleGenerator
uint32_t minMemoryLength() const { return shared_->minMemoryLength; }
// Tables:
uint32_t numTables() const { return numTables_; }
const TableDescVector& tables() const { return shared_->tables; }
// Signatures:

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

@ -104,6 +104,52 @@ function testStoreOOB(type, ext, base, offset, align, value) {
assertErrorMessage(() => storeModule(type, ext, offset, align).store(base, value), Error, /invalid or out-of-range index/);
}
function badLoadModule(type, ext) {
return wasmEvalText( `(module (func (param i32) (${type}.load${ext} (get_local 0))) (export "" 0))`);
}
function badStoreModule(type, ext) {
return wasmEvalText( `(module (func (param i32) (${type}.store${ext} (get_local 0) (${type}.const 0))) (export "" 0))`);
}
// Can't touch memory.
for (let [type, ext] of [
['i32', ''],
['i32', '8_s'],
['i32', '8_u'],
['i32', '16_s'],
['i32', '16_u'],
['i64', ''],
['i64', '8_s'],
['i64', '8_u'],
['i64', '16_s'],
['i64', '16_u'],
['i64', '32_s'],
['i64', '32_u'],
['f32', ''],
['f64', ''],
])
{
if (type !== 'i64' || hasI64())
assertErrorMessage(() => badLoadModule(type, ext), TypeError, /can't touch memory/);
}
for (let [type, ext] of [
['i32', ''],
['i32', '8'],
['i32', '16'],
['i64', ''],
['i64', '8'],
['i64', '16'],
['i64', '32'],
['f32', ''],
['f64', ''],
])
{
if (type !== 'i64' || hasI64())
assertErrorMessage(() => badStoreModule(type, ext), TypeError, /can't touch memory/);
}
// Test bounds checks and edge cases.
const align = 0;

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

@ -403,6 +403,8 @@ if (hasI64()) {
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /NYI/);
}
assertErrorMessage(() => wasmEvalText(`(module (type $t (func)) (func (call_indirect $t (i32.const 0))))`), TypeError, /can't call_indirect without a table/);
var {v2i, i2i, i2v} = wasmEvalText(`(module
(type (func (result i32)))
(type (func (param i32) (result i32)))