[wasm-gc] read_heap_type should check if index is in module bounds

read_heap_type did not have knowledge of the module for which the heap
type was being decoded. As a result, callers of read_heap_type (or
read_value_type, which in turn calls read_heap_type) had to check after
the fact that a decoded indexed type (ref, ref null, or rtt) references
a type index within the module's bounds. This was not done consistently,
and was missing (at least) in DecodeLocals.
To avoid such problems in the future, this CL refactors read_heap_type
to accept a module and check the decoded index against it.

Changes:
- Add WasmModule argument to read_heap_type. Do so accordingly to all
  its transitive callers (read_value_type, immediate arguments,
  DecodeLocalDecls, DecodeValue/HeapType in unittests).
- Add index check to read_heap_type and emit an error for an
  out-of-bounds index.
- Remove all other now-redundant index validations. Replace them with
  decoder->ok() if needed (since read_heap_type will now emit an error).
- Fix error message in Validate for BlockTypeImmediate.
- In DecodeLocalDecls in unittests, pass an empty module to
  DecodeLocalDecls in the main code.
- Add a unit test with an invalid index in local type declarations.

Bug: v8:9495
Change-Id: I4ed1204847db80f78b6ae85fa40d300cd2456295
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2569757
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71572}
This commit is contained in:
Manos Koukoutos 2020-12-02 14:29:22 +00:00 committed by Commit Bot
parent 2bc979aa0a
commit 0396b732e7
7 changed files with 125 additions and 118 deletions

View File

@ -195,9 +195,12 @@ V8_INLINE WasmFeature feature_for_heap_type(HeapType heap_type) {
}
}
// If {module} is not null, the read index will be checked against the module's
// type capacity.
template <Decoder::ValidateFlag validate>
HeapType read_heap_type(Decoder* decoder, const byte* pc,
uint32_t* const length, const WasmFeatures& enabled) {
uint32_t* const length, const WasmModule* module,
const WasmFeatures& enabled) {
int64_t heap_index = decoder->read_i33v<validate>(pc, length, "heap type");
if (heap_index < 0) {
int64_t min_1_byte_leb128 = -64;
@ -248,6 +251,12 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
type_index, kV8MaxWasmTypes);
return HeapType(HeapType::kBottom);
}
// We use capacity over size so this works mid-DecodeTypeSection.
if (!VALIDATE(module == nullptr || type_index < module->types.capacity())) {
DecodeError<validate>(decoder, pc, "Type index %u is out of bounds",
type_index);
return HeapType(HeapType::kBottom);
}
return HeapType(type_index);
}
}
@ -259,7 +268,8 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
// kNoValidate.
template <Decoder::ValidateFlag validate>
ValueType read_value_type(Decoder* decoder, const byte* pc,
uint32_t* const length, const WasmFeatures& enabled) {
uint32_t* const length, const WasmModule* module,
const WasmFeatures& enabled) {
*length = 1;
byte val = decoder->read_u8<validate>(pc, "value type opcode");
if (decoder->failed()) {
@ -306,7 +316,7 @@ ValueType read_value_type(Decoder* decoder, const byte* pc,
return kWasmBottom;
}
HeapType heap_type =
read_heap_type<validate>(decoder, pc + 1, length, enabled);
read_heap_type<validate>(decoder, pc + 1, length, module, enabled);
*length += 1;
return heap_type.is_bottom() ? kWasmBottom
: ValueType::Ref(heap_type, nullability);
@ -329,8 +339,8 @@ ValueType read_value_type(Decoder* decoder, const byte* pc,
return kWasmBottom;
}
uint32_t heap_type_length;
HeapType heap_type = read_heap_type<validate>(decoder, pc + *length,
&heap_type_length, enabled);
HeapType heap_type = read_heap_type<validate>(
decoder, pc + *length, &heap_type_length, module, enabled);
*length += heap_type_length;
return heap_type.is_bottom() ? kWasmBottom
: ValueType::Rtt(heap_type, depth);
@ -445,7 +455,7 @@ struct SelectTypeImmediate {
ValueType type;
inline SelectTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
const byte* pc) {
const byte* pc, const WasmModule* module) {
uint8_t num_types =
decoder->read_u32v<validate>(pc, &length, "number of select types");
if (!VALIDATE(num_types == 1)) {
@ -455,8 +465,8 @@ struct SelectTypeImmediate {
return;
}
uint32_t type_length;
type = value_type_reader::read_value_type<validate>(decoder, pc + length,
&type_length, enabled);
type = value_type_reader::read_value_type<validate>(
decoder, pc + length, &type_length, module, enabled);
length += type_length;
}
};
@ -469,7 +479,7 @@ struct BlockTypeImmediate {
const FunctionSig* sig = nullptr;
inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
const byte* pc) {
const byte* pc, const WasmModule* module) {
int64_t block_type =
decoder->read_i33v<validate>(pc, &length, "block type");
if (block_type < 0) {
@ -483,7 +493,7 @@ struct BlockTypeImmediate {
}
if (static_cast<ValueTypeCode>(block_type & 0x7F) == kVoidCode) return;
type = value_type_reader::read_value_type<validate>(decoder, pc, &length,
enabled);
module, enabled);
} else {
if (!VALIDATE(enabled.has_mv())) {
DecodeError<validate>(decoder, pc,
@ -826,9 +836,9 @@ struct HeapTypeImmediate {
uint32_t length = 1;
HeapType type = HeapType(HeapType::kBottom);
inline HeapTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
const byte* pc) {
const byte* pc, const WasmModule* module) {
type = value_type_reader::read_heap_type<validate>(decoder, pc, &length,
enabled);
module, enabled);
}
};
@ -1172,7 +1182,7 @@ class WasmDecoder : public Decoder {
*total_length += length;
ValueType type = value_type_reader::read_value_type<validate>(
this, pc + *total_length, &length, enabled_);
this, pc + *total_length, &length, this->module_, enabled_);
if (!VALIDATE(type != kWasmBottom)) return -1;
*total_length += length;
total_count += count;
@ -1479,8 +1489,8 @@ class WasmDecoder : public Decoder {
inline bool Validate(const byte* pc, BlockTypeImmediate<validate>& imm) {
if (!Complete(imm)) {
DecodeError(pc, "block type index %u out of bounds (%zu types)",
imm.sig_index, module_->types.size());
DecodeError(pc, "block type index %u is not a signature definition",
imm.sig_index);
return false;
}
return true;
@ -1578,19 +1588,6 @@ class WasmDecoder : public Decoder {
return true;
}
inline bool Validate(const byte* pc, HeapTypeImmediate<validate>& imm) {
if (!VALIDATE(!imm.type.is_bottom())) {
DecodeError(pc, "invalid heap type");
return false;
}
if (!VALIDATE(imm.type.is_generic() ||
module_->has_type(imm.type.ref_index()))) {
DecodeError(pc, "Type index %u is out of bounds", imm.type.ref_index());
return false;
}
return true;
}
// Returns the length of the opcode under {pc}.
static uint32_t OpcodeLength(WasmDecoder* decoder, const byte* pc) {
WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
@ -1611,7 +1608,8 @@ class WasmDecoder : public Decoder {
case kExprIf:
case kExprLoop:
case kExprBlock: {
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1);
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
nullptr);
return 1 + imm.length;
}
case kExprBr:
@ -1637,7 +1635,8 @@ class WasmDecoder : public Decoder {
return 1 + imm.length;
}
case kExprLet: {
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1);
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
nullptr);
uint32_t locals_length;
int new_locals_count = decoder->DecodeLocals(
pc + 1 + imm.length, &locals_length, base::Optional<uint32_t>());
@ -1662,7 +1661,8 @@ class WasmDecoder : public Decoder {
case kExprSelect:
return 1;
case kExprSelectWithType: {
SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1);
SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
nullptr);
return 1 + imm.length;
}
case kExprLocalGet:
@ -1694,7 +1694,8 @@ class WasmDecoder : public Decoder {
case kExprF64Const:
return 9;
case kExprRefNull: {
HeapTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1);
HeapTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
nullptr);
return 1 + imm.length;
}
case kExprRefIsNull: {
@ -1881,7 +1882,7 @@ class WasmDecoder : public Decoder {
// TODO(7748): Account for rtt.sub's additional immediates if
// they stick.
HeapTypeImmediate<validate> imm(WasmFeatures::All(), decoder,
pc + length);
pc + length, nullptr);
return length + imm.length;
}
case kExprI31New:
@ -1891,9 +1892,9 @@ class WasmDecoder : public Decoder {
case kExprRefTest:
case kExprRefCast: {
HeapTypeImmediate<validate> ht1(WasmFeatures::All(), decoder,
pc + length);
pc + length, nullptr);
HeapTypeImmediate<validate> ht2(WasmFeatures::All(), decoder,
pc + length + ht1.length);
pc + length + ht1.length, nullptr);
return length + ht1.length + ht2.length;
}
default:
@ -2371,7 +2372,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
#undef BUILD_SIMPLE_OPCODE
DECODE(Block) {
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
ArgVector args = PopArgs(imm.sig);
Control* block = PushControl(kControlBlock);
@ -2401,7 +2403,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
DECODE(Try) {
CHECK_PROTOTYPE_OPCODE(eh);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
ArgVector args = PopArgs(imm.sig);
Control* try_block = PushControl(kControlTry);
@ -2501,7 +2504,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
DECODE(Let) {
CHECK_PROTOTYPE_OPCODE(typed_funcref);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
// Temporarily add the let-defined values to the beginning of the function
// locals.
@ -2524,7 +2528,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
DECODE(Loop) {
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
ArgVector args = PopArgs(imm.sig);
Control* block = PushControl(kControlLoop);
@ -2535,7 +2540,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
DECODE(If) {
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
Value cond = Pop(0, kWasmI32);
ArgVector args = PopArgs(imm.sig);
@ -2631,7 +2637,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
DECODE(SelectWithType) {
CHECK_PROTOTYPE_OPCODE(reftypes);
SelectTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
SelectTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (this->failed()) return 0;
Value cond = Pop(2, kWasmI32);
Value fval = Pop(1, imm.type);
@ -2773,8 +2780,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
DECODE(RefNull) {
CHECK_PROTOTYPE_OPCODE(reftypes);
HeapTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1);
if (!this->Validate(this->pc_ + 1, imm)) return 0;
HeapTypeImmediate<validate> imm(this->enabled_, this, this->pc_ + 1,
this->module_);
if (!VALIDATE(this->ok())) return 0;
ValueType type = ValueType::Ref(imm.type, kNullable);
Value* value = Push(type);
CALL_INTERFACE_IF_REACHABLE(RefNull, type, value);
@ -3937,9 +3945,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return opcode_length;
}
case kExprRttCanon: {
HeapTypeImmediate<validate> imm(this->enabled_, this,
this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
HeapTypeImmediate<validate> imm(
this->enabled_, this, this->pc_ + opcode_length, this->module_);
if (!VALIDATE(this->ok())) return 0;
Value* value =
Push(ValueType::Rtt(imm.type, imm.type == HeapType::kAny ? 0 : 1));
CALL_INTERFACE_IF_REACHABLE(RttCanon, imm, value);
@ -3952,9 +3960,9 @@ class WasmFullDecoder : public WasmDecoder<validate> {
// If these immediates don't get dropped (in the spirit of
// https://github.com/WebAssembly/function-references/pull/31 ),
// implement them here.
HeapTypeImmediate<validate> imm(this->enabled_, this,
this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, imm)) return 0;
HeapTypeImmediate<validate> imm(
this->enabled_, this, this->pc_ + opcode_length, this->module_);
if (!VALIDATE(this->ok())) return 0;
Value parent = Pop(0);
if (parent.type.is_bottom()) {
Push(kWasmBottom);
@ -3986,14 +3994,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprRefTest: {
// "Tests whether {obj}'s runtime type is a runtime subtype of {rtt}."
HeapTypeImmediate<validate> obj_type(this->enabled_, this,
this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, obj_type)) return 0;
HeapTypeImmediate<validate> obj_type(
this->enabled_, this, this->pc_ + opcode_length, this->module_);
int len = opcode_length + obj_type.length;
HeapTypeImmediate<validate> rtt_type(this->enabled_, this,
this->pc_ + len);
if (!this->Validate(this->pc_ + len, rtt_type)) return 0;
this->pc_ + len, this->module_);
len += rtt_type.length;
if (!VALIDATE(this->ok())) return 0;
// The static type of {obj} must be a supertype of the {rtt}'s type.
if (!VALIDATE(IsSubtypeOf(ValueType::Ref(rtt_type.type, kNonNullable),
ValueType::Ref(obj_type.type, kNonNullable),
@ -4017,14 +4025,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return len;
}
case kExprRefCast: {
HeapTypeImmediate<validate> obj_type(this->enabled_, this,
this->pc_ + opcode_length);
if (!this->Validate(this->pc_ + opcode_length, obj_type)) return 0;
HeapTypeImmediate<validate> obj_type(
this->enabled_, this, this->pc_ + opcode_length, this->module_);
int len = opcode_length + obj_type.length;
HeapTypeImmediate<validate> rtt_type(this->enabled_, this,
this->pc_ + len);
if (!this->Validate(this->pc_ + len, rtt_type)) return 0;
this->pc_ + len, this->module_);
len += rtt_type.length;
if (!VALIDATE(this->ok())) return 0;
if (!VALIDATE(IsSubtypeOf(ValueType::Ref(rtt_type.type, kNonNullable),
ValueType::Ref(obj_type.type, kNonNullable),
this->module_))) {

View File

@ -20,11 +20,12 @@ namespace internal {
namespace wasm {
bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls,
const byte* start, const byte* end) {
const WasmModule* module, const byte* start,
const byte* end) {
WasmFeatures no_features = WasmFeatures::None();
Zone* zone = decls->type_list.get_allocator().zone();
WasmDecoder<Decoder::kFullValidation> decoder(
zone, nullptr, enabled, &no_features, nullptr, start, end, 0);
zone, module, enabled, &no_features, nullptr, start, end, 0);
uint32_t length;
if (decoder.DecodeLocals(decoder.pc(), &length, 0) < 0) {
decls->encoded_size = 0;
@ -42,7 +43,7 @@ BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
BodyLocalDecls* decls)
: Decoder(start, end) {
if (decls != nullptr) {
if (DecodeLocalDecls(WasmFeatures::All(), decls, start, end)) {
if (DecodeLocalDecls(WasmFeatures::All(), decls, nullptr, start, end)) {
pc_ += decls->encoded_size;
if (pc_ > end_) pc_ = end_;
}
@ -244,7 +245,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
case kExprBlock:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidation> imm(WasmFeatures::All(), &i,
i.pc() + 1);
i.pc() + 1, module);
os << " @" << i.pc_offset();
if (decoder.Complete(imm)) {
for (uint32_t i = 0; i < imm.out_arity(); i++) {

View File

@ -67,6 +67,7 @@ struct BodyLocalDecls {
V8_EXPORT_PRIVATE bool DecodeLocalDecls(const WasmFeatures& enabled,
BodyLocalDecls* decls,
const WasmModule* module,
const byte* start, const byte* end);
V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting(

View File

@ -1648,22 +1648,6 @@ class ModuleDecoderImpl : public Decoder {
return true;
}
// TODO(manoskouk): This is copy-modified from function-body-decoder-impl.h.
// We should find a way to share this code.
V8_INLINE bool Validate(const byte* pc,
HeapTypeImmediate<kFullValidation>& imm) {
if (V8_UNLIKELY(imm.type.is_bottom())) {
error(pc, "invalid heap type");
return false;
}
if (V8_UNLIKELY(!(imm.type.is_generic() ||
module_->has_type(imm.type.ref_index())))) {
errorf(pc, "Type index %u is out of bounds", imm.type.ref_index());
return false;
}
return true;
}
WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected,
size_t current_global_index) {
constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
@ -1735,10 +1719,10 @@ class ModuleDecoderImpl : public Decoder {
kExprRefNull);
return {};
}
HeapTypeImmediate<Decoder::kFullValidation> imm(enabled_features_,
this, pc() + 1);
HeapTypeImmediate<Decoder::kFullValidation> imm(
enabled_features_, this, pc() + 1, module_.get());
if (V8_UNLIKELY(failed())) return {};
len = 1 + imm.length;
if (!Validate(pc() + 1, imm)) return {};
stack.push_back(
WasmInitExpr::RefNullConst(imm.type.representation()));
break;
@ -1786,19 +1770,19 @@ class ModuleDecoderImpl : public Decoder {
opcode = read_prefixed_opcode<validate>(pc(), &len);
switch (opcode) {
case kExprRttCanon: {
HeapTypeImmediate<validate> imm(enabled_features_, this,
pc() + 2);
HeapTypeImmediate<validate> imm(enabled_features_, this, pc() + 2,
module_.get());
if (V8_UNLIKELY(failed())) return {};
len += imm.length;
if (!Validate(pc() + len, imm)) return {};
stack.push_back(
WasmInitExpr::RttCanon(imm.type.representation()));
break;
}
case kExprRttSub: {
HeapTypeImmediate<validate> imm(enabled_features_, this,
pc() + 2);
HeapTypeImmediate<validate> imm(enabled_features_, this, pc() + 2,
module_.get());
if (V8_UNLIKELY(failed())) return {};
len += imm.length;
if (!Validate(pc() + len, imm)) return {};
if (stack.empty()) {
error(pc(), "calling rtt.sub without arguments");
return {};
@ -1870,13 +1854,8 @@ class ModuleDecoderImpl : public Decoder {
ValueType consume_value_type() {
uint32_t type_length;
ValueType result = value_type_reader::read_value_type<kFullValidation>(
this, this->pc(), &type_length,
this, this->pc(), &type_length, module_.get(),
origin_ == kWasmOrigin ? enabled_features_ : WasmFeatures::None());
// We use capacity() over size() so this function works
// mid-DecodeTypeSection.
if (result.has_index() && result.ref_index() >= module_->types.capacity()) {
errorf(pc(), "Type index %u is out of bounds", result.ref_index());
}
consume_bytes(type_length, "value type");
return result;
}
@ -2166,7 +2145,7 @@ class ModuleDecoderImpl : public Decoder {
switch (opcode) {
case kExprRefNull: {
HeapTypeImmediate<kFullValidation> imm(WasmFeatures::All(), this,
this->pc());
this->pc(), module_.get());
consume_bytes(imm.length, "ref.null immediate");
index = WasmElemSegment::kNullIndex;
break;

View File

@ -790,8 +790,8 @@ class SideTable : public ZoneObject {
case kExprBlock:
case kExprLoop: {
bool is_loop = opcode == kExprLoop;
BlockTypeImmediate<Decoder::kNoValidation> imm(WasmFeatures::All(),
&i, i.pc() + 1);
BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &i, i.pc() + 1, module);
if (imm.type == kWasmBottom) {
imm.sig = module->signature(imm.sig_index);
}
@ -812,8 +812,8 @@ class SideTable : public ZoneObject {
break;
}
case kExprIf: {
BlockTypeImmediate<Decoder::kNoValidation> imm(WasmFeatures::All(),
&i, i.pc() + 1);
BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &i, i.pc() + 1, module);
if (imm.type == kWasmBottom) {
imm.sig = module->signature(imm.sig_index);
}
@ -852,8 +852,8 @@ class SideTable : public ZoneObject {
break;
}
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidation> imm(WasmFeatures::All(),
&i, i.pc() + 1);
BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &i, i.pc() + 1, module);
if (imm.type == kWasmBottom) {
imm.sig = module->signature(imm.sig_index);
}
@ -3262,13 +3262,13 @@ class WasmInterpreterInternals {
case kExprLoop:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &decoder, code->at(pc + 1));
WasmFeatures::All(), &decoder, code->at(pc + 1), module());
len = 1 + imm.length;
break;
}
case kExprIf: {
BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &decoder, code->at(pc + 1));
WasmFeatures::All(), &decoder, code->at(pc + 1), module());
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
@ -3328,7 +3328,7 @@ class WasmInterpreterInternals {
}
case kExprSelectWithType: {
SelectTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &decoder, code->at(pc + 1));
WasmFeatures::All(), &decoder, code->at(pc + 1), module());
len = 1 + imm.length;
V8_FALLTHROUGH;
}
@ -3417,7 +3417,7 @@ class WasmInterpreterInternals {
}
case kExprRefNull: {
HeapTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &decoder, code->at(pc + 1));
WasmFeatures::All(), &decoder, code->at(pc + 1), module());
len = 1 + imm.length;
Push(WasmValue(isolate_->factory()->null_value()));
break;

View File

@ -269,7 +269,7 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
// Add locals.
BodyLocalDecls decls(&tmp_zone);
DecodeLocalDecls(enabled_features, &decls, func_code.begin(),
DecodeLocalDecls(enabled_features, &decls, module, func_code.begin(),
func_code.end());
if (!decls.type_list.empty()) {
os << " ";

View File

@ -4663,18 +4663,20 @@ TEST_F(WasmOpcodeLengthTest, PrefixedOpcodesLEB) {
class TypeReaderTest : public TestWithZone {
public:
ValueType DecodeValueType(const byte* start, const byte* end) {
ValueType DecodeValueType(const byte* start, const byte* end,
const WasmModule* module) {
Decoder decoder(start, end);
uint32_t length;
return value_type_reader::read_value_type<Decoder::kFullValidation>(
&decoder, start, &length, enabled_features_);
&decoder, start, &length, module, enabled_features_);
}
HeapType DecodeHeapType(const byte* start, const byte* end) {
HeapType DecodeHeapType(const byte* start, const byte* end,
const WasmModule* module) {
Decoder decoder(start, end);
uint32_t length;
return value_type_reader::read_heap_type<Decoder::kFullValidation>(
&decoder, start, &length, enabled_features_);
&decoder, start, &length, module, enabled_features_);
}
// This variable is modified by WASM_FEATURE_SCOPE.
@ -4692,34 +4694,34 @@ TEST_F(TypeReaderTest, HeapTypeDecodingTest) {
// 1- to 5-byte representation of kFuncRefCode.
{
const byte data[] = {kFuncRefCode};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_TRUE(result == heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0xFF, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_func);
}
{
// Some negative number.
const byte data[] = {0xB4, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_bottom);
}
@ -4728,7 +4730,7 @@ TEST_F(TypeReaderTest, HeapTypeDecodingTest) {
// range. This should therefore NOT be decoded as HeapType::kFunc and
// instead fail.
const byte data[] = {kFuncRefCode | 0x80, 0x6F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
HeapType result = DecodeHeapType(data, data + sizeof(data), nullptr);
EXPECT_EQ(result, heap_bottom);
}
}
@ -4750,7 +4752,9 @@ class LocalDeclDecoderTest : public TestWithZone {
bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
const byte* end) {
return i::wasm::DecodeLocalDecls(enabled_features_, decls, start, end);
WasmModule module;
return i::wasm::DecodeLocalDecls(enabled_features_, decls, &module, start,
end);
}
};
@ -4877,6 +4881,20 @@ TEST_F(LocalDeclDecoderTest, ExnRef) {
EXPECT_EQ(type, map[0]);
}
TEST_F(LocalDeclDecoderTest, InvalidTypeIndex) {
WASM_FEATURE_SCOPE(reftypes);
WASM_FEATURE_SCOPE(typed_funcref);
const byte* data = nullptr;
const byte* end = nullptr;
LocalDeclEncoder local_decls(zone());
local_decls.AddLocals(1, ValueType::Ref(0, kNullable));
BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(&decls, data, end);
EXPECT_FALSE(result);
}
class BytecodeIteratorTest : public TestWithZone {};
TEST_F(BytecodeIteratorTest, SimpleForeach) {