[wasm] Update signature map on indirect calls
The code was already there, but there was a bug in it: Because of the missing reference, we were only updating a *copy* of the signature map, hence the update had no effect. This intentially is a minimal CL, in order to allow for easy backmerging. More mitigations and tests are coming in a separate CL. R=titzer@chromium.org Change-Id: Ifb462093f4b8f4d5380b6774636537c67c2b676c Reviewed-on: https://chromium-review.googlesource.com/570278 Reviewed-by: Ben Titzer <titzer@chromium.org> Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#46664}
This commit is contained in:
parent
527f541fe8
commit
883db26e6f
@ -2321,7 +2321,7 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
|
||||
Int32Constant(kPointerSizeLog2)),
|
||||
Int32Constant(fixed_offset)),
|
||||
*effect_, *control_);
|
||||
auto map = const_cast<wasm::SignatureMap&>(
|
||||
auto& map = const_cast<wasm::SignatureMap&>(
|
||||
module_->module->function_tables[0].map);
|
||||
Node* sig_match = graph()->NewNode(
|
||||
machine->WordEqual(), load_sig,
|
||||
|
@ -388,7 +388,7 @@ void wasm::UpdateDispatchTables(Isolate* isolate,
|
||||
// a dangling pointer in the signature map.
|
||||
Handle<WasmInstanceObject> instance(
|
||||
WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
|
||||
auto func_table = instance->module()->function_tables[table_index];
|
||||
auto& func_table = instance->module()->function_tables[table_index];
|
||||
uint32_t sig_index = func_table.map.FindOrInsert(function->sig);
|
||||
signature_table->set(index, Smi::FromInt(static_cast<int>(sig_index)));
|
||||
function_table->set(index, *code);
|
||||
|
@ -23,7 +23,7 @@ let instance0 = new WebAssembly.Instance(module0);
|
||||
|
||||
let builder1 = new WasmModuleBuilder();
|
||||
builder1.setName('module_1');
|
||||
builder1.addFunction('main', kSig_i_i).addBody([0]);
|
||||
builder1.addFunction('main', kSig_i_v).addBody([kExprUnreachable]);
|
||||
builder1.addImportedTable('z', 'table');
|
||||
builder1.addFunctionTableInit(0, false, [0], true);
|
||||
let module1 = new WebAssembly.Module(builder1.toBuffer());
|
||||
|
@ -568,3 +568,37 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
(function InitImportedTableSignatureMismatch() {
|
||||
// instance0 exports a function table and a main function which indirectly
|
||||
// calls a function from the table.
|
||||
let builder0 = new WasmModuleBuilder();
|
||||
builder0.setName('module_0');
|
||||
let sig_index = builder0.addType(kSig_i_v);
|
||||
builder0.addFunction('main', kSig_i_i)
|
||||
.addBody([
|
||||
kExprGetLocal, 0, // -
|
||||
kExprCallIndirect, sig_index, kTableZero
|
||||
])
|
||||
.exportAs('main');
|
||||
builder0.setFunctionTableLength(3);
|
||||
builder0.addExportOfKind('table', kExternalTable);
|
||||
let module0 = new WebAssembly.Module(builder0.toBuffer());
|
||||
let instance0 = new WebAssembly.Instance(module0);
|
||||
|
||||
// instance1 imports the table and adds a function to it.
|
||||
let builder1 = new WasmModuleBuilder();
|
||||
builder1.setName('module_1');
|
||||
builder1.addFunction('f', kSig_i_i).addBody([kExprGetLocal, 0]);
|
||||
builder1.addImportedTable('z', 'table');
|
||||
builder1.addFunctionTableInit(0, false, [0], true);
|
||||
let module1 = new WebAssembly.Module(builder1.toBuffer());
|
||||
let instance1 =
|
||||
new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}});
|
||||
|
||||
// Calling the main method on instance0 should fail, because the signature of
|
||||
// the added function does not match.
|
||||
assertThrows(
|
||||
() => instance0.exports.main(0), WebAssembly.RuntimeError,
|
||||
/signature mismatch/);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user