Commit d2c75d32 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm-gc] Disallow new_default with immutable fields

This is required by the MVP spec. In the future, it might be possible
to pass values for any immutable fields.

Bug: v8:7748
Change-Id: Ie7705b48e9d6ebb87d5e1b0a2a10556302395db6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3793383Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82072}
parent cd617a58
......@@ -4278,6 +4278,11 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
if (validate) {
for (uint32_t i = 0; i < imm.struct_type->field_count(); i++) {
if (!VALIDATE(imm.struct_type->mutability(i))) {
this->DecodeError("%s: struct_type %d has immutable field %d",
WasmOpcodes::OpcodeName(opcode), imm.index, i);
return 0;
}
ValueType ftype = imm.struct_type->field(i);
if (!VALIDATE(ftype.is_defaultable())) {
this->DecodeError(
......@@ -4384,6 +4389,11 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprArrayNewDefault: {
ArrayIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
if (!VALIDATE(imm.array_type->mutability())) {
this->DecodeError("%s: array type %d is immutable",
WasmOpcodes::OpcodeName(opcode), imm.index);
return 0;
}
if (!VALIDATE(imm.array_type->element_type().is_defaultable())) {
this->DecodeError(
"%s: array type %d has non-defaultable element type %s",
......
......@@ -6,7 +6,6 @@
#include "src/base/vector.h"
#include "src/codegen/signature.h"
#include "src/utils/utils.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/struct-types.h"
#include "src/wasm/wasm-arguments.h"
......@@ -16,7 +15,6 @@
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
#include "test/cctest/wasm/wasm-run-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
......@@ -495,21 +493,23 @@ WASM_COMPILED_EXEC_TEST(RefCastStatic) {
tester.DefineSignature(&sub_sig2, function_type_index);
const byte function_index = tester.DefineFunction(
function_subtype1_index, {},
{WASM_STRUCT_NEW_DEFAULT(subtype1_index), WASM_END});
{WASM_STRUCT_NEW(subtype1_index, WASM_I32V(10), WASM_F32(20)), WASM_END});
// Just so this function counts as "declared".
tester.AddGlobal(ValueType::RefNull(function_type_index), false,
WasmInitExpr::RefFuncConst(function_index));
const byte kTestSuccessful = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::RefNull(supertype_index)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
{WASM_LOCAL_SET(
0, WASM_STRUCT_NEW(subtype1_index, WASM_I32V(10), WASM_F32(20))),
WASM_STRUCT_GET(subtype1_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype1_index)),
WASM_END});
const byte kTestFailed = tester.DefineFunction(
tester.sigs.i_v(), {ValueType::RefNull(supertype_index)},
{WASM_LOCAL_SET(0, WASM_STRUCT_NEW_DEFAULT(subtype1_index)),
{WASM_LOCAL_SET(
0, WASM_STRUCT_NEW(subtype1_index, WASM_I32V(10), WASM_F32(20))),
WASM_STRUCT_GET(subtype2_index, 0,
WASM_REF_CAST_STATIC(WASM_LOCAL_GET(0), subtype2_index)),
WASM_END});
......@@ -533,7 +533,7 @@ WASM_COMPILED_EXEC_TEST(RefCastStatic) {
WASM_DROP, WASM_I32V(1), WASM_END});
tester.CompileModule();
tester.CheckResult(kTestSuccessful, 0);
tester.CheckResult(kTestSuccessful, 10);
tester.CheckHasThrown(kTestFailed);
tester.CheckResult(kFuncTestSuccessfulSuper, 0);
tester.CheckResult(kFuncTestSuccessfulSub, 0);
......@@ -546,7 +546,7 @@ WASM_COMPILED_EXEC_TEST(RefCastStaticNoChecks) {
const byte supertype_index = tester.DefineStruct({F(kWasmI32, true)});
const byte subtype1_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmF32, false)}, supertype_index);
{F(kWasmI32, true), F(kWasmF32, true)}, supertype_index);
const byte subtype2_index = tester.DefineStruct(
{F(kWasmI32, true), F(kWasmI64, false)}, supertype_index);
......@@ -1179,7 +1179,7 @@ WASM_COMPILED_EXEC_TEST(RefTrivialCastsStatic) {
WasmGCTester tester(execution_tier);
byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
byte subtype_index = tester.DefineStruct(
{F(wasm::kWasmI32, true), F(wasm::kWasmS128, false)}, type_index);
{F(wasm::kWasmI32, true), F(wasm::kWasmS128, true)}, type_index);
ValueType sig_types[] = {kWasmS128, kWasmI32, kWasmF64};
FunctionSig sig(1, 2, sig_types);
byte sig_index = tester.DefineSignature(&sig);
......
......@@ -114,7 +114,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
var builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmI32, true),
makeField(kWasmI8, false)]);
makeField(kWasmI8, true)]);
let array_type = test_object_type ? wasmRefNullType(struct_index) : kWasmI32;
var array_index = builder.addArray(array_type, true);
......@@ -155,7 +155,7 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
var builder = new WasmModuleBuilder();
let struct_index = builder.addStruct([makeField(kWasmI32, true),
makeField(kWasmI8, false)]);
makeField(kWasmI8, true)]);
let array_type = test_object_type ? wasmRefNullType(struct_index) : kWasmI32;
var array_index = builder.addArray(array_type, true);
......
......@@ -110,10 +110,10 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
print(arguments.callee.name);
var builder = new WasmModuleBuilder();
var struct_index = builder.addStruct([{type: kWasmI32, mutability: false}]);
var struct_index = builder.addStruct([{type: kWasmI32, mutability: true}]);
var composite_struct_index = builder.addStruct(
[{type: kWasmI32, mutability: false},
{type: wasmRefNullType(struct_index), mutability: false},
[{type: kWasmI32, mutability: true},
{type: wasmRefNullType(struct_index), mutability: true},
{type: kWasmI8, mutability: true}]);
let field1_value = 432;
......
......@@ -4,9 +4,6 @@
#include "src/wasm/function-body-decoder.h"
#include "src/init/v8.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/utils/ostreams.h"
#include "src/wasm/canonical-types.h"
#include "src/wasm/function-body-decoder-impl.h"
......@@ -1949,9 +1946,9 @@ TEST_F(FunctionBodyDecoderTest, TablesWithFunctionSubtyping) {
EXPERIMENTAL_FLAG_SCOPE(gc);
byte empty_struct = builder.AddStruct({});
byte super_struct = builder.AddStruct({F(kWasmI32, false)}, empty_struct);
byte super_struct = builder.AddStruct({F(kWasmI32, true)}, empty_struct);
byte sub_struct =
builder.AddStruct({F(kWasmI32, false), F(kWasmF64, false)}, super_struct);
builder.AddStruct({F(kWasmI32, true), F(kWasmF64, true)}, super_struct);
byte table_supertype = builder.AddSignature(
FunctionSig::Build(zone(), {ValueType::RefNull(empty_struct)},
......@@ -2687,7 +2684,8 @@ TEST_F(FunctionBodyDecoderTest, BrTableSubtyping) {
sigs.v_v(),
{WASM_BLOCK_R(wasm::ValueType::Ref(supertype1),
WASM_BLOCK_R(wasm::ValueType::Ref(supertype2),
WASM_STRUCT_NEW_DEFAULT(subtype),
WASM_STRUCT_NEW(subtype, WASM_I32V(10),
WASM_I32V(20), WASM_I32V(30)),
WASM_BR_TABLE(WASM_I32V(5), 1, BR_TARGET(0),
BR_TARGET(1))),
WASM_UNREACHABLE),
......@@ -3596,31 +3594,43 @@ TEST_F(FunctionBodyDecoderTest, UnpackPackedTypes) {
ValueType ref(byte type_index) { return ValueType::Ref(type_index); }
ValueType refNull(byte type_index) { return ValueType::RefNull(type_index); }
TEST_F(FunctionBodyDecoderTest, StructNewDefault) {
TEST_F(FunctionBodyDecoderTest, StructOrArrayNewDefault) {
WASM_FEATURE_SCOPE(typed_funcref);
WASM_FEATURE_SCOPE(gc);
{
TestModuleBuilder builder;
byte type_index = builder.AddStruct({F(kWasmI32, true)});
byte bad_type_index = builder.AddStruct({F(ref(type_index), true)});
module = builder.module();
ExpectValidates(sigs.v_v(),
{WASM_STRUCT_NEW_DEFAULT(type_index), WASM_DROP});
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_NEW_DEFAULT(bad_type_index), WASM_DROP});
}
{
TestModuleBuilder builder;
byte type_index = builder.AddArray(kWasmI32, true);
byte bad_type_index = builder.AddArray(ref(type_index), true);
module = builder.module();
ExpectValidates(
sigs.v_v(),
{WASM_ARRAY_NEW_DEFAULT(type_index, WASM_I32V(3)), WASM_DROP});
ExpectFailure(
sigs.v_v(),
{WASM_ARRAY_NEW_DEFAULT(bad_type_index, WASM_I32V(3)), WASM_DROP});
}
TestModuleBuilder builder;
byte struct_index = builder.AddStruct({F(kWasmI32, true)});
byte struct_non_def_index = builder.AddStruct({F(ref(struct_index), true)});
byte struct_immutable_index = builder.AddStruct({F(kWasmI32, false)});
byte array_index = builder.AddArray(kWasmI32, true);
byte array_non_def_index = builder.AddArray(ref(array_index), true);
byte array_immutable_index = builder.AddArray(kWasmI32, false);
module = builder.module();
ExpectValidates(sigs.v_v(),
{WASM_STRUCT_NEW_DEFAULT(struct_index), WASM_DROP});
ExpectFailure(sigs.v_v(),
{WASM_STRUCT_NEW_DEFAULT(struct_non_def_index), WASM_DROP},
kAppendEnd,
"struct.new_default: struct type 1 has field 0 of "
"non-defaultable type (ref 0)");
ExpectFailure(
sigs.v_v(), {WASM_STRUCT_NEW_DEFAULT(struct_immutable_index), WASM_DROP},
kAppendEnd, "struct.new_default: struct_type 2 has immutable field 0");
ExpectValidates(
sigs.v_v(),
{WASM_ARRAY_NEW_DEFAULT(array_index, WASM_I32V(3)), WASM_DROP});
ExpectFailure(
sigs.v_v(),
{WASM_ARRAY_NEW_DEFAULT(array_non_def_index, WASM_I32V(3)), WASM_DROP},
kAppendEnd,
"array.new_default: array type 4 has non-defaultable element type (ref "
"3)");
ExpectFailure(
sigs.v_v(),
{WASM_ARRAY_NEW_DEFAULT(array_immutable_index, WASM_I32V(3)), WASM_DROP},
kAppendEnd, "array.new_default: array type 5 is immutable");
}
TEST_F(FunctionBodyDecoderTest, DefaultableLocal) {
......
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