Commit 02b4d0e6 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] [decoder] Merge checked_read_leb and consume_leb

Both methods decoded a LEB128 encoded integer, but only consume_leb
incremented the pc pointer accordingly.
This CL implements consume_leb by using checked_read_leb.

It also refactors a few things:
1) It removes error_pt, which was only avaible in checked_read_leb.
2) It renames the error method to errorf, since it receives a format
   string. This also avoids a name clash.
3) It implements sign extension directly in checked_read_leb instead of
   doing this in the caller.

R=ahaas@chromium.org
BUG=v8:5822

Change-Id: I8058f57418493861e5df26d4949041f6766d5138
Reviewed-on: https://chromium-review.googlesource.com/467150
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44405}
parent 0ed2f178
...@@ -23,8 +23,13 @@ namespace wasm { ...@@ -23,8 +23,13 @@ namespace wasm {
do { \ do { \
if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
} while (false) } while (false)
#define TRACE_IF(cond, ...) \
do { \
if (FLAG_trace_wasm_decoder && (cond)) PrintF(__VA_ARGS__); \
} while (false)
#else #else
#define TRACE(...) #define TRACE(...)
#define TRACE_IF(...)
#endif #endif
// A helper utility to decode bytes, integers, fields, varints, etc, from // A helper utility to decode bytes, integers, fields, varints, etc, from
...@@ -32,94 +37,67 @@ namespace wasm { ...@@ -32,94 +37,67 @@ namespace wasm {
class Decoder { class Decoder {
public: public:
Decoder(const byte* start, const byte* end) Decoder(const byte* start, const byte* end)
: start_(start), : start_(start), pc_(start), end_(end), error_pc_(nullptr) {}
pc_(start),
end_(end),
error_pc_(nullptr),
error_pt_(nullptr) {}
Decoder(const byte* start, const byte* pc, const byte* end) Decoder(const byte* start, const byte* pc, const byte* end)
: start_(start), : start_(start), pc_(pc), end_(end), error_pc_(nullptr) {}
pc_(pc),
end_(end),
error_pc_(nullptr),
error_pt_(nullptr) {}
virtual ~Decoder() {} virtual ~Decoder() {}
inline bool check(const byte* base, unsigned offset, unsigned length, inline bool check(const byte* pc, unsigned length, const char* msg) {
const char* msg) { DCHECK_LE(start_, pc);
DCHECK_GE(base, start_); if (V8_UNLIKELY(pc + length > end_)) {
if ((base + offset + length) > end_) { error(pc, msg);
error(base, base + offset, "%s", msg);
return false; return false;
} }
return true; return true;
} }
// Reads a single 8-bit byte, reporting an error if out of bounds. // Reads a single 8-bit byte, reporting an error if out of bounds.
inline uint8_t checked_read_u8(const byte* base, unsigned offset, inline uint8_t checked_read_u8(const byte* pc,
const char* msg = "expected 1 byte") { const char* msg = "expected 1 byte") {
return check(base, offset, 1, msg) ? base[offset] : 0; return check(pc, 1, msg) ? *pc : 0;
} }
// Reads 16-bit word, reporting an error if out of bounds. // Reads 16-bit word, reporting an error if out of bounds.
inline uint16_t checked_read_u16(const byte* base, unsigned offset, inline uint16_t checked_read_u16(const byte* pc,
const char* msg = "expected 2 bytes") { const char* msg = "expected 2 bytes") {
return check(base, offset, 2, msg) ? read_u16(base + offset) : 0; return check(pc, 2, msg) ? read_u16(pc) : 0;
} }
// Reads 32-bit word, reporting an error if out of bounds. // Reads 32-bit word, reporting an error if out of bounds.
inline uint32_t checked_read_u32(const byte* base, unsigned offset, inline uint32_t checked_read_u32(const byte* pc,
const char* msg = "expected 4 bytes") { const char* msg = "expected 4 bytes") {
return check(base, offset, 4, msg) ? read_u32(base + offset) : 0; return check(pc, 4, msg) ? read_u32(pc) : 0;
} }
// Reads 64-bit word, reporting an error if out of bounds. // Reads 64-bit word, reporting an error if out of bounds.
inline uint64_t checked_read_u64(const byte* base, unsigned offset, inline uint64_t checked_read_u64(const byte* pc,
const char* msg = "expected 8 bytes") { const char* msg = "expected 8 bytes") {
return check(base, offset, 8, msg) ? read_u64(base + offset) : 0; return check(pc, 8, msg) ? read_u64(pc) : 0;
} }
// Reads a variable-length unsigned integer (little endian). // Reads a variable-length unsigned integer (little endian).
uint32_t checked_read_u32v(const byte* base, unsigned offset, uint32_t checked_read_u32v(const byte* pc, unsigned* length,
unsigned* length, const char* name = "LEB32") {
const char* msg = "expected LEB32") { return checked_read_leb<uint32_t, false, false>(pc, length, name);
return checked_read_leb<uint32_t, false>(base, offset, length, msg);
} }
// Reads a variable-length signed integer (little endian). // Reads a variable-length signed integer (little endian).
int32_t checked_read_i32v(const byte* base, unsigned offset, unsigned* length, int32_t checked_read_i32v(const byte* pc, unsigned* length,
const char* msg = "expected SLEB32") { const char* name = "signed LEB32") {
uint32_t result = return checked_read_leb<int32_t, false, false>(pc, length, name);
checked_read_leb<uint32_t, true>(base, offset, length, msg);
if (*length == 5) return bit_cast<int32_t>(result);
if (*length > 0) {
int shift = 32 - 7 * *length;
// Perform sign extension.
return bit_cast<int32_t>(result << shift) >> shift;
}
return 0;
} }
// Reads a variable-length unsigned integer (little endian). // Reads a variable-length unsigned integer (little endian).
uint64_t checked_read_u64v(const byte* base, unsigned offset, uint64_t checked_read_u64v(const byte* pc, unsigned* length,
unsigned* length, const char* name = "LEB64") {
const char* msg = "expected LEB64") { return checked_read_leb<uint64_t, false, false>(pc, length, name);
return checked_read_leb<uint64_t, false>(base, offset, length, msg);
} }
// Reads a variable-length signed integer (little endian). // Reads a variable-length signed integer (little endian).
int64_t checked_read_i64v(const byte* base, unsigned offset, unsigned* length, int64_t checked_read_i64v(const byte* pc, unsigned* length,
const char* msg = "expected SLEB64") { const char* name = "signed LEB64") {
uint64_t result = return checked_read_leb<int64_t, false, false>(pc, length, name);
checked_read_leb<uint64_t, true>(base, offset, length, msg);
if (*length == 10) return bit_cast<int64_t>(result);
if (*length > 0) {
int shift = 64 - 7 * *length;
// Perform sign extension.
return bit_cast<int64_t>(result << shift) >> shift;
}
return 0;
} }
// Reads a single 16-bit unsigned integer (little endian). // Reads a single 16-bit unsigned integer (little endian).
...@@ -149,7 +127,7 @@ class Decoder { ...@@ -149,7 +127,7 @@ class Decoder {
TRACE("%02x = %d\n", val, val); TRACE("%02x = %d\n", val, val);
return val; return val;
} }
return traceOffEnd<uint8_t>(); return traceOffEnd<uint8_t, true>();
} }
// Reads a 16-bit unsigned integer (little endian) and advances {pc_}. // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
...@@ -162,7 +140,7 @@ class Decoder { ...@@ -162,7 +140,7 @@ class Decoder {
pc_ += 2; pc_ += 2;
return val; return val;
} }
return traceOffEnd<uint16_t>(); return traceOffEnd<uint16_t, true>();
} }
// Reads a single 32-bit unsigned integer (little endian) and advances {pc_}. // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
...@@ -175,28 +153,26 @@ class Decoder { ...@@ -175,28 +153,26 @@ class Decoder {
pc_ += 4; pc_ += 4;
return val; return val;
} }
return traceOffEnd<uint32_t>(); return traceOffEnd<uint32_t, true>();
} }
// Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}. // Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}.
uint32_t consume_u32v(const char* name = nullptr) { uint32_t consume_u32v(const char* name = nullptr) {
return consume_leb<uint32_t, false>(name); unsigned length = 0;
return checked_read_leb<uint32_t, true, true>(pc_, &length, name);
} }
// Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}. // Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}.
int32_t consume_i32v(const char* name = nullptr) { int32_t consume_i32v(const char* name = nullptr) {
return consume_leb<int32_t, true>(name); unsigned length = 0;
return checked_read_leb<int32_t, true, true>(pc_, &length, name);
} }
// Consume {size} bytes and send them to the bit bucket, advancing {pc_}. // Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
void consume_bytes(uint32_t size, const char* name = "skip") { void consume_bytes(uint32_t size, const char* name = "skip") {
#if DEBUG // Only trace if the name is not null.
if (name) { TRACE_IF(name, " +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_),
// Only trace if the name is not null. name, size);
TRACE(" +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_), name,
size);
}
#endif
if (checkAvailable(size)) { if (checkAvailable(size)) {
pc_ += size; pc_ += size;
} else { } else {
...@@ -208,55 +184,52 @@ class Decoder { ...@@ -208,55 +184,52 @@ class Decoder {
bool checkAvailable(int size) { bool checkAvailable(int size) {
intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size; intptr_t pc_overflow_value = std::numeric_limits<intptr_t>::max() - size;
if (size < 0 || (intptr_t)pc_ > pc_overflow_value) { if (size < 0 || (intptr_t)pc_ > pc_overflow_value) {
error(pc_, nullptr, "reading %d bytes would underflow/overflow", size); errorf(pc_, "reading %d bytes would underflow/overflow", size);
return false; return false;
} else if (pc_ < start_ || end_ < (pc_ + size)) { } else if (pc_ < start_ || end_ < (pc_ + size)) {
error(pc_, nullptr, "expected %d bytes, fell off end", size); errorf(pc_, "expected %d bytes, fell off end", size);
return false; return false;
} else { } else {
return true; return true;
} }
} }
void error(const char* msg) { error(pc_, nullptr, "%s", msg); } void error(const char* msg) { errorf(pc_, "%s", msg); }
void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); } void error(const byte* pc, const char* msg) { errorf(pc, "%s", msg); }
// Sets internal error state. // Sets internal error state.
void PRINTF_FORMAT(4, 5) void PRINTF_FORMAT(3, 4) errorf(const byte* pc, const char* format, ...) {
error(const byte* pc, const byte* pt, const char* format, ...) { // Only report the first error.
if (ok()) { if (!ok()) return;
#if DEBUG #if DEBUG
if (FLAG_wasm_break_on_decoder_error) { if (FLAG_wasm_break_on_decoder_error) {
base::OS::DebugBreak(); base::OS::DebugBreak();
}
#endif
const int kMaxErrorMsg = 256;
char* buffer = new char[kMaxErrorMsg];
va_list arguments;
va_start(arguments, format);
base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
va_end(arguments);
error_msg_.reset(buffer);
error_pc_ = pc;
error_pt_ = pt;
onFirstError();
} }
#endif
const int kMaxErrorMsg = 256;
char* buffer = new char[kMaxErrorMsg];
va_list arguments;
va_start(arguments, format);
base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
va_end(arguments);
error_msg_.reset(buffer);
error_pc_ = pc;
onFirstError();
} }
// Behavior triggered on first error, overridden in subclasses. // Behavior triggered on first error, overridden in subclasses.
virtual void onFirstError() {} virtual void onFirstError() {}
// Debugging helper to print bytes up to the end. // Debugging helper to print bytes up to the end.
template <typename T> template <typename T, bool update_pc>
T traceOffEnd() { T traceOffEnd() {
T t = 0;
for (const byte* ptr = pc_; ptr < end_; ptr++) { for (const byte* ptr = pc_; ptr < end_; ptr++) {
TRACE("%02x ", *ptr); TRACE("%02x ", *ptr);
} }
TRACE("<end>\n"); TRACE("<end>\n");
pc_ = end_; if (update_pc) pc_ = end_;
return t; return T{0};
} }
// Converts the given value to a {Result}, copying the error if necessary. // Converts the given value to a {Result}, copying the error if necessary.
...@@ -268,7 +241,6 @@ class Decoder { ...@@ -268,7 +241,6 @@ class Decoder {
result.error_code = kError; result.error_code = kError;
result.start = start_; result.start = start_;
result.error_pc = error_pc_; result.error_pc = error_pc_;
result.error_pt = error_pt_;
// transfer ownership of the error to the result. // transfer ownership of the error to the result.
result.error_msg.reset(error_msg_.release()); result.error_msg.reset(error_msg_.release());
} else { } else {
...@@ -284,7 +256,6 @@ class Decoder { ...@@ -284,7 +256,6 @@ class Decoder {
pc_ = start; pc_ = start;
end_ = end; end_ = end;
error_pc_ = nullptr; error_pc_ = nullptr;
error_pt_ = nullptr;
error_msg_.reset(); error_msg_.reset();
} }
...@@ -302,104 +273,64 @@ class Decoder { ...@@ -302,104 +273,64 @@ class Decoder {
const byte* pc_; const byte* pc_;
const byte* end_; const byte* end_;
const byte* error_pc_; const byte* error_pc_;
const byte* error_pt_;
std::unique_ptr<char[]> error_msg_; std::unique_ptr<char[]> error_msg_;
private: private:
template <typename IntType, bool is_signed> template <typename IntType, bool advance_pc, bool trace>
IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length, inline IntType checked_read_leb(const byte* pc, unsigned* length,
const char* msg) { const char* name = "varint") {
if (!check(base, offset, 1, msg)) { DCHECK_IMPLIES(advance_pc, pc == pc_);
*length = 0; constexpr bool is_signed = std::is_signed<IntType>::value;
return 0; TRACE_IF(trace, " +%d %-20s: ", static_cast<int>(pc - start_), name);
} constexpr int kMaxLength = (sizeof(IntType) * 8 + 6) / 7;
const byte* ptr = pc;
const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; const byte* end = Min(end_, ptr + kMaxLength);
const byte* ptr = base + offset;
const byte* end = ptr + kMaxLength;
if (end > end_) end = end_;
int shift = 0; int shift = 0;
byte b = 0; byte b = 0;
IntType result = 0; IntType result = 0;
while (ptr < end) { for (;;) {
if (V8_UNLIKELY(ptr >= end)) {
TRACE_IF(trace, "<end> ");
errorf(ptr, "expected %s", name);
break;
}
b = *ptr++; b = *ptr++;
result = result | (static_cast<IntType>(b & 0x7F) << shift); TRACE_IF(trace, "%02x ", b);
if ((b & 0x80) == 0) break; result = result | ((static_cast<IntType>(b) & 0x7F) << shift);
shift += 7; shift += 7;
if ((b & 0x80) == 0) break;
} }
DCHECK_LE(ptr - (base + offset), kMaxLength); DCHECK_LE(ptr - pc, kMaxLength);
*length = static_cast<unsigned>(ptr - (base + offset)); *length = static_cast<unsigned>(ptr - pc);
if (ptr == end) { if (advance_pc) pc_ = ptr;
// Check there are no bits set beyond the bitwidth of {IntType}. if (*length == kMaxLength) {
const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); // A signed-LEB128 must sign-extend the final byte, excluding its
const byte kExtraBitsMask = // most-significant bit; e.g. for a 32-bit LEB128:
static_cast<byte>((0xFF << (8 - kExtraBits)) & 0xFF); // kExtraBits = 4 (== 32 - (5-1) * 7)
int extra_bits_value; // For unsigned values, the extra bits must be all zero.
if (is_signed) { // For signed values, the extra bits *plus* the most significant bit must
// A signed-LEB128 must sign-extend the final byte, excluding its // either be 0, or all ones.
// most-signifcant bit. e.g. for a 32-bit LEB128: constexpr int kExtraBits = (sizeof(IntType) * 8) - ((kMaxLength - 1) * 7);
// kExtraBits = 4 constexpr int kSignExtBits = kExtraBits - (is_signed ? 1 : 0);
// kExtraBitsMask = 0xf0 const byte checked_bits = b & (0xFF << kSignExtBits);
// If b is 0x0f, the value is negative, so extra_bits_value is 0x70. constexpr byte kSignExtendedExtraBits = 0x7f & (0xFF << kSignExtBits);
// If b is 0x03, the value is positive, so extra_bits_value is 0x00. if (checked_bits != 0 &&
extra_bits_value = (static_cast<int8_t>(b << kExtraBits) >> 8) & (!is_signed || checked_bits != kSignExtendedExtraBits)) {
kExtraBitsMask & ~0x80; error(ptr, "extra bits in varint");
} else {
extra_bits_value = 0;
}
if (*length == kMaxLength && (b & kExtraBitsMask) != extra_bits_value) {
error(base, ptr, "extra bits in varint");
return 0;
}
if ((b & 0x80) != 0) {
error(base, ptr, "%s", msg);
return 0; return 0;
} }
} }
return result; if (is_signed && *length < kMaxLength) {
} int sign_ext_shift = 8 * sizeof(IntType) - shift;
// Perform sign extension.
template <typename IntType, bool is_signed> result = (result << sign_ext_shift) >> sign_ext_shift;
IntType consume_leb(const char* name = nullptr) { }
TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_), if (trace && is_signed) {
name ? name : "varint"); TRACE("= %" PRIi64 "\n", static_cast<int64_t>(result));
if (checkAvailable(1)) { } else if (trace) {
const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7; TRACE("= %" PRIu64 "\n", static_cast<uint64_t>(result));
const byte* pos = pc_;
const byte* end = pc_ + kMaxLength;
if (end > end_) end = end_;
IntType result = 0;
int shift = 0;
byte b = 0;
while (pc_ < end) {
b = *pc_++;
TRACE("%02x ", b);
result = result | (static_cast<IntType>(b & 0x7F) << shift);
shift += 7;
if ((b & 0x80) == 0) break;
}
int length = static_cast<int>(pc_ - pos);
if (pc_ == end && (b & 0x80)) {
TRACE("\n");
error(pc_ - 1, "varint too large");
} else if (length == 0) {
TRACE("\n");
error(pc_, "varint of length 0");
} else if (is_signed) {
if (length < kMaxLength) {
int sign_ext_shift = 8 * sizeof(IntType) - shift;
// Perform sign extension.
result = (result << sign_ext_shift) >> sign_ext_shift;
}
TRACE("= %" PRIi64 "\n", static_cast<int64_t>(result));
} else {
TRACE("= %" PRIu64 "\n", static_cast<uint64_t>(result));
}
return result;
} }
return traceOffEnd<uint32_t>(); return result;
} }
}; };
......
...@@ -21,7 +21,7 @@ struct LocalIndexOperand { ...@@ -21,7 +21,7 @@ struct LocalIndexOperand {
unsigned length; unsigned length;
inline LocalIndexOperand(Decoder* decoder, const byte* pc) { inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "local index"); index = decoder->checked_read_u32v(pc + 1, &length, "local index");
type = kWasmStmt; type = kWasmStmt;
} }
}; };
...@@ -30,7 +30,7 @@ struct ImmI32Operand { ...@@ -30,7 +30,7 @@ struct ImmI32Operand {
int32_t value; int32_t value;
unsigned length; unsigned length;
inline ImmI32Operand(Decoder* decoder, const byte* pc) { inline ImmI32Operand(Decoder* decoder, const byte* pc) {
value = decoder->checked_read_i32v(pc, 1, &length, "immi32"); value = decoder->checked_read_i32v(pc + 1, &length, "immi32");
} }
}; };
...@@ -38,7 +38,7 @@ struct ImmI64Operand { ...@@ -38,7 +38,7 @@ struct ImmI64Operand {
int64_t value; int64_t value;
unsigned length; unsigned length;
inline ImmI64Operand(Decoder* decoder, const byte* pc) { inline ImmI64Operand(Decoder* decoder, const byte* pc) {
value = decoder->checked_read_i64v(pc, 1, &length, "immi64"); value = decoder->checked_read_i64v(pc + 1, &length, "immi64");
} }
}; };
...@@ -47,7 +47,7 @@ struct ImmF32Operand { ...@@ -47,7 +47,7 @@ struct ImmF32Operand {
unsigned length; unsigned length;
inline ImmF32Operand(Decoder* decoder, const byte* pc) { inline ImmF32Operand(Decoder* decoder, const byte* pc) {
// Avoid bit_cast because it might not preserve the signalling bit of a NaN. // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
uint32_t tmp = decoder->checked_read_u32(pc, 1, "immf32"); uint32_t tmp = decoder->checked_read_u32(pc + 1, "immf32");
memcpy(&value, &tmp, sizeof(value)); memcpy(&value, &tmp, sizeof(value));
length = 4; length = 4;
} }
...@@ -58,7 +58,7 @@ struct ImmF64Operand { ...@@ -58,7 +58,7 @@ struct ImmF64Operand {
unsigned length; unsigned length;
inline ImmF64Operand(Decoder* decoder, const byte* pc) { inline ImmF64Operand(Decoder* decoder, const byte* pc) {
// Avoid bit_cast because it might not preserve the signalling bit of a NaN. // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
uint64_t tmp = decoder->checked_read_u64(pc, 1, "immf64"); uint64_t tmp = decoder->checked_read_u64(pc + 1, "immf64");
memcpy(&value, &tmp, sizeof(value)); memcpy(&value, &tmp, sizeof(value));
length = 8; length = 8;
} }
...@@ -71,7 +71,7 @@ struct GlobalIndexOperand { ...@@ -71,7 +71,7 @@ struct GlobalIndexOperand {
unsigned length; unsigned length;
inline GlobalIndexOperand(Decoder* decoder, const byte* pc) { inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "global index"); index = decoder->checked_read_u32v(pc + 1, &length, "global index");
global = nullptr; global = nullptr;
type = kWasmStmt; type = kWasmStmt;
} }
...@@ -83,7 +83,7 @@ struct BlockTypeOperand { ...@@ -83,7 +83,7 @@ struct BlockTypeOperand {
unsigned length; unsigned length;
inline BlockTypeOperand(Decoder* decoder, const byte* pc) { inline BlockTypeOperand(Decoder* decoder, const byte* pc) {
uint8_t val = decoder->checked_read_u8(pc, 1, "block type"); uint8_t val = decoder->checked_read_u8(pc + 1, "block type");
ValueType type = kWasmStmt; ValueType type = kWasmStmt;
length = 1; length = 1;
arity = 0; arity = 0;
...@@ -94,16 +94,16 @@ struct BlockTypeOperand { ...@@ -94,16 +94,16 @@ struct BlockTypeOperand {
} else { } else {
// Handle multi-value blocks. // Handle multi-value blocks.
if (!FLAG_wasm_mv_prototype) { if (!FLAG_wasm_mv_prototype) {
decoder->error(pc, pc + 1, "invalid block arity > 1"); decoder->error(pc + 1, "invalid block arity > 1");
return; return;
} }
if (val != kMultivalBlock) { if (val != kMultivalBlock) {
decoder->error(pc, pc + 1, "invalid block type"); decoder->error(pc + 1, "invalid block type");
return; return;
} }
// Decode and check the types vector of the block. // Decode and check the types vector of the block.
unsigned len = 0; unsigned len = 0;
uint32_t count = decoder->checked_read_u32v(pc, 2, &len, "block arity"); uint32_t count = decoder->checked_read_u32v(pc + 2, &len, "block arity");
// {count} is encoded as {arity-2}, so that a {0} count here corresponds // {count} is encoded as {arity-2}, so that a {0} count here corresponds
// to a block with 2 values. This makes invalid/redundant encodings // to a block with 2 values. This makes invalid/redundant encodings
// impossible. // impossible.
...@@ -113,10 +113,10 @@ struct BlockTypeOperand { ...@@ -113,10 +113,10 @@ struct BlockTypeOperand {
for (uint32_t i = 0; i < arity; i++) { for (uint32_t i = 0; i < arity; i++) {
uint32_t offset = 1 + 1 + len + i; uint32_t offset = 1 + 1 + len + i;
val = decoder->checked_read_u8(pc, offset, "block type"); val = decoder->checked_read_u8(pc + offset, "block type");
decode_local_type(val, &type); decode_local_type(val, &type);
if (type == kWasmStmt) { if (type == kWasmStmt) {
decoder->error(pc, pc + offset, "invalid block type"); decoder->error(pc + offset, "invalid block type");
return; return;
} }
} }
...@@ -172,7 +172,7 @@ struct BreakDepthOperand { ...@@ -172,7 +172,7 @@ struct BreakDepthOperand {
Control* target; Control* target;
unsigned length; unsigned length;
inline BreakDepthOperand(Decoder* decoder, const byte* pc) { inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
depth = decoder->checked_read_u32v(pc, 1, &length, "break depth"); depth = decoder->checked_read_u32v(pc + 1, &length, "break depth");
target = nullptr; target = nullptr;
} }
}; };
...@@ -184,11 +184,11 @@ struct CallIndirectOperand { ...@@ -184,11 +184,11 @@ struct CallIndirectOperand {
unsigned length; unsigned length;
inline CallIndirectOperand(Decoder* decoder, const byte* pc) { inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
unsigned len = 0; unsigned len = 0;
index = decoder->checked_read_u32v(pc, 1, &len, "signature index"); index = decoder->checked_read_u32v(pc + 1, &len, "signature index");
table_index = decoder->checked_read_u8(pc, 1 + len, "table index"); table_index = decoder->checked_read_u8(pc + 1 + len, "table index");
if (table_index != 0) { if (table_index != 0) {
decoder->error(pc, pc + 1 + len, "expected table index 0, found %u", decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
table_index); table_index);
} }
length = 1 + len; length = 1 + len;
sig = nullptr; sig = nullptr;
...@@ -200,7 +200,7 @@ struct CallFunctionOperand { ...@@ -200,7 +200,7 @@ struct CallFunctionOperand {
FunctionSig* sig; FunctionSig* sig;
unsigned length; unsigned length;
inline CallFunctionOperand(Decoder* decoder, const byte* pc) { inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u32v(pc, 1, &length, "function index"); index = decoder->checked_read_u32v(pc + 1, &length, "function index");
sig = nullptr; sig = nullptr;
} }
}; };
...@@ -209,9 +209,9 @@ struct MemoryIndexOperand { ...@@ -209,9 +209,9 @@ struct MemoryIndexOperand {
uint32_t index; uint32_t index;
unsigned length; unsigned length;
inline MemoryIndexOperand(Decoder* decoder, const byte* pc) { inline MemoryIndexOperand(Decoder* decoder, const byte* pc) {
index = decoder->checked_read_u8(pc, 1, "memory index"); index = decoder->checked_read_u8(pc + 1, "memory index");
if (index != 0) { if (index != 0) {
decoder->error(pc, pc + 1, "expected memory index 0, found %u", index); decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
} }
length = 1; length = 1;
} }
...@@ -222,10 +222,10 @@ struct BranchTableOperand { ...@@ -222,10 +222,10 @@ struct BranchTableOperand {
const byte* start; const byte* start;
const byte* table; const byte* table;
inline BranchTableOperand(Decoder* decoder, const byte* pc) { inline BranchTableOperand(Decoder* decoder, const byte* pc) {
DCHECK_EQ(kExprBrTable, decoder->checked_read_u8(pc, 0, "opcode")); DCHECK_EQ(kExprBrTable, decoder->checked_read_u8(pc, "opcode"));
start = pc + 1; start = pc + 1;
unsigned len1 = 0; unsigned len1 = 0;
table_count = decoder->checked_read_u32v(pc, 1, &len1, "table count"); table_count = decoder->checked_read_u32v(pc + 1, &len1, "table count");
if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 || if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 ||
len1 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) { len1 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) {
decoder->error(pc, "branch table size overflow"); decoder->error(pc, "branch table size overflow");
...@@ -244,7 +244,7 @@ class BranchTableIterator { ...@@ -244,7 +244,7 @@ class BranchTableIterator {
index_++; index_++;
unsigned length = 0; unsigned length = 0;
uint32_t result = uint32_t result =
decoder_->checked_read_u32v(pc_, 0, &length, "branch table entry"); decoder_->checked_read_u32v(pc_, &length, "branch table entry");
pc_ += length; pc_ += length;
return result; return result;
} }
...@@ -279,15 +279,15 @@ struct MemoryAccessOperand { ...@@ -279,15 +279,15 @@ struct MemoryAccessOperand {
uint32_t max_alignment) { uint32_t max_alignment) {
unsigned alignment_length; unsigned alignment_length;
alignment = alignment =
decoder->checked_read_u32v(pc, 1, &alignment_length, "alignment"); decoder->checked_read_u32v(pc + 1, &alignment_length, "alignment");
if (max_alignment < alignment) { if (max_alignment < alignment) {
decoder->error(pc, pc + 1, decoder->errorf(pc + 1,
"invalid alignment; expected maximum alignment is %u, " "invalid alignment; expected maximum alignment is %u, "
"actual alignment is %u", "actual alignment is %u",
max_alignment, alignment); max_alignment, alignment);
} }
unsigned offset_length; unsigned offset_length;
offset = decoder->checked_read_u32v(pc, 1 + alignment_length, offset = decoder->checked_read_u32v(pc + 1 + alignment_length,
&offset_length, "offset"); &offset_length, "offset");
length = alignment_length + offset_length; length = alignment_length + offset_length;
} }
...@@ -299,7 +299,7 @@ struct SimdLaneOperand { ...@@ -299,7 +299,7 @@ struct SimdLaneOperand {
unsigned length; unsigned length;
inline SimdLaneOperand(Decoder* decoder, const byte* pc) { inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
lane = decoder->checked_read_u8(pc, 2, "lane"); lane = decoder->checked_read_u8(pc + 2, "lane");
length = 1; length = 1;
} }
}; };
...@@ -310,7 +310,7 @@ struct SimdShiftOperand { ...@@ -310,7 +310,7 @@ struct SimdShiftOperand {
unsigned length; unsigned length;
inline SimdShiftOperand(Decoder* decoder, const byte* pc) { inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
shift = decoder->checked_read_u8(pc, 2, "shift"); shift = decoder->checked_read_u8(pc + 2, "shift");
length = 1; length = 1;
} }
}; };
......
...@@ -283,7 +283,7 @@ class WasmDecoder : public Decoder { ...@@ -283,7 +283,7 @@ class WasmDecoder : public Decoder {
} }
return true; return true;
} }
error(pc, pc + 1, "invalid local index: %u", operand.index); errorf(pc + 1, "invalid local index: %u", operand.index);
return false; return false;
} }
...@@ -293,7 +293,7 @@ class WasmDecoder : public Decoder { ...@@ -293,7 +293,7 @@ class WasmDecoder : public Decoder {
operand.type = operand.global->type; operand.type = operand.global->type;
return true; return true;
} }
error(pc, pc + 1, "invalid global index: %u", operand.index); errorf(pc + 1, "invalid global index: %u", operand.index);
return false; return false;
} }
...@@ -309,7 +309,7 @@ class WasmDecoder : public Decoder { ...@@ -309,7 +309,7 @@ class WasmDecoder : public Decoder {
if (Complete(pc, operand)) { if (Complete(pc, operand)) {
return true; return true;
} }
error(pc, pc + 1, "invalid function index: %u", operand.index); errorf(pc + 1, "invalid function index: %u", operand.index);
return false; return false;
} }
...@@ -329,7 +329,7 @@ class WasmDecoder : public Decoder { ...@@ -329,7 +329,7 @@ class WasmDecoder : public Decoder {
if (Complete(pc, operand)) { if (Complete(pc, operand)) {
return true; return true;
} }
error(pc, pc + 1, "invalid signature index: #%u", operand.index); errorf(pc + 1, "invalid signature index: #%u", operand.index);
return false; return false;
} }
...@@ -339,7 +339,7 @@ class WasmDecoder : public Decoder { ...@@ -339,7 +339,7 @@ class WasmDecoder : public Decoder {
operand.target = &control[control.size() - operand.depth - 1]; operand.target = &control[control.size() - operand.depth - 1];
return true; return true;
} }
error(pc, pc + 1, "invalid break depth: %u", operand.depth); errorf(pc + 1, "invalid break depth: %u", operand.depth);
return false; return false;
} }
...@@ -372,7 +372,7 @@ class WasmDecoder : public Decoder { ...@@ -372,7 +372,7 @@ class WasmDecoder : public Decoder {
break; break;
} }
if (operand.lane < 0 || operand.lane >= num_lanes) { if (operand.lane < 0 || operand.lane >= num_lanes) {
error(pc_, pc_ + 2, "invalid lane index"); error(pc_ + 2, "invalid lane index");
return false; return false;
} else { } else {
return true; return true;
...@@ -403,7 +403,7 @@ class WasmDecoder : public Decoder { ...@@ -403,7 +403,7 @@ class WasmDecoder : public Decoder {
break; break;
} }
if (operand.shift < 0 || operand.shift >= max_shift) { if (operand.shift < 0 || operand.shift >= max_shift) {
error(pc_, pc_ + 2, "invalid shift amount"); error(pc_ + 2, "invalid shift amount");
return false; return false;
} else { } else {
return true; return true;
...@@ -478,7 +478,7 @@ class WasmDecoder : public Decoder { ...@@ -478,7 +478,7 @@ class WasmDecoder : public Decoder {
case kExprF64Const: case kExprF64Const:
return 9; return 9;
case kSimdPrefix: { case kSimdPrefix: {
byte simd_index = decoder->checked_read_u8(pc, 1, "simd_index"); byte simd_index = decoder->checked_read_u8(pc + 1, "simd_index");
WasmOpcode opcode = WasmOpcode opcode =
static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index); static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
switch (opcode) { switch (opcode) {
...@@ -548,7 +548,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -548,7 +548,7 @@ class WasmFullDecoder : public WasmDecoder {
// Generate a better error message whether the unterminated control // Generate a better error message whether the unterminated control
// structure is the function body block or an innner structure. // structure is the function body block or an innner structure.
if (control_.size() > 1) { if (control_.size() > 1) {
error(pc_, control_.back().pc, "unterminated control structure"); error(control_.back().pc, "unterminated control structure");
} else { } else {
error("function body must end with \"end\" opcode."); error("function body must end with \"end\" opcode.");
} }
...@@ -840,11 +840,11 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -840,11 +840,11 @@ class WasmFullDecoder : public WasmDecoder {
} }
Control* c = &control_.back(); Control* c = &control_.back();
if (!c->is_if()) { if (!c->is_if()) {
error(pc_, c->pc, "else does not match an if"); error(pc_, "else does not match an if");
break; break;
} }
if (c->false_env == nullptr) { if (c->false_env == nullptr) {
error(pc_, c->pc, "else already present for if"); error(pc_, "else already present for if");
break; break;
} }
FallThruTo(c); FallThruTo(c);
...@@ -901,7 +901,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -901,7 +901,7 @@ class WasmFullDecoder : public WasmDecoder {
if (control_.size() == 1) { if (control_.size() == 1) {
// If at the last (implicit) control, check we are at end. // If at the last (implicit) control, check we are at end.
if (pc_ + 1 != end_) { if (pc_ + 1 != end_) {
error(pc_, pc_ + 1, "trailing code after function end"); error(pc_ + 1, "trailing code after function end");
break; break;
} }
last_end_found_ = true; last_end_found_ = true;
...@@ -992,17 +992,18 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -992,17 +992,18 @@ class WasmFullDecoder : public WasmDecoder {
if (i == 0) { if (i == 0) {
merge = &c->merge; merge = &c->merge;
} else if (merge->arity != c->merge.arity) { } else if (merge->arity != c->merge.arity) {
error(pos, pos, "inconsistent arity in br_table target %d" errorf(pos,
" (previous was %u, this one %u)", "inconsistent arity in br_table target %d"
i, merge->arity, c->merge.arity); " (previous was %u, this one %u)",
i, merge->arity, c->merge.arity);
} else if (control_.back().unreachable) { } else if (control_.back().unreachable) {
for (uint32_t j = 0; ok() && j < merge->arity; ++j) { for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
if ((*merge)[j].type != c->merge[j].type) { if ((*merge)[j].type != c->merge[j].type) {
error(pos, pos, errorf(pos,
"type error in br_table target %d operand %d" "type error in br_table target %d operand %d"
" (previous expected %s, this one %s)", i, j, " (previous expected %s, this one %s)",
WasmOpcodes::TypeName((*merge)[j].type), i, j, WasmOpcodes::TypeName((*merge)[j].type),
WasmOpcodes::TypeName(c->merge[j].type)); WasmOpcodes::TypeName(c->merge[j].type));
} }
} }
} }
...@@ -1108,8 +1109,8 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1108,8 +1109,8 @@ class WasmFullDecoder : public WasmDecoder {
Value val = Pop(0, operand.type); Value val = Pop(0, operand.type);
BUILD(SetGlobal, operand.index, val.node); BUILD(SetGlobal, operand.index, val.node);
} else { } else {
error(pc_, pc_ + 1, "immutable global #%u cannot be assigned", errorf(pc_, "immutable global #%u cannot be assigned",
operand.index); operand.index);
} }
} }
len = 1 + operand.length; len = 1 + operand.length;
...@@ -1239,7 +1240,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1239,7 +1240,7 @@ class WasmFullDecoder : public WasmDecoder {
case kSimdPrefix: { case kSimdPrefix: {
CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
len++; len++;
byte simd_index = checked_read_u8(pc_, 1, "simd index"); byte simd_index = checked_read_u8(pc_ + 1, "simd index");
opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
TRACE(" @%-4d #%-20s|", startrel(pc_), TRACE(" @%-4d #%-20s|", startrel(pc_),
WasmOpcodes::OpcodeName(opcode)); WasmOpcodes::OpcodeName(opcode));
...@@ -1256,7 +1257,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1256,7 +1257,7 @@ class WasmFullDecoder : public WasmDecoder {
break; break;
} }
len = 2; len = 2;
byte atomic_opcode = checked_read_u8(pc_, 1, "atomic index"); byte atomic_opcode = checked_read_u8(pc_ + 1, "atomic index");
opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode); opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode);
sig = WasmOpcodes::AtomicSignature(opcode); sig = WasmOpcodes::AtomicSignature(opcode);
if (sig) { if (sig) {
...@@ -1575,9 +1576,9 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1575,9 +1576,9 @@ class WasmFullDecoder : public WasmDecoder {
Value Pop(int index, ValueType expected) { Value Pop(int index, ValueType expected) {
Value val = Pop(); Value val = Pop();
if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) { if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
} }
return val; return val;
} }
...@@ -1588,7 +1589,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1588,7 +1589,7 @@ class WasmFullDecoder : public WasmDecoder {
// Popping past the current control start in reachable code. // Popping past the current control start in reachable code.
Value val = {pc_, nullptr, kWasmVar}; Value val = {pc_, nullptr, kWasmVar};
if (!control_.back().unreachable) { if (!control_.back().unreachable) {
error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); errorf(pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
} }
return val; return val;
} }
...@@ -1612,8 +1613,8 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1612,8 +1613,8 @@ class WasmFullDecoder : public WasmDecoder {
// Merge the value(s) into the end of the block. // Merge the value(s) into the end of the block.
size_t expected = control_.back().stack_depth + c->merge.arity; size_t expected = control_.back().stack_depth + c->merge.arity;
if (stack_.size() < expected && !control_.back().unreachable) { if (stack_.size() < expected && !control_.back().unreachable) {
error( errorf(
pc_, pc_, pc_,
"expected at least %u values on the stack for br to @%d, found %d", "expected at least %u values on the stack for br to @%d, found %d",
c->merge.arity, startrel(c->pc), c->merge.arity, startrel(c->pc),
static_cast<int>(stack_.size() - c->stack_depth)); static_cast<int>(stack_.size() - c->stack_depth));
...@@ -1633,8 +1634,8 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1633,8 +1634,8 @@ class WasmFullDecoder : public WasmDecoder {
c->unreachable = false; c->unreachable = false;
return; return;
} }
error(pc_, pc_, "expected %u elements on the stack for fallthru to @%d", errorf(pc_, "expected %u elements on the stack for fallthru to @%d",
c->merge.arity, startrel(c->pc)); c->merge.arity, startrel(c->pc));
} }
inline Value& GetMergeValueFromStack(Control* c, size_t i) { inline Value& GetMergeValueFromStack(Control* c, size_t i) {
...@@ -1647,8 +1648,8 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1647,8 +1648,8 @@ class WasmFullDecoder : public WasmDecoder {
int arity = static_cast<int>(c->merge.arity); int arity = static_cast<int>(c->merge.arity);
if (c->stack_depth + arity < stack_.size() || if (c->stack_depth + arity < stack_.size() ||
(c->stack_depth + arity != stack_.size() && !c->unreachable)) { (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", errorf(pc_, "expected %d elements on the stack for fallthru to @%d",
arity, startrel(c->pc)); arity, startrel(c->pc));
return; return;
} }
// Typecheck the values left on the stack. // Typecheck the values left on the stack.
...@@ -1658,8 +1659,9 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1658,8 +1659,9 @@ class WasmFullDecoder : public WasmDecoder {
Value& val = GetMergeValueFromStack(c, i); Value& val = GetMergeValueFromStack(c, i);
Value& old = c->merge[i]; Value& old = c->merge[i];
if (val.type != old.type) { if (val.type != old.type) {
error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); WasmOpcodes::TypeName(old.type),
WasmOpcodes::TypeName(val.type));
return; return;
} }
} }
...@@ -1677,8 +1679,9 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1677,8 +1679,9 @@ class WasmFullDecoder : public WasmDecoder {
Value& val = GetMergeValueFromStack(c, i); Value& val = GetMergeValueFromStack(c, i);
Value& old = c->merge[i]; Value& old = c->merge[i];
if (val.type != old.type && val.type != kWasmVar) { if (val.type != old.type && val.type != kWasmVar) {
error(pc_, pc_, "type error in merge[%zu] (expected %s, got %s)", i, errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type)); WasmOpcodes::TypeName(old.type),
WasmOpcodes::TypeName(val.type));
return; return;
} }
if (builder_ && reachable) { if (builder_ && reachable) {
......
...@@ -170,8 +170,7 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) { ...@@ -170,8 +170,7 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) {
} }
WasmOpcode current() { WasmOpcode current() {
return static_cast<WasmOpcode>( return static_cast<WasmOpcode>(checked_read_u8(pc_, "expected bytecode"));
checked_read_u8(pc_, 0, "expected bytecode"));
} }
void next() { void next() {
......
...@@ -127,11 +127,11 @@ class WasmSectionIterator { ...@@ -127,11 +127,11 @@ class WasmSectionIterator {
void advance() { void advance() {
if (decoder_.pc() != section_end_) { if (decoder_.pc() != section_end_) {
const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer"; const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
decoder_.error(decoder_.pc(), decoder_.pc(), decoder_.errorf(decoder_.pc(),
"section was %s than expected size " "section was %s than expected size "
"(%u bytes expected, %zu decoded)", "(%u bytes expected, %zu decoded)",
msg, section_length(), msg, section_length(),
static_cast<size_t>(decoder_.pc() - section_start_)); static_cast<size_t>(decoder_.pc() - section_start_));
} }
next(); next();
} }
...@@ -188,8 +188,8 @@ class WasmSectionIterator { ...@@ -188,8 +188,8 @@ class WasmSectionIterator {
section_code = kUnknownSectionCode; section_code = kUnknownSectionCode;
} }
} else if (!IsValidSectionCode(section_code)) { } else if (!IsValidSectionCode(section_code)) {
decoder_.error(decoder_.pc(), decoder_.pc(), decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
"unknown section code #0x%02x", section_code); section_code);
section_code = kUnknownSectionCode; section_code = kUnknownSectionCode;
} }
section_code_ = static_cast<WasmSectionCode>(section_code); section_code_ = static_cast<WasmSectionCode>(section_code);
...@@ -265,20 +265,20 @@ class ModuleDecoder : public Decoder { ...@@ -265,20 +265,20 @@ class ModuleDecoder : public Decoder {
uint32_t magic_word = consume_u32("wasm magic"); uint32_t magic_word = consume_u32("wasm magic");
#define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
if (magic_word != kWasmMagic) { if (magic_word != kWasmMagic) {
error(pos, pos, errorf(pos,
"expected magic word %02x %02x %02x %02x, " "expected magic word %02x %02x %02x %02x, "
"found %02x %02x %02x %02x", "found %02x %02x %02x %02x",
BYTES(kWasmMagic), BYTES(magic_word)); BYTES(kWasmMagic), BYTES(magic_word));
} }
pos = pc_; pos = pc_;
{ {
uint32_t magic_version = consume_u32("wasm version"); uint32_t magic_version = consume_u32("wasm version");
if (magic_version != kWasmVersion) { if (magic_version != kWasmVersion) {
error(pos, pos, errorf(pos,
"expected version %02x %02x %02x %02x, " "expected version %02x %02x %02x %02x, "
"found %02x %02x %02x %02x", "found %02x %02x %02x %02x",
BYTES(kWasmVersion), BYTES(magic_version)); BYTES(kWasmVersion), BYTES(magic_version));
} }
} }
...@@ -379,7 +379,7 @@ class ModuleDecoder : public Decoder { ...@@ -379,7 +379,7 @@ class ModuleDecoder : public Decoder {
break; break;
} }
default: default:
error(pos, pos, "unknown import kind 0x%02x", import->kind); errorf(pos, "unknown import kind 0x%02x", import->kind);
break; break;
} }
} }
...@@ -515,7 +515,7 @@ class ModuleDecoder : public Decoder { ...@@ -515,7 +515,7 @@ class ModuleDecoder : public Decoder {
break; break;
} }
default: default:
error(pos, pos, "invalid export kind 0x%02x", exp->kind); errorf(pos, "invalid export kind 0x%02x", exp->kind);
break; break;
} }
} }
...@@ -539,9 +539,8 @@ class ModuleDecoder : public Decoder { ...@@ -539,9 +539,8 @@ class ModuleDecoder : public Decoder {
DCHECK(!cmp_less(*it, *last)); // Vector must be sorted. DCHECK(!cmp_less(*it, *last)); // Vector must be sorted.
if (!cmp_less(*last, *it)) { if (!cmp_less(*last, *it)) {
const byte* pc = start_ + it->name_offset; const byte* pc = start_ + it->name_offset;
error(pc, pc, errorf(pc, "Duplicate export name '%.*s' for functions %d and %d",
"Duplicate export name '%.*s' for functions %d and %d", it->name_length, pc, last->index, it->index);
it->name_length, pc, last->index, it->index);
break; break;
} }
} }
...@@ -570,11 +569,11 @@ class ModuleDecoder : public Decoder { ...@@ -570,11 +569,11 @@ class ModuleDecoder : public Decoder {
const byte* pos = pc(); const byte* pos = pc();
uint32_t table_index = consume_u32v("table index"); uint32_t table_index = consume_u32v("table index");
if (table_index != 0) { if (table_index != 0) {
error(pos, pos, "illegal table index %u != 0", table_index); errorf(pos, "illegal table index %u != 0", table_index);
} }
WasmIndirectFunctionTable* table = nullptr; WasmIndirectFunctionTable* table = nullptr;
if (table_index >= module->function_tables.size()) { if (table_index >= module->function_tables.size()) {
error(pos, pos, "out of bounds table index %u", table_index); errorf(pos, "out of bounds table index %u", table_index);
break; break;
} }
table = &module->function_tables[table_index]; table = &module->function_tables[table_index];
...@@ -604,8 +603,8 @@ class ModuleDecoder : public Decoder { ...@@ -604,8 +603,8 @@ class ModuleDecoder : public Decoder {
const byte* pos = pc_; const byte* pos = pc_;
uint32_t functions_count = consume_u32v("functions count"); uint32_t functions_count = consume_u32v("functions count");
if (functions_count != module->num_declared_functions) { if (functions_count != module->num_declared_functions) {
error(pos, pos, "function body count %u mismatch (%u expected)", errorf(pos, "function body count %u mismatch (%u expected)",
functions_count, module->num_declared_functions); functions_count, module->num_declared_functions);
} }
for (uint32_t i = 0; ok() && i < functions_count; ++i) { for (uint32_t i = 0; ok() && i < functions_count; ++i) {
WasmFunction* function = WasmFunction* function =
...@@ -677,8 +676,8 @@ class ModuleDecoder : public Decoder { ...@@ -677,8 +676,8 @@ class ModuleDecoder : public Decoder {
// ===== Remaining sections ============================================== // ===== Remaining sections ==============================================
if (section_iter.more() && ok()) { if (section_iter.more() && ok()) {
error(pc(), pc(), "unexpected section: %s", errorf(pc(), "unexpected section: %s",
SectionName(section_iter.section_code())); SectionName(section_iter.section_code()));
} }
if (ok()) { if (ok()) {
...@@ -760,25 +759,25 @@ class ModuleDecoder : public Decoder { ...@@ -760,25 +759,25 @@ class ModuleDecoder : public Decoder {
case WasmInitExpr::kGlobalIndex: { case WasmInitExpr::kGlobalIndex: {
uint32_t other_index = global->init.val.global_index; uint32_t other_index = global->init.val.global_index;
if (other_index >= index) { if (other_index >= index) {
error(pos, pos, errorf(pos,
"invalid global index in init expression, " "invalid global index in init expression, "
"index %u, other_index %u", "index %u, other_index %u",
index, other_index); index, other_index);
} else if (module->globals[other_index].type != global->type) { } else if (module->globals[other_index].type != global->type) {
error(pos, pos, errorf(pos,
"type mismatch in global initialization " "type mismatch in global initialization "
"(from global #%u), expected %s, got %s", "(from global #%u), expected %s, got %s",
other_index, WasmOpcodes::TypeName(global->type), other_index, WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(module->globals[other_index].type)); WasmOpcodes::TypeName(module->globals[other_index].type));
} }
break; break;
} }
default: default:
if (global->type != TypeOf(module, global->init)) { if (global->type != TypeOf(module, global->init)) {
error(pos, pos, errorf(pos,
"type error in global initialization, expected %s, got %s", "type error in global initialization, expected %s, got %s",
WasmOpcodes::TypeName(global->type), WasmOpcodes::TypeName(global->type),
WasmOpcodes::TypeName(TypeOf(module, global->init))); WasmOpcodes::TypeName(TypeOf(module, global->init)));
} }
} }
} }
...@@ -881,8 +880,8 @@ class ModuleDecoder : public Decoder { ...@@ -881,8 +880,8 @@ class ModuleDecoder : public Decoder {
const byte* pos = pc_; const byte* pos = pc_;
uint32_t sig_index = consume_u32v("signature index"); uint32_t sig_index = consume_u32v("signature index");
if (sig_index >= module->signatures.size()) { if (sig_index >= module->signatures.size()) {
error(pos, pos, "signature index %u out of bounds (%d signatures)", errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
sig_index, static_cast<int>(module->signatures.size())); static_cast<int>(module->signatures.size()));
*sig = nullptr; *sig = nullptr;
return 0; return 0;
} }
...@@ -894,8 +893,7 @@ class ModuleDecoder : public Decoder { ...@@ -894,8 +893,7 @@ class ModuleDecoder : public Decoder {
const byte* p = pc_; const byte* p = pc_;
uint32_t count = consume_u32v(name); uint32_t count = consume_u32v(name);
if (count > maximum) { if (count > maximum) {
error(p, p, "%s of %u exceeds internal limit of %zu", name, count, errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
maximum);
return static_cast<uint32_t>(maximum); return static_cast<uint32_t>(maximum);
} }
return count; return count;
...@@ -919,8 +917,8 @@ class ModuleDecoder : public Decoder { ...@@ -919,8 +917,8 @@ class ModuleDecoder : public Decoder {
const byte* pos = pc_; const byte* pos = pc_;
uint32_t index = consume_u32v(name); uint32_t index = consume_u32v(name);
if (index >= vector.size()) { if (index >= vector.size()) {
error(pos, pos, "%s %u out of bounds (%d entries)", name, index, errorf(pos, "%s %u out of bounds (%d entries)", name, index,
static_cast<int>(vector.size())); static_cast<int>(vector.size()));
*ptr = nullptr; *ptr = nullptr;
return 0; return 0;
} }
...@@ -937,23 +935,23 @@ class ModuleDecoder : public Decoder { ...@@ -937,23 +935,23 @@ class ModuleDecoder : public Decoder {
*initial = consume_u32v("initial size"); *initial = consume_u32v("initial size");
*has_max = false; *has_max = false;
if (*initial > max_initial) { if (*initial > max_initial) {
error(pos, pos, errorf(pos,
"initial %s size (%u %s) is larger than implementation limit (%u)", "initial %s size (%u %s) is larger than implementation limit (%u)",
name, *initial, units, max_initial); name, *initial, units, max_initial);
} }
if (flags & 1) { if (flags & 1) {
*has_max = true; *has_max = true;
pos = pc(); pos = pc();
*maximum = consume_u32v("maximum size"); *maximum = consume_u32v("maximum size");
if (*maximum > max_maximum) { if (*maximum > max_maximum) {
error( errorf(
pos, pos, pos,
"maximum %s size (%u %s) is larger than implementation limit (%u)", "maximum %s size (%u %s) is larger than implementation limit (%u)",
name, *maximum, units, max_maximum); name, *maximum, units, max_maximum);
} }
if (*maximum < *initial) { if (*maximum < *initial) {
error(pos, pos, "maximum %s size (%u %s) is less than initial (%u %s)", errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
name, *maximum, units, *initial, units); name, *maximum, units, *initial, units);
} }
} else { } else {
*has_max = false; *has_max = false;
...@@ -965,7 +963,7 @@ class ModuleDecoder : public Decoder { ...@@ -965,7 +963,7 @@ class ModuleDecoder : public Decoder {
const byte* pos = pc(); const byte* pos = pc();
uint8_t value = consume_u8(name); uint8_t value = consume_u8(name);
if (value != expected) { if (value != expected) {
error(pos, pos, "expected %s 0x%02x, got 0x%02x", name, expected, value); errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
return false; return false;
} }
return true; return true;
...@@ -1038,9 +1036,9 @@ class ModuleDecoder : public Decoder { ...@@ -1038,9 +1036,9 @@ class ModuleDecoder : public Decoder {
expr.kind = WasmInitExpr::kNone; expr.kind = WasmInitExpr::kNone;
} }
if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) { if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
error(pos, pos, "type error in init expression, expected %s, got %s", errorf(pos, "type error in init expression, expected %s, got %s",
WasmOpcodes::TypeName(expected), WasmOpcodes::TypeName(expected),
WasmOpcodes::TypeName(TypeOf(module, expr))); WasmOpcodes::TypeName(TypeOf(module, expr)));
} }
return expr; return expr;
} }
......
...@@ -40,7 +40,6 @@ struct Result { ...@@ -40,7 +40,6 @@ struct Result {
ErrorCode error_code; ErrorCode error_code;
const byte* start; const byte* start;
const byte* error_pc; const byte* error_pc;
const byte* error_pt;
std::unique_ptr<char[]> error_msg; std::unique_ptr<char[]> error_msg;
bool ok() const { return error_code == kSuccess; } bool ok() const { return error_code == kSuccess; }
...@@ -51,7 +50,6 @@ struct Result { ...@@ -51,7 +50,6 @@ struct Result {
error_code = that.error_code; error_code = that.error_code;
start = that.start; start = that.start;
error_pc = that.error_pc; error_pc = that.error_pc;
error_pt = that.error_pt;
error_msg = std::move(that.error_msg); error_msg = std::move(that.error_msg);
} }
......
...@@ -387,11 +387,9 @@ inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module, ...@@ -387,11 +387,9 @@ inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
} }
ptrdiff_t pc = result.error_pc - result.start; ptrdiff_t pc = result.error_pc - result.start;
ptrdiff_t pt = result.error_pt - result.start;
std::ostringstream str; std::ostringstream str;
str << "Verification failed: " << result.error_code << " pc = +" << pc; str << "Verification failed: " << result.error_code << " pc = +" << pc
if (result.error_pt) str << ", pt = +" << pt; << ", msg = " << result.error_msg.get();
str << ", msg = " << result.error_msg.get();
FATAL(str.str().c_str()); FATAL(str.str().c_str());
} }
builder.Int64LoweringForTesting(); builder.Int64LoweringForTesting();
......
...@@ -25,7 +25,7 @@ class DecoderTest : public TestWithZone { ...@@ -25,7 +25,7 @@ class DecoderTest : public TestWithZone {
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
unsigned length; \ unsigned length; \
EXPECT_EQ(static_cast<uint32_t>(expected), \ EXPECT_EQ(static_cast<uint32_t>(expected), \
decoder.checked_read_u32v(decoder.start(), 0, &length)); \ decoder.checked_read_u32v(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \ EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
EXPECT_EQ(data, decoder.pc()); \ EXPECT_EQ(data, decoder.pc()); \
EXPECT_TRUE(decoder.ok()); \ EXPECT_TRUE(decoder.ok()); \
...@@ -33,38 +33,36 @@ class DecoderTest : public TestWithZone { ...@@ -33,38 +33,36 @@ class DecoderTest : public TestWithZone {
EXPECT_EQ(data + expected_length, decoder.pc()); \ EXPECT_EQ(data + expected_length, decoder.pc()); \
} while (false) } while (false)
#define CHECK_INT32V_INLINE(expected, expected_length, ...) \ #define CHECK_INT32V_INLINE(expected, expected_length, ...) \
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
unsigned length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, decoder.checked_read_i32v(decoder.start(), &length)); \
decoder.checked_read_i32v(decoder.start(), 0, &length)); \ EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \ EXPECT_EQ(data, decoder.pc()); \
EXPECT_EQ(data, decoder.pc()); \ EXPECT_TRUE(decoder.ok()); \
EXPECT_TRUE(decoder.ok()); \ EXPECT_EQ(expected, decoder.consume_i32v()); \
EXPECT_EQ(expected, decoder.consume_i32v()); \ EXPECT_EQ(data + expected_length, decoder.pc()); \
EXPECT_EQ(data + expected_length, decoder.pc()); \
} while (false) } while (false)
#define CHECK_UINT64V_INLINE(expected, expected_length, ...) \ #define CHECK_UINT64V_INLINE(expected, expected_length, ...) \
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
unsigned length; \ unsigned length; \
EXPECT_EQ(static_cast<uint64_t>(expected), \ EXPECT_EQ(static_cast<uint64_t>(expected), \
decoder.checked_read_u64v(decoder.start(), 0, &length)); \ decoder.checked_read_u64v(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \ EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
} while (false) } while (false)
#define CHECK_INT64V_INLINE(expected, expected_length, ...) \ #define CHECK_INT64V_INLINE(expected, expected_length, ...) \
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
unsigned length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, decoder.checked_read_i64v(decoder.start(), &length)); \
decoder.checked_read_i64v(decoder.start(), 0, &length)); \ EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
} while (false) } while (false)
TEST_F(DecoderTest, ReadU32v_OneByte) { TEST_F(DecoderTest, ReadU32v_OneByte) {
...@@ -376,7 +374,7 @@ TEST_F(DecoderTest, ReadU32v_off_end1) { ...@@ -376,7 +374,7 @@ TEST_F(DecoderTest, ReadU32v_off_end1) {
static const byte data[] = {U32V_1(11)}; static const byte data[] = {U32V_1(11)};
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data); decoder.Reset(data, data);
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(0u, length); EXPECT_EQ(0u, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -386,7 +384,7 @@ TEST_F(DecoderTest, ReadU32v_off_end2) { ...@@ -386,7 +384,7 @@ TEST_F(DecoderTest, ReadU32v_off_end2) {
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + i); decoder.Reset(data, data + i);
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -397,7 +395,7 @@ TEST_F(DecoderTest, ReadU32v_off_end3) { ...@@ -397,7 +395,7 @@ TEST_F(DecoderTest, ReadU32v_off_end3) {
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + i); decoder.Reset(data, data + i);
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -408,7 +406,7 @@ TEST_F(DecoderTest, ReadU32v_off_end4) { ...@@ -408,7 +406,7 @@ TEST_F(DecoderTest, ReadU32v_off_end4) {
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + i); decoder.Reset(data, data + i);
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -419,7 +417,7 @@ TEST_F(DecoderTest, ReadU32v_off_end5) { ...@@ -419,7 +417,7 @@ TEST_F(DecoderTest, ReadU32v_off_end5) {
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + i); decoder.Reset(data, data + i);
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -431,7 +429,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) { ...@@ -431,7 +429,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) {
data[4] = static_cast<byte>(i << 4); data[4] = static_cast<byte>(i << 4);
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_u32v(decoder.start(), 0, &length); decoder.checked_read_u32v(decoder.start(), &length);
EXPECT_EQ(5u, length); EXPECT_EQ(5u, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -442,7 +440,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_negative) { ...@@ -442,7 +440,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_negative) {
unsigned length = 0; unsigned length = 0;
byte data[] = {0xff, 0xff, 0xff, 0xff, 0x7f}; byte data[] = {0xff, 0xff, 0xff, 0xff, 0x7f};
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_i32v(decoder.start(), 0, &length); decoder.checked_read_i32v(decoder.start(), &length);
EXPECT_EQ(5u, length); EXPECT_EQ(5u, length);
EXPECT_TRUE(decoder.ok()); EXPECT_TRUE(decoder.ok());
} }
...@@ -452,7 +450,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_positive) { ...@@ -452,7 +450,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_positive) {
unsigned length = 0; unsigned length = 0;
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x77}; byte data[] = {0x80, 0x80, 0x80, 0x80, 0x77};
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_i32v(decoder.start(), 0, &length); decoder.checked_read_i32v(decoder.start(), &length);
EXPECT_EQ(5u, length); EXPECT_EQ(5u, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -487,7 +485,7 @@ TEST_F(DecoderTest, ReadU32v_Bits) { ...@@ -487,7 +485,7 @@ TEST_F(DecoderTest, ReadU32v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) { for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
unsigned rlen; unsigned rlen;
uint32_t result = decoder.checked_read_u32v(data, 0, &rlen); uint32_t result = decoder.checked_read_u32v(data, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} else { } else {
...@@ -543,7 +541,7 @@ TEST_F(DecoderTest, ReadU64v_PowerOf2) { ...@@ -543,7 +541,7 @@ TEST_F(DecoderTest, ReadU64v_PowerOf2) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) { for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
unsigned length; unsigned length;
uint64_t result = decoder.checked_read_u64v(data, 0, &length); uint64_t result = decoder.checked_read_u64v(data, &length);
if (limit <= index) { if (limit <= index) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} else { } else {
...@@ -584,7 +582,7 @@ TEST_F(DecoderTest, ReadU64v_Bits) { ...@@ -584,7 +582,7 @@ TEST_F(DecoderTest, ReadU64v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) { for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
unsigned rlen; unsigned rlen;
uint64_t result = decoder.checked_read_u64v(data, 0, &rlen); uint64_t result = decoder.checked_read_u64v(data, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} else { } else {
...@@ -626,7 +624,7 @@ TEST_F(DecoderTest, ReadI64v_Bits) { ...@@ -626,7 +624,7 @@ TEST_F(DecoderTest, ReadI64v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) { for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
unsigned rlen; unsigned rlen;
int64_t result = decoder.checked_read_i64v(data, 0, &rlen); int64_t result = decoder.checked_read_i64v(data, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} else { } else {
...@@ -645,7 +643,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) { ...@@ -645,7 +643,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) {
data[9] = static_cast<byte>(i << 1); data[9] = static_cast<byte>(i << 1);
unsigned length = 0; unsigned length = 0;
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_u64v(decoder.start(), 0, &length); decoder.checked_read_u64v(decoder.start(), &length);
EXPECT_EQ(10u, length); EXPECT_EQ(10u, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
...@@ -656,7 +654,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_negative) { ...@@ -656,7 +654,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_negative) {
unsigned length = 0; unsigned length = 0;
byte data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; byte data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_i64v(decoder.start(), 0, &length); decoder.checked_read_i64v(decoder.start(), &length);
EXPECT_EQ(10u, length); EXPECT_EQ(10u, length);
EXPECT_TRUE(decoder.ok()); EXPECT_TRUE(decoder.ok());
} }
...@@ -666,7 +664,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_positive) { ...@@ -666,7 +664,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_positive) {
unsigned length = 0; unsigned length = 0;
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x77}; byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x77};
decoder.Reset(data, data + sizeof(data)); decoder.Reset(data, data + sizeof(data));
decoder.checked_read_i64v(decoder.start(), 0, &length); decoder.checked_read_i64v(decoder.start(), &length);
EXPECT_EQ(10u, length); EXPECT_EQ(10u, length);
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
} }
......
...@@ -137,18 +137,15 @@ class FunctionBodyDecoderTest : public TestWithZone { ...@@ -137,18 +137,15 @@ class FunctionBodyDecoderTest : public TestWithZone {
if (result.error_code != expected) { if (result.error_code != expected) {
ptrdiff_t pc = result.error_pc - result.start; ptrdiff_t pc = result.error_pc - result.start;
ptrdiff_t pt = result.error_pt - result.start;
std::ostringstream str; std::ostringstream str;
if (expected == kSuccess) { if (expected == kSuccess) {
str << "Verification failed: " << result.error_code << " pc = +" << pc; str << "Verification failed: " << result.error_code << " pc = +" << pc
if (result.error_pt) str << ", pt = +" << pt; << ", msg = " << result.error_msg.get();
str << ", msg = " << result.error_msg.get();
} else { } else {
str << "Verification expected: " << expected << ", but got " str << "Verification expected: " << expected << ", but got "
<< result.error_code; << result.error_code;
if (result.error_code != kSuccess) { if (result.error_code != kSuccess) {
str << " pc = +" << pc; str << " pc = +" << pc;
if (result.error_pt) str << ", pt = +" << pt;
} }
} }
EXPECT_TRUE(false) << str.str().c_str(); EXPECT_TRUE(false) << str.str().c_str();
......
...@@ -92,13 +92,13 @@ TEST_F(LEBHelperTest, sizeof_i32v) { ...@@ -92,13 +92,13 @@ TEST_F(LEBHelperTest, sizeof_i32v) {
static void CheckEncodeDecode_##name(ctype val) { \ static void CheckEncodeDecode_##name(ctype val) { \
static const int kSize = 16; \ static const int kSize = 16; \
static byte buffer[kSize]; \ static byte buffer[kSize]; \
byte *ptr = buffer; \ byte* ptr = buffer; \
LEBHelper::write_##name(&ptr, val); \ LEBHelper::write_##name(&ptr, val); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), \ EXPECT_EQ(LEBHelper::sizeof_##name(val), \
static_cast<size_t>(ptr - buffer)); \ static_cast<size_t>(ptr - buffer)); \
Decoder decoder(buffer, buffer + kSize); \ Decoder decoder(buffer, buffer + kSize); \
unsigned length = 0; \ unsigned length = 0; \
ctype result = decoder.checked_read_##name(buffer, 0, &length); \ ctype result = decoder.checked_read_##name(buffer, &length); \
EXPECT_EQ(val, result); \ EXPECT_EQ(val, result); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \ EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
} }
......
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