Commit d91bed67 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Only immutable imported globals are valid initializer expressions

R=titzer@chromium.org
TEST=unittests/WasmModuleVerifyTest.DataSegmentWithImmutableGlobal, unittests/WasmModuleVerifyTest.DataSegmentWithMutableImportedGlobal, unittests/WasmModuleVerifyTest.DataSegmentWithImmutableImportedGlobal

Review-Url: https://codereview.chromium.org/2493433002
Cr-Commit-Position: refs/heads/master@{#40865}
parent dd4ce25c
...@@ -910,6 +910,21 @@ class ModuleDecoder : public Decoder { ...@@ -910,6 +910,21 @@ class ModuleDecoder : public Decoder {
switch (opcode) { switch (opcode) {
case kExprGetGlobal: { case kExprGetGlobal: {
GlobalIndexOperand operand(this, pc() - 1); GlobalIndexOperand operand(this, pc() - 1);
if (module->globals.size() <= operand.index) {
error("global index is out of bounds");
expr.kind = WasmInitExpr::kNone;
expr.val.i32_const = 0;
break;
}
WasmGlobal* global = &module->globals[operand.index];
if (global->mutability || !global->imported) {
error(
"only immutable imported globals can be used in initializer "
"expressions");
expr.kind = WasmInitExpr::kNone;
expr.val.i32_const = 0;
break;
}
expr.kind = WasmInitExpr::kGlobalIndex; expr.kind = WasmInitExpr::kGlobalIndex;
expr.val.global_index = operand.index; expr.val.global_index = operand.index;
len = operand.length; len = operand.length;
......
...@@ -755,35 +755,6 @@ static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) { ...@@ -755,35 +755,6 @@ static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) {
ExportAsMain(f1); ExportAsMain(f1);
TestModule(&zone, builder, expected); TestModule(&zone, builder, expected);
} }
for (int padding = 0; padding < 5; padding++) {
// Test with a global index
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
for (int i = 0; i < padding; i++) { // pad global before
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 40000));
}
uint32_t global1 =
builder->AddGlobal(type, false, false, WasmInitExpr(expected));
for (int i = 0; i < padding; i++) { // pad global middle
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 50000));
}
uint32_t global2 =
builder->AddGlobal(type, false, false,
WasmInitExpr(WasmInitExpr::kGlobalIndex, global1));
for (int i = 0; i < padding; i++) { // pad global after
builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 60000));
}
WasmFunctionBuilder* f1 = builder->AddFunction(&sig);
byte code[] = {WASM_GET_GLOBAL(global2)};
f1->EmitCode(code, sizeof(code));
ExportAsMain(f1);
TestModule(&zone, builder, expected);
}
} }
Cleanup(); Cleanup();
} }
......
...@@ -32,30 +32,6 @@ SimpleDataSegmentTest(4); ...@@ -32,30 +32,6 @@ SimpleDataSegmentTest(4);
SimpleDataSegmentTest(12); SimpleDataSegmentTest(12);
SimpleDataSegmentTest(1064); SimpleDataSegmentTest(1064);
function GlobalInitTest(offset) {
print("GlobalInitTest(" + offset + ")...");
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
var g = builder.addGlobal(kAstI32, false);
g.init = offset;
builder.addFunction("load", kSig_i_i)
.addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0])
.exportAs("load");
builder.addDataSegment(g.index, [7, 7, 7, 7], true);
var buffer = builder.toBuffer(debug);
var instance = new WebAssembly.Instance(new WebAssembly.Module(buffer));
for (var i = offset - 20; i < offset + 20; i += 4) {
if (i < 0) continue;
var expected = i == offset ? 117901063 : 0;
assertEquals(expected, instance.exports.load(i));
}
}
GlobalInitTest(0);
GlobalInitTest(12);
GlobalInitTest(3040);
function GlobalImportedInitTest(pad) { function GlobalImportedInitTest(pad) {
print("GlobaleImportedInitTest(" + pad + ")..."); print("GlobaleImportedInitTest(" + pad + ")...");
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
......
...@@ -417,6 +417,100 @@ TEST_F(WasmModuleVerifyTest, MultipleSignatures) { ...@@ -417,6 +417,100 @@ TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
EXPECT_OFF_END_FAILURE(data, 1, sizeof(data)); EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
} }
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) {
// Import 2 globals so that we can initialize data with a global index != 0.
const byte data[] = {
SECTION(Import, 15), // section header
2, // number of imports
NAME_LENGTH(1), // --
'm', // module name
NAME_LENGTH(1), // --
'f', // global name
kExternalGlobal, // import kind
kLocalI32, // type
0, // mutability
NAME_LENGTH(1), // --
'n', // module name
NAME_LENGTH(1), // --
'g', // global name
kExternalGlobal, // import kind
kLocalI32, // type
0, // mutability
SECTION(Memory, 4),
ENTRY_COUNT(1),
kResizableMaximumFlag,
28,
28,
SECTION(Data, 9),
ENTRY_COUNT(1),
LINEAR_MEMORY_INDEX_0,
WASM_INIT_EXPR_GLOBAL(1), // dest addr
U32V_1(3), // source size
'a',
'b',
'c' // data bytes
};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
WasmInitExpr expr = result.val->data_segments.back().dest_addr;
EXPECT_EQ(WasmInitExpr::kGlobalIndex, expr.kind);
EXPECT_EQ(1, expr.val.global_index);
if (result.val) delete result.val;
}
TEST_F(WasmModuleVerifyTest, DataSegmentWithMutableImportedGlobal) {
// Only an immutable imported global can be used as an init_expr.
const byte data[] = {
SECTION(Import, 8), // section header
1, // number of imports
NAME_LENGTH(1), // --
'm', // module name
NAME_LENGTH(1), // --
'f', // global name
kExternalGlobal, // import kind
kLocalI32, // type
1, // mutability
SECTION(Memory, 4),
ENTRY_COUNT(1),
kResizableMaximumFlag,
28,
28,
SECTION(Data, 9),
ENTRY_COUNT(1),
LINEAR_MEMORY_INDEX_0,
WASM_INIT_EXPR_GLOBAL(0), // dest addr
U32V_1(3), // source size
'a',
'b',
'c' // data bytes
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableGlobal) {
// Only an immutable imported global can be used as an init_expr.
const byte data[] = {
SECTION(Memory, 4),
ENTRY_COUNT(1),
kResizableMaximumFlag,
28,
28,
SECTION(Global, 8), // --
1,
kLocalI32, // local type
0, // immutable
WASM_INIT_EXPR_I32V_3(0x9bbaa), // init
SECTION(Data, 9),
ENTRY_COUNT(1),
LINEAR_MEMORY_INDEX_0,
WASM_INIT_EXPR_GLOBAL(0), // dest addr
U32V_1(3), // source size
'a',
'b',
'c' // data bytes
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, OneDataSegment) { TEST_F(WasmModuleVerifyTest, OneDataSegment) {
const byte kDataSegmentSourceOffset = 24; const byte kDataSegmentSourceOffset = 24;
const byte data[] = { const byte data[] = {
...@@ -1378,13 +1472,6 @@ TEST_F(WasmModuleVerifyTest, InitExpr_illegal) { ...@@ -1378,13 +1472,6 @@ TEST_F(WasmModuleVerifyTest, InitExpr_illegal) {
EXPECT_INIT_EXPR_FAIL(WASM_IF_ELSE(WASM_ZERO, WASM_ZERO, WASM_ZERO)); EXPECT_INIT_EXPR_FAIL(WASM_IF_ELSE(WASM_ZERO, WASM_ZERO, WASM_ZERO));
} }
TEST_F(WasmModuleVerifyTest, InitExpr_global) {
static const byte data[] = {WASM_INIT_EXPR_GLOBAL(37)};
WasmInitExpr expr = DecodeWasmInitExprForTesting(data, data + sizeof(data));
EXPECT_EQ(WasmInitExpr::kGlobalIndex, expr.kind);
EXPECT_EQ(37, expr.val.global_index);
}
TEST_F(WasmModuleVerifyTest, Multiple_Named_Sections) { TEST_F(WasmModuleVerifyTest, Multiple_Named_Sections) {
static const byte data[] = { static const byte data[] = {
SECTION(Unknown, 4), 1, 'X', 17, 18, // -- SECTION(Unknown, 4), 1, 'X', 17, 18, // --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment