Commit f792114b authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm-gc] Don't only consider 7 bits of i33 values

When comparing a decoded i33 value (v) to an expected value (ex) given
as a 7-bit unsigned byte, we first truncated (v) to 7 bits. This
resulted in values which coincide with (ex) only in the last 7 digits to
erroneously be accepted.

Bug: v8:7748
Change-Id: Iaf40d5be7bbfa80535cec9109c7dd19a9d96edaf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2526387
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71091}
parent 8a5cb3dc
......@@ -197,6 +197,12 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
uint32_t* const length, 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;
if (heap_index < min_1_byte_leb128) {
DecodeError<validate>(decoder, pc, "Unknown heap type %" PRId64,
heap_index);
return HeapType(HeapType::kBottom);
}
uint8_t uint_7_mask = 0x7F;
uint8_t code = static_cast<ValueTypeCode>(heap_index) & uint_7_mask;
switch (code) {
......@@ -457,7 +463,8 @@ struct BlockTypeImmediate {
int64_t block_type =
decoder->read_i33v<validate>(pc, &length, "block type");
if (block_type < 0) {
if ((static_cast<uint8_t>(block_type) & byte{0x7f}) == kVoidCode) return;
constexpr int64_t kVoidCode_i64_extended = (~int64_t{0x7F}) | kVoidCode;
if (block_type == kVoidCode_i64_extended) return;
type = value_type_reader::read_value_type<validate>(decoder, pc, &length,
enabled);
if (!VALIDATE(type != kWasmBottom)) {
......
......@@ -755,6 +755,14 @@ TEST_F(FunctionBodyDecoderTest, BlockBrBinop) {
WASM_I32V_1(2))});
}
TEST_F(FunctionBodyDecoderTest, VoidBlockTypeVariants) {
// Valid kVoidCode encoded in 2 bytes.
ExpectValidates(sigs.v_v(), {kExprBlock, kVoidCode | 0x80, 0x7F, kExprEnd});
// Invalid code, whose last 7 bits coincide with kVoidCode.
ExpectFailure(sigs.v_v(), {kExprBlock, kVoidCode | 0x80, 0x45, kExprEnd},
kAppendEnd, "Invalid block type");
}
TEST_F(FunctionBodyDecoderTest, If_empty1) {
ExpectValidates(sigs.v_v(), {WASM_ZERO, WASM_IF_OP, kExprEnd});
}
......@@ -4601,6 +4609,78 @@ TEST_F(WasmOpcodeLengthTest, PrefixedOpcodesLEB) {
ExpectLength(5, 0xfe, 0x80, 0x00, 0x00, 0x00);
}
class TypeReaderTest : public TestWithZone {
public:
ValueType DecodeValueType(const byte* start, const byte* end) {
Decoder decoder(start, end);
uint32_t length;
return value_type_reader::read_value_type<Decoder::kFullValidation>(
&decoder, start, &length, enabled_features_);
}
HeapType DecodeHeapType(const byte* start, const byte* end) {
Decoder decoder(start, end);
uint32_t length;
return value_type_reader::read_heap_type<Decoder::kFullValidation>(
&decoder, start, &length, enabled_features_);
}
// This variable is modified by WASM_FEATURE_SCOPE.
WasmFeatures enabled_features_;
};
TEST_F(TypeReaderTest, HeapTypeDecodingTest) {
WASM_FEATURE_SCOPE(gc);
WASM_FEATURE_SCOPE(reftypes);
WASM_FEATURE_SCOPE(typed_funcref);
HeapType heap_func = HeapType(HeapType::kFunc);
HeapType heap_bottom = HeapType(HeapType::kBottom);
// 1- to 5-byte representation of kFuncRefCode.
{
const byte data[] = {kFuncRefCode};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_TRUE(result == heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_EQ(result, heap_func);
}
{
const byte data[] = {kFuncRefCode | 0x80, 0xFF, 0xFF, 0xFF, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_EQ(result, heap_func);
}
{
// Some negative number.
const byte data[] = {0xB4, 0x7F};
HeapType result = DecodeHeapType(data, data + sizeof(data));
EXPECT_EQ(result, heap_bottom);
}
{
// This differs from kFuncRefCode by one bit outside the 1-byte LEB128
// 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));
EXPECT_EQ(result, heap_bottom);
}
}
using TypesOfLocals = ZoneVector<ValueType>;
class LocalDeclDecoderTest : public TestWithZone {
......
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