Commit 63c95e61 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[wasm] Remove wrong signature definitions for numerics

Some of the numeric opcodes have a variadic signature, e.g. table.grow
or table.fill, and soon also the bulk memory opcodes because their
consumed types depend on the memory type.

For those opcodes, remove the signature definition from the opcode macro
lists, because using it might result in bugs.

R=thibaudm@chromium.org

Bug: v8:10949, chromium:1281995
Change-Id: I350e75db7197d97a561f8219cedba5fe85b5c9c9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3424494Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78903}
parent 418aa66f
...@@ -1687,7 +1687,7 @@ class WasmDecoder : public Decoder { ...@@ -1687,7 +1687,7 @@ class WasmDecoder : public Decoder {
case kExprRefAsNonNull: case kExprRefAsNonNull:
return 1; return 1;
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: #define DECLARE_OPCODE_CASE(name, ...) case kExpr##name:
// clang-format off // clang-format off
/********** Simple and memory opcodes **********/ /********** Simple and memory opcodes **********/
FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
...@@ -1914,7 +1914,7 @@ class WasmDecoder : public Decoder { ...@@ -1914,7 +1914,7 @@ class WasmDecoder : public Decoder {
// Prefixed opcodes (already handled, included here for completeness of // Prefixed opcodes (already handled, included here for completeness of
// switch) // switch)
FOREACH_SIMD_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_NUMERIC_OPCODE(DECLARE_OPCODE_CASE) FOREACH_NUMERIC_OPCODE(DECLARE_OPCODE_CASE, DECLARE_OPCODE_CASE)
FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE) FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_ATOMIC_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_GC_OPCODE(DECLARE_OPCODE_CASE) FOREACH_GC_OPCODE(DECLARE_OPCODE_CASE)
...@@ -2022,13 +2022,19 @@ class WasmDecoder : public Decoder { ...@@ -2022,13 +2022,19 @@ class WasmDecoder : public Decoder {
return {2, 1}; return {2, 1};
FOREACH_SIMD_CONST_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_CONST_OPCODE(DECLARE_OPCODE_CASE)
return {0, 1}; return {0, 1};
// Special case numeric opcodes without fixed signature.
case kExprMemoryInit:
case kExprMemoryCopy:
case kExprMemoryFill:
return {3, 0};
case kExprTableGrow:
return {2, 1};
case kExprTableFill:
return {3, 0};
default: { default: {
sig = WasmOpcodes::Signature(opcode); sig = WasmOpcodes::Signature(opcode);
if (sig) { DCHECK_NOT_NULL(sig);
return {sig->parameter_count(), sig->return_count()}; return {sig->parameter_count(), sig->return_count()};
} else {
UNREACHABLE();
}
} }
} }
} }
...@@ -4924,10 +4930,6 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4924,10 +4930,6 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
unsigned DecodeNumericOpcode(WasmOpcode opcode, uint32_t opcode_length) { unsigned DecodeNumericOpcode(WasmOpcode opcode, uint32_t opcode_length) {
const FunctionSig* sig = WasmOpcodes::Signature(opcode); const FunctionSig* sig = WasmOpcodes::Signature(opcode);
if (!VALIDATE(sig != nullptr)) {
this->DecodeError("invalid numeric opcode");
return 0;
}
switch (opcode) { switch (opcode) {
case kExprI32SConvertSatF32: case kExprI32SConvertSatF32:
case kExprI32UConvertSatF32: case kExprI32UConvertSatF32:
...@@ -4943,10 +4945,11 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4943,10 +4945,11 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprMemoryInit: { case kExprMemoryInit: {
MemoryInitImmediate<validate> imm(this, this->pc_ + opcode_length); MemoryInitImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0; if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value size = Peek(0, 2, sig->GetParam(2)); // TODO(clemensb): Add memory64 support.
Value src = Peek(1, 1, sig->GetParam(1)); Value size = Peek(0, 2, kWasmI32);
Value dst = Peek(2, 0, sig->GetParam(0)); Value offset = Peek(1, 1, kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryInit, imm, dst, src, size); Value dst = Peek(2, 0, kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryInit, imm, dst, offset, size);
Drop(3); Drop(3);
return opcode_length + imm.length; return opcode_length + imm.length;
} }
...@@ -4962,9 +4965,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4962,9 +4965,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprMemoryCopy: { case kExprMemoryCopy: {
MemoryCopyImmediate<validate> imm(this, this->pc_ + opcode_length); MemoryCopyImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0; if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value size = Peek(0, 2, sig->GetParam(2)); // TODO(clemensb): Add memory64 support.
Value src = Peek(1, 1, sig->GetParam(1)); Value size = Peek(0, 2, kWasmI32);
Value dst = Peek(2, 0, sig->GetParam(0)); Value src = Peek(1, 1, kWasmI32);
Value dst = Peek(2, 0, kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryCopy, imm, dst, src, size); CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryCopy, imm, dst, src, size);
Drop(3); Drop(3);
return opcode_length + imm.length; return opcode_length + imm.length;
...@@ -4972,9 +4976,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -4972,9 +4976,10 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
case kExprMemoryFill: { case kExprMemoryFill: {
MemoryIndexImmediate<validate> imm(this, this->pc_ + opcode_length); MemoryIndexImmediate<validate> imm(this, this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0; if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
Value size = Peek(0, 2, sig->GetParam(2)); // TODO(clemensb): Add memory64 support.
Value value = Peek(1, 1, sig->GetParam(1)); Value size = Peek(0, 2, kWasmI32);
Value dst = Peek(2, 0, sig->GetParam(0)); Value value = Peek(1, 1, kWasmI32);
Value dst = Peek(2, 0, kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryFill, imm, dst, value, size); CALL_INTERFACE_IF_OK_AND_REACHABLE(MemoryFill, imm, dst, value, size);
Drop(3); Drop(3);
return opcode_length + imm.length; return opcode_length + imm.length;
...@@ -5010,7 +5015,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5010,7 +5015,7 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
IndexImmediate<validate> imm(this, this->pc_ + opcode_length, IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
"table index"); "table index");
if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0; if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0;
Value delta = Peek(0, 1, sig->GetParam(1)); Value delta = Peek(0, 1, kWasmI32);
Value value = Peek(1, 0, this->module_->tables[imm.index].type); Value value = Peek(1, 0, this->module_->tables[imm.index].type);
Value result = CreateValue(kWasmI32); Value result = CreateValue(kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(TableGrow, imm, value, delta, CALL_INTERFACE_IF_OK_AND_REACHABLE(TableGrow, imm, value, delta,
...@@ -5032,9 +5037,9 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> { ...@@ -5032,9 +5037,9 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
IndexImmediate<validate> imm(this, this->pc_ + opcode_length, IndexImmediate<validate> imm(this, this->pc_ + opcode_length,
"table index"); "table index");
if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0; if (!this->ValidateTable(this->pc_ + opcode_length, imm)) return 0;
Value count = Peek(0, 2, sig->GetParam(2)); Value count = Peek(0, 2, kWasmI32);
Value value = Peek(1, 1, this->module_->tables[imm.index].type); Value value = Peek(1, 1, this->module_->tables[imm.index].type);
Value start = Peek(2, 0, sig->GetParam(0)); Value start = Peek(2, 0, kWasmI32);
CALL_INTERFACE_IF_OK_AND_REACHABLE(TableFill, imm, start, value, count); CALL_INTERFACE_IF_OK_AND_REACHABLE(TableFill, imm, start, value, count);
Drop(3); Drop(3);
return opcode_length + imm.length; return opcode_length + imm.length;
......
...@@ -106,7 +106,7 @@ void PrintRawWasmCode(const byte* start, const byte* end) { ...@@ -106,7 +106,7 @@ void PrintRawWasmCode(const byte* start, const byte* end) {
namespace { namespace {
const char* RawOpcodeName(WasmOpcode opcode) { const char* RawOpcodeName(WasmOpcode opcode) {
switch (opcode) { switch (opcode) {
#define DECLARE_NAME_CASE(name, opcode, sig) \ #define DECLARE_NAME_CASE(name, ...) \
case kExpr##name: \ case kExpr##name: \
return "kExpr" #name; return "kExpr" #name;
FOREACH_OPCODE(DECLARE_NAME_CASE) FOREACH_OPCODE(DECLARE_NAME_CASE)
......
...@@ -633,9 +633,11 @@ constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) { ...@@ -633,9 +633,11 @@ constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) {
} }
constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(byte opcode) { constexpr WasmOpcodeSig GetNumericOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig: #define CASE_SIG(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_NUMERIC_OPCODE(CASE) kSigEnum_None; #define CASE_VARIADIC(name, opc)
#undef CASE return FOREACH_NUMERIC_OPCODE(CASE_SIG, CASE_VARIADIC) kSigEnum_None;
#undef CASE_SIG
#undef CASE_VARIADIC
} }
constexpr std::array<WasmOpcodeSig, 256> kShortSigTable = constexpr std::array<WasmOpcodeSig, 256> kShortSigTable =
......
...@@ -569,29 +569,29 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -569,29 +569,29 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
FOREACH_SIMD_MEM_1_OPERAND_OPCODE(V) \ FOREACH_SIMD_MEM_1_OPERAND_OPCODE(V) \
FOREACH_SIMD_CONST_OPCODE(V) FOREACH_SIMD_CONST_OPCODE(V)
#define FOREACH_NUMERIC_OPCODE(V) \ #define FOREACH_NUMERIC_OPCODE(V_SIG, V_VARIADIC) \
V(I32SConvertSatF32, 0xfc00, i_f) \ V_SIG(I32SConvertSatF32, 0xfc00, i_f) \
V(I32UConvertSatF32, 0xfc01, i_f) \ V_SIG(I32UConvertSatF32, 0xfc01, i_f) \
V(I32SConvertSatF64, 0xfc02, i_d) \ V_SIG(I32SConvertSatF64, 0xfc02, i_d) \
V(I32UConvertSatF64, 0xfc03, i_d) \ V_SIG(I32UConvertSatF64, 0xfc03, i_d) \
V(I64SConvertSatF32, 0xfc04, l_f) \ V_SIG(I64SConvertSatF32, 0xfc04, l_f) \
V(I64UConvertSatF32, 0xfc05, l_f) \ V_SIG(I64UConvertSatF32, 0xfc05, l_f) \
V(I64SConvertSatF64, 0xfc06, l_d) \ V_SIG(I64SConvertSatF64, 0xfc06, l_d) \
V(I64UConvertSatF64, 0xfc07, l_d) \ V_SIG(I64UConvertSatF64, 0xfc07, l_d) \
V(MemoryInit, 0xfc08, v_iii) \ V_VARIADIC(MemoryInit, 0xfc08) \
V(DataDrop, 0xfc09, v_v) \ V_SIG(DataDrop, 0xfc09, v_v) \
V(MemoryCopy, 0xfc0a, v_iii) \ V_VARIADIC(MemoryCopy, 0xfc0a) \
V(MemoryFill, 0xfc0b, v_iii) \ V_VARIADIC(MemoryFill, 0xfc0b) \
V(TableInit, 0xfc0c, v_iii) \ V_SIG(TableInit, 0xfc0c, v_iii) \
V(ElemDrop, 0xfc0d, v_v) \ V_SIG(ElemDrop, 0xfc0d, v_v) \
V(TableCopy, 0xfc0e, v_iii) \ V_SIG(TableCopy, 0xfc0e, v_iii) \
/* TableGrow is polymorphic in the first parameter. */ \ /* TableGrow is polymorphic in the first parameter. */ \
/* It's whatever the table type is. */ \ /* It's whatever the table type is. */ \
V(TableGrow, 0xfc0f, i_ci) \ V_VARIADIC(TableGrow, 0xfc0f) \
V(TableSize, 0xfc10, i_v) \ V_SIG(TableSize, 0xfc10, i_v) \
/* TableFill is polymorphic in the second parameter. */ \ /* TableFill is polymorphic in the second parameter. */ \
/* It's whatever the table type is. */ \ /* It's whatever the table type is. */ \
V(TableFill, 0xfc11, v_iii) V_VARIADIC(TableFill, 0xfc11)
#define FOREACH_ATOMIC_OPCODE(V) \ #define FOREACH_ATOMIC_OPCODE(V) \
V(AtomicNotify, 0xfe00, i_ii) \ V(AtomicNotify, 0xfe00, i_ii) \
...@@ -730,7 +730,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -730,7 +730,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
FOREACH_SIMD_OPCODE(V) \ FOREACH_SIMD_OPCODE(V) \
FOREACH_ATOMIC_OPCODE(V) \ FOREACH_ATOMIC_OPCODE(V) \
FOREACH_ATOMIC_0_OPERAND_OPCODE(V) \ FOREACH_ATOMIC_0_OPERAND_OPCODE(V) \
FOREACH_NUMERIC_OPCODE(V) \ FOREACH_NUMERIC_OPCODE(V, V) \
FOREACH_GC_OPCODE(V) FOREACH_GC_OPCODE(V)
// All signatures. // All signatures.
...@@ -799,7 +799,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -799,7 +799,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
enum WasmOpcode { enum WasmOpcode {
// Declare expression opcodes. // Declare expression opcodes.
#define DECLARE_NAMED_ENUM(name, opcode, sig) kExpr##name = opcode, #define DECLARE_NAMED_ENUM(name, opcode, ...) kExpr##name = opcode,
FOREACH_OPCODE(DECLARE_NAMED_ENUM) FOREACH_OPCODE(DECLARE_NAMED_ENUM)
#undef DECLARE_NAMED_ENUM #undef DECLARE_NAMED_ENUM
#define DECLARE_PREFIX(name, opcode) k##name##Prefix = opcode, #define DECLARE_PREFIX(name, opcode) k##name##Prefix = opcode,
......
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