[wasm] Simplify LEB decoding
Remove one "mode" of LEB decoding by eliminating the {AdvancePCFlag}, and doing the PC advance in the caller instead. The returned length is now always zero in case of an error, thus remove the respective checks from the unit tests. The returned length does not really matter if we ran into an error. R=thibaudm@chromium.org Change-Id: Ibfd94dd981cefa2fc24c7af560c85afd1c826f2c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2449972 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#70404}
This commit is contained in:
parent
637d1fc00b
commit
5bf16197ec
@ -46,8 +46,6 @@ class Decoder {
|
||||
kFullValidation // Run full validation with error message and location.
|
||||
};
|
||||
|
||||
enum AdvancePCFlag : bool { kAdvancePc = true, kNoAdvancePc = false };
|
||||
|
||||
enum TraceFlag : bool { kTrace = true, kNoTrace = false };
|
||||
|
||||
Decoder(const byte* start, const byte* end, uint32_t buffer_offset = 0)
|
||||
@ -101,40 +99,35 @@ class Decoder {
|
||||
template <ValidateFlag validate>
|
||||
uint32_t read_u32v(const byte* pc, uint32_t* length,
|
||||
const char* name = "LEB32") {
|
||||
return read_leb<uint32_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
|
||||
name);
|
||||
return read_leb<uint32_t, validate, kNoTrace>(pc, length, name);
|
||||
}
|
||||
|
||||
// Reads a variable-length signed integer (little endian).
|
||||
template <ValidateFlag validate>
|
||||
int32_t read_i32v(const byte* pc, uint32_t* length,
|
||||
const char* name = "signed LEB32") {
|
||||
return read_leb<int32_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
|
||||
name);
|
||||
return read_leb<int32_t, validate, kNoTrace>(pc, length, name);
|
||||
}
|
||||
|
||||
// Reads a variable-length unsigned integer (little endian).
|
||||
template <ValidateFlag validate>
|
||||
uint64_t read_u64v(const byte* pc, uint32_t* length,
|
||||
const char* name = "LEB64") {
|
||||
return read_leb<uint64_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
|
||||
name);
|
||||
return read_leb<uint64_t, validate, kNoTrace>(pc, length, name);
|
||||
}
|
||||
|
||||
// Reads a variable-length signed integer (little endian).
|
||||
template <ValidateFlag validate>
|
||||
int64_t read_i64v(const byte* pc, uint32_t* length,
|
||||
const char* name = "signed LEB64") {
|
||||
return read_leb<int64_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
|
||||
name);
|
||||
return read_leb<int64_t, validate, kNoTrace>(pc, length, name);
|
||||
}
|
||||
|
||||
// Reads a variable-length 33-bit signed integer (little endian).
|
||||
template <ValidateFlag validate>
|
||||
int64_t read_i33v(const byte* pc, uint32_t* length,
|
||||
const char* name = "signed LEB33") {
|
||||
return read_leb<int64_t, validate, kNoAdvancePc, kNoTrace, 33>(pc, length,
|
||||
name);
|
||||
return read_leb<int64_t, validate, kNoTrace, 33>(pc, length, name);
|
||||
}
|
||||
|
||||
// Reads a prefixed-opcode, possibly with variable-length index.
|
||||
@ -188,22 +181,28 @@ class Decoder {
|
||||
// Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}.
|
||||
uint32_t consume_u32v(const char* name = nullptr) {
|
||||
uint32_t length = 0;
|
||||
return read_leb<uint32_t, kFullValidation, kAdvancePc, kTrace>(pc_, &length,
|
||||
name);
|
||||
uint32_t result =
|
||||
read_leb<uint32_t, kFullValidation, kTrace>(pc_, &length, name);
|
||||
pc_ += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}.
|
||||
int32_t consume_i32v(const char* name = nullptr) {
|
||||
uint32_t length = 0;
|
||||
return read_leb<int32_t, kFullValidation, kAdvancePc, kTrace>(pc_, &length,
|
||||
name);
|
||||
int32_t result =
|
||||
read_leb<int32_t, kFullValidation, kTrace>(pc_, &length, name);
|
||||
pc_ += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Reads a LEB128 variable-length unsigned 64-bit integer and advances {pc_}.
|
||||
uint64_t consume_u64v(const char* name = nullptr) {
|
||||
uint32_t length = 0;
|
||||
return read_leb<uint64_t, kFullValidation, kAdvancePc, kTrace>(pc_, &length,
|
||||
name);
|
||||
uint64_t result =
|
||||
read_leb<uint64_t, kFullValidation, kTrace>(pc_, &length, name);
|
||||
pc_ += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
|
||||
@ -386,20 +385,19 @@ class Decoder {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename IntType, ValidateFlag validate, AdvancePCFlag advance_pc,
|
||||
TraceFlag trace, size_t size_in_bits = 8 * sizeof(IntType)>
|
||||
template <typename IntType, ValidateFlag validate, TraceFlag trace,
|
||||
size_t size_in_bits = 8 * sizeof(IntType)>
|
||||
IntType read_leb(const byte* pc, uint32_t* length,
|
||||
const char* name = "varint") {
|
||||
DCHECK_IMPLIES(advance_pc, pc == pc_);
|
||||
static_assert(size_in_bits <= 8 * sizeof(IntType),
|
||||
"leb does not fit in type");
|
||||
TRACE_IF(trace, " +%u %-20s: ", pc_offset(), name);
|
||||
return read_leb_tail<IntType, validate, advance_pc, trace, size_in_bits, 0>(
|
||||
pc, length, name, 0);
|
||||
return read_leb_tail<IntType, validate, trace, size_in_bits, 0>(pc, length,
|
||||
name, 0);
|
||||
}
|
||||
|
||||
template <typename IntType, ValidateFlag validate, AdvancePCFlag advance_pc,
|
||||
TraceFlag trace, size_t size_in_bits, int byte_index>
|
||||
template <typename IntType, ValidateFlag validate, TraceFlag trace,
|
||||
size_t size_in_bits, int byte_index>
|
||||
IntType read_leb_tail(const byte* pc, uint32_t* length, const char* name,
|
||||
IntType result) {
|
||||
constexpr bool is_signed = std::is_signed<IntType>::value;
|
||||
@ -422,10 +420,9 @@ class Decoder {
|
||||
// Compilers are not smart enough to figure out statically that the
|
||||
// following call is unreachable if is_last_byte is false.
|
||||
constexpr int next_byte_index = byte_index + (is_last_byte ? 0 : 1);
|
||||
return read_leb_tail<IntType, validate, advance_pc, trace, size_in_bits,
|
||||
return read_leb_tail<IntType, validate, trace, size_in_bits,
|
||||
next_byte_index>(pc + 1, length, name, result);
|
||||
}
|
||||
if (advance_pc) pc_ = pc + (at_end ? 0 : 1);
|
||||
*length = byte_index + (at_end ? 0 : 1);
|
||||
if (validate && V8_UNLIKELY(at_end || (b & 0x80))) {
|
||||
TRACE_IF(trace, at_end ? "<end> " : "<length overflow> ");
|
||||
@ -435,6 +432,7 @@ class Decoder {
|
||||
MarkError();
|
||||
}
|
||||
result = 0;
|
||||
*length = 0;
|
||||
}
|
||||
if (is_last_byte) {
|
||||
// A signed-LEB128 must sign-extend the final byte, excluding its
|
||||
@ -459,6 +457,7 @@ class Decoder {
|
||||
MarkError();
|
||||
}
|
||||
result = 0;
|
||||
*length = 0;
|
||||
}
|
||||
}
|
||||
constexpr int sign_ext_shift =
|
||||
|
@ -517,10 +517,6 @@ size_t AsyncStreamingDecoder::DecodeVarInt32::ReadBytes(
|
||||
Decoder decoder(buf,
|
||||
streaming->module_offset() - static_cast<uint32_t>(offset()));
|
||||
value_ = decoder.consume_u32v(field_name_);
|
||||
// The number of bytes we actually needed to read.
|
||||
DCHECK_GT(decoder.pc(), buffer().begin());
|
||||
bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.begin());
|
||||
TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
|
||||
|
||||
if (decoder.failed()) {
|
||||
if (new_bytes == remaining_buf.size()) {
|
||||
@ -531,6 +527,11 @@ size_t AsyncStreamingDecoder::DecodeVarInt32::ReadBytes(
|
||||
return new_bytes;
|
||||
}
|
||||
|
||||
// The number of bytes we actually needed to read.
|
||||
DCHECK_GT(decoder.pc(), buffer().begin());
|
||||
bytes_consumed_ = static_cast<size_t>(decoder.pc() - buf.begin());
|
||||
TRACE_STREAMING(" ==> %zu bytes consumed\n", bytes_consumed_);
|
||||
|
||||
// We read all the bytes we needed.
|
||||
DCHECK_GT(bytes_consumed_, offset());
|
||||
new_bytes = bytes_consumed_ - offset();
|
||||
|
@ -380,7 +380,6 @@ TEST_F(DecoderTest, ReadU32v_off_end1) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data);
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(0u, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
|
||||
@ -390,7 +389,6 @@ TEST_F(DecoderTest, ReadU32v_off_end2) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + i);
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(i, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -401,7 +399,6 @@ TEST_F(DecoderTest, ReadU32v_off_end3) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + i);
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(i, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -412,7 +409,6 @@ TEST_F(DecoderTest, ReadU32v_off_end4) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + i);
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(i, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -423,7 +419,6 @@ TEST_F(DecoderTest, ReadU32v_off_end5) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + i);
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(i, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -435,7 +430,6 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + sizeof(data));
|
||||
decoder.read_u32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(5u, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -456,7 +450,6 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_positive) {
|
||||
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x77};
|
||||
decoder.Reset(data, data + sizeof(data));
|
||||
decoder.read_i32v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(5u, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
|
||||
@ -654,7 +647,6 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) {
|
||||
unsigned length = 0;
|
||||
decoder.Reset(data, data + sizeof(data));
|
||||
decoder.read_u64v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(10u, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
}
|
||||
@ -675,7 +667,6 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_positive) {
|
||||
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x77};
|
||||
decoder.Reset(data, data + sizeof(data));
|
||||
decoder.read_i64v<Decoder::kFullValidation>(decoder.start(), &length);
|
||||
EXPECT_EQ(10u, length);
|
||||
EXPECT_FALSE(decoder.ok());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user