Commit fd2bf837 authored by ddchen's avatar ddchen Committed by Commit bot

[wasm] improve handling of malformed inputs

When reading malformed input, the length of variable-length types can be very large. Computing operand length with this and adding it to PC will overflow and screw up decode.

This patch switches to unsigned int for arity and lengths, terminates loop analysis on error, adds overflow checking to BranchTableOperand, and adds a unit test.

Review-Url: https://codereview.chromium.org/2052623003
Cr-Commit-Position: refs/heads/master@{#37301}
parent ea844f9a
...@@ -259,7 +259,7 @@ class WasmDecoder : public Decoder { ...@@ -259,7 +259,7 @@ class WasmDecoder : public Decoder {
return true; return true;
} }
int OpcodeArity(const byte* pc) { unsigned OpcodeArity(const byte* pc) {
#define DECLARE_ARITY(name, ...) \ #define DECLARE_ARITY(name, ...) \
static const LocalType kTypes_##name[] = {__VA_ARGS__}; \ static const LocalType kTypes_##name[] = {__VA_ARGS__}; \
static const int kArity_##name = \ static const int kArity_##name = \
...@@ -340,7 +340,7 @@ class WasmDecoder : public Decoder { ...@@ -340,7 +340,7 @@ class WasmDecoder : public Decoder {
} }
} }
int OpcodeLength(const byte* pc) { unsigned OpcodeLength(const byte* pc) {
switch (static_cast<WasmOpcode>(*pc)) { switch (static_cast<WasmOpcode>(*pc)) {
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
...@@ -621,7 +621,7 @@ class SR_WasmDecoder : public WasmDecoder { ...@@ -621,7 +621,7 @@ class SR_WasmDecoder : public WasmDecoder {
if (pc_ >= limit_) return; // Nothing to do. if (pc_ >= limit_) return; // Nothing to do.
while (true) { // decoding loop. while (true) { // decoding loop.
int len = 1; unsigned len = 1;
WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
TRACE(" @%-6d #%02x:%-20s|", startrel(pc_), opcode, TRACE(" @%-6d #%02x:%-20s|", startrel(pc_), opcode,
WasmOpcodes::ShortOpcodeName(opcode)); WasmOpcodes::ShortOpcodeName(opcode));
...@@ -1455,9 +1455,9 @@ class SR_WasmDecoder : public WasmDecoder { ...@@ -1455,9 +1455,9 @@ class SR_WasmDecoder : public WasmDecoder {
new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_); new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_);
int depth = 0; int depth = 0;
// Iteratively process all AST nodes nested inside the loop. // Iteratively process all AST nodes nested inside the loop.
while (pc < limit_) { while (pc < limit_ && ok()) {
WasmOpcode opcode = static_cast<WasmOpcode>(*pc); WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
int length = 1; unsigned length = 1;
switch (opcode) { switch (opcode) {
case kExprLoop: case kExprLoop:
case kExprIf: case kExprIf:
...@@ -1485,7 +1485,7 @@ class SR_WasmDecoder : public WasmDecoder { ...@@ -1485,7 +1485,7 @@ class SR_WasmDecoder : public WasmDecoder {
if (depth <= 0) break; if (depth <= 0) break;
pc += length; pc += length;
} }
return assigned; return ok() ? assigned : nullptr;
} }
inline wasm::WasmCodePosition position() { inline wasm::WasmCodePosition position() {
...@@ -1535,12 +1535,12 @@ std::ostream& operator<<(std::ostream& os, const Tree& tree) { ...@@ -1535,12 +1535,12 @@ std::ostream& operator<<(std::ostream& os, const Tree& tree) {
return os; return os;
} }
int OpcodeLength(const byte* pc, const byte* end) { unsigned OpcodeLength(const byte* pc, const byte* end) {
WasmDecoder decoder(nullptr, nullptr, pc, end); WasmDecoder decoder(nullptr, nullptr, pc, end);
return decoder.OpcodeLength(pc); return decoder.OpcodeLength(pc);
} }
int OpcodeArity(const byte* pc, const byte* end) { unsigned OpcodeArity(const byte* pc, const byte* end) {
WasmDecoder decoder(nullptr, nullptr, pc, end); WasmDecoder decoder(nullptr, nullptr, pc, end);
return decoder.OpcodeArity(pc); return decoder.OpcodeArity(pc);
} }
...@@ -1588,7 +1588,7 @@ bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, ...@@ -1588,7 +1588,7 @@ bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body,
++line_nr; ++line_nr;
unsigned control_depth = 0; unsigned control_depth = 0;
while (pc < body.end) { while (pc < body.end) {
size_t length = decoder.OpcodeLength(pc); unsigned length = decoder.OpcodeLength(pc);
WasmOpcode opcode = static_cast<WasmOpcode>(*pc); WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
if (opcode == kExprElse) control_depth--; if (opcode == kExprElse) control_depth--;
......
...@@ -25,7 +25,7 @@ namespace wasm { ...@@ -25,7 +25,7 @@ namespace wasm {
struct LocalIndexOperand { struct LocalIndexOperand {
uint32_t index; uint32_t index;
LocalType type; LocalType type;
int 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");
...@@ -35,7 +35,7 @@ struct LocalIndexOperand { ...@@ -35,7 +35,7 @@ struct LocalIndexOperand {
struct ImmI8Operand { struct ImmI8Operand {
int8_t value; int8_t value;
int length; unsigned length;
inline ImmI8Operand(Decoder* decoder, const byte* pc) { inline ImmI8Operand(Decoder* decoder, const byte* pc) {
value = bit_cast<int8_t>(decoder->checked_read_u8(pc, 1, "immi8")); value = bit_cast<int8_t>(decoder->checked_read_u8(pc, 1, "immi8"));
length = 1; length = 1;
...@@ -44,7 +44,7 @@ struct ImmI8Operand { ...@@ -44,7 +44,7 @@ struct ImmI8Operand {
struct ImmI32Operand { struct ImmI32Operand {
int32_t value; int32_t value;
int 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");
} }
...@@ -52,7 +52,7 @@ struct ImmI32Operand { ...@@ -52,7 +52,7 @@ struct ImmI32Operand {
struct ImmI64Operand { struct ImmI64Operand {
int64_t value; int64_t value;
int 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");
} }
...@@ -60,7 +60,7 @@ struct ImmI64Operand { ...@@ -60,7 +60,7 @@ struct ImmI64Operand {
struct ImmF32Operand { struct ImmF32Operand {
float value; float value;
int length; unsigned length;
inline ImmF32Operand(Decoder* decoder, const byte* pc) { inline ImmF32Operand(Decoder* decoder, const byte* pc) {
value = bit_cast<float>(decoder->checked_read_u32(pc, 1, "immf32")); value = bit_cast<float>(decoder->checked_read_u32(pc, 1, "immf32"));
length = 4; length = 4;
...@@ -69,7 +69,7 @@ struct ImmF32Operand { ...@@ -69,7 +69,7 @@ struct ImmF32Operand {
struct ImmF64Operand { struct ImmF64Operand {
double value; double value;
int length; unsigned length;
inline ImmF64Operand(Decoder* decoder, const byte* pc) { inline ImmF64Operand(Decoder* decoder, const byte* pc) {
value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64")); value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64"));
length = 8; length = 8;
...@@ -80,7 +80,7 @@ struct GlobalIndexOperand { ...@@ -80,7 +80,7 @@ struct GlobalIndexOperand {
uint32_t index; uint32_t index;
LocalType type; LocalType type;
MachineType machine_type; MachineType machine_type;
int 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");
...@@ -94,10 +94,10 @@ struct BreakDepthOperand { ...@@ -94,10 +94,10 @@ struct BreakDepthOperand {
uint32_t arity; uint32_t arity;
uint32_t depth; uint32_t depth;
Control* target; Control* target;
int length; unsigned length;
inline BreakDepthOperand(Decoder* decoder, const byte* pc) { inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
int len1 = 0; unsigned len1 = 0;
int len2 = 0; unsigned len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth"); depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth");
length = len1 + len2; length = len1 + len2;
...@@ -109,10 +109,10 @@ struct CallIndirectOperand { ...@@ -109,10 +109,10 @@ struct CallIndirectOperand {
uint32_t arity; uint32_t arity;
uint32_t index; uint32_t index;
FunctionSig* sig; FunctionSig* sig;
int length; unsigned length;
inline CallIndirectOperand(Decoder* decoder, const byte* pc) { inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
int len1 = 0; unsigned len1 = 0;
int len2 = 0; unsigned len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index"); index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index");
length = len1 + len2; length = len1 + len2;
...@@ -124,10 +124,10 @@ struct CallFunctionOperand { ...@@ -124,10 +124,10 @@ struct CallFunctionOperand {
uint32_t arity; uint32_t arity;
uint32_t index; uint32_t index;
FunctionSig* sig; FunctionSig* sig;
int length; unsigned length;
inline CallFunctionOperand(Decoder* decoder, const byte* pc) { inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
int len1 = 0; unsigned len1 = 0;
int len2 = 0; unsigned len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index"); index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index");
length = len1 + len2; length = len1 + len2;
...@@ -139,10 +139,10 @@ struct CallImportOperand { ...@@ -139,10 +139,10 @@ struct CallImportOperand {
uint32_t arity; uint32_t arity;
uint32_t index; uint32_t index;
FunctionSig* sig; FunctionSig* sig;
int length; unsigned length;
inline CallImportOperand(Decoder* decoder, const byte* pc) { inline CallImportOperand(Decoder* decoder, const byte* pc) {
int len1 = 0; unsigned len1 = 0;
int len2 = 0; unsigned len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index"); index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index");
length = len1 + len2; length = len1 + len2;
...@@ -154,13 +154,17 @@ struct BranchTableOperand { ...@@ -154,13 +154,17 @@ struct BranchTableOperand {
uint32_t arity; uint32_t arity;
uint32_t table_count; uint32_t table_count;
const byte* table; const byte* table;
int length; unsigned length;
inline BranchTableOperand(Decoder* decoder, const byte* pc) { inline BranchTableOperand(Decoder* decoder, const byte* pc) {
int len1 = 0; unsigned len1 = 0;
int len2 = 0; unsigned len2 = 0;
arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
table_count = table_count =
decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count"); decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count");
if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 ||
len1 + len2 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) {
decoder->error(pc, "branch table size overflow");
}
length = len1 + len2 + (table_count + 1) * sizeof(uint32_t); length = len1 + len2 + (table_count + 1) * sizeof(uint32_t);
uint32_t table_start = 1 + len1 + len2; uint32_t table_start = 1 + len1 + len2;
...@@ -171,8 +175,8 @@ struct BranchTableOperand { ...@@ -171,8 +175,8 @@ struct BranchTableOperand {
table = nullptr; table = nullptr;
} }
} }
inline uint32_t read_entry(Decoder* decoder, int i) { inline uint32_t read_entry(Decoder* decoder, unsigned i) {
DCHECK(i >= 0 && static_cast<uint32_t>(i) <= table_count); DCHECK(i <= table_count);
return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0; return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0;
} }
}; };
...@@ -180,12 +184,12 @@ struct BranchTableOperand { ...@@ -180,12 +184,12 @@ struct BranchTableOperand {
struct MemoryAccessOperand { struct MemoryAccessOperand {
uint32_t alignment; uint32_t alignment;
uint32_t offset; uint32_t offset;
int length; unsigned length;
inline MemoryAccessOperand(Decoder* decoder, const byte* pc) { inline MemoryAccessOperand(Decoder* decoder, const byte* pc) {
int 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");
int 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;
...@@ -194,7 +198,7 @@ struct MemoryAccessOperand { ...@@ -194,7 +198,7 @@ struct MemoryAccessOperand {
struct ReturnArityOperand { struct ReturnArityOperand {
uint32_t arity; uint32_t arity;
int length; unsigned length;
inline ReturnArityOperand(Decoder* decoder, const byte* pc) { inline ReturnArityOperand(Decoder* decoder, const byte* pc) {
arity = decoder->checked_read_u32v(pc, 1, &length, "return count"); arity = decoder->checked_read_u32v(pc, 1, &length, "return count");
...@@ -269,10 +273,10 @@ BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, ...@@ -269,10 +273,10 @@ BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end); const byte* start, const byte* end);
// Computes the length of the opcode at the given address. // Computes the length of the opcode at the given address.
int OpcodeLength(const byte* pc, const byte* end); unsigned OpcodeLength(const byte* pc, const byte* end);
// Computes the arity (number of sub-nodes) of the opcode at the given address. // Computes the arity (number of sub-nodes) of the opcode at the given address.
int OpcodeArity(const byte* pc, const byte* end); unsigned OpcodeArity(const byte* pc, const byte* end);
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
...@@ -46,7 +46,8 @@ class Decoder { ...@@ -46,7 +46,8 @@ class Decoder {
virtual ~Decoder() {} virtual ~Decoder() {}
inline bool check(const byte* base, int offset, int length, const char* msg) { inline bool check(const byte* base, unsigned offset, unsigned length,
const char* msg) {
DCHECK_GE(base, start_); DCHECK_GE(base, start_);
if ((base + offset + length) > limit_) { if ((base + offset + length) > limit_) {
error(base, base + offset, "%s", msg); error(base, base + offset, "%s", msg);
...@@ -56,37 +57,38 @@ class Decoder { ...@@ -56,37 +57,38 @@ class Decoder {
} }
// 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, int offset, inline uint8_t checked_read_u8(const byte* base, unsigned offset,
const char* msg = "expected 1 byte") { const char* msg = "expected 1 byte") {
return check(base, offset, 1, msg) ? base[offset] : 0; return check(base, offset, 1, msg) ? base[offset] : 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, int offset, inline uint16_t checked_read_u16(const byte* base, unsigned offset,
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(base, offset, 2, msg) ? read_u16(base + offset) : 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, int offset, inline uint32_t checked_read_u32(const byte* base, unsigned offset,
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(base, offset, 4, msg) ? read_u32(base + offset) : 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, int offset, inline uint64_t checked_read_u64(const byte* base, unsigned offset,
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(base, offset, 8, msg) ? read_u64(base + offset) : 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, int offset, int* length, uint32_t checked_read_u32v(const byte* base, unsigned offset,
unsigned* length,
const char* msg = "expected LEB32") { const char* msg = "expected LEB32") {
return checked_read_leb<uint32_t, false>(base, offset, length, msg); 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, int offset, int* length, int32_t checked_read_i32v(const byte* base, unsigned offset, unsigned* length,
const char* msg = "expected SLEB32") { const char* msg = "expected SLEB32") {
uint32_t result = uint32_t result =
checked_read_leb<uint32_t, true>(base, offset, length, msg); checked_read_leb<uint32_t, true>(base, offset, length, msg);
...@@ -100,13 +102,14 @@ class Decoder { ...@@ -100,13 +102,14 @@ class Decoder {
} }
// Reads a variable-length unsigned integer (little endian). // Reads a variable-length unsigned integer (little endian).
uint64_t checked_read_u64v(const byte* base, int offset, int* length, uint64_t checked_read_u64v(const byte* base, unsigned offset,
unsigned* length,
const char* msg = "expected LEB64") { const char* msg = "expected LEB64") {
return checked_read_leb<uint64_t, false>(base, offset, length, msg); 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, int offset, int* length, int64_t checked_read_i64v(const byte* base, unsigned offset, unsigned* length,
const char* msg = "expected SLEB64") { const char* msg = "expected SLEB64") {
uint64_t result = uint64_t result =
checked_read_leb<uint64_t, true>(base, offset, length, msg); checked_read_leb<uint64_t, true>(base, offset, length, msg);
...@@ -349,7 +352,7 @@ class Decoder { ...@@ -349,7 +352,7 @@ class Decoder {
private: private:
template <typename IntType, bool is_signed> template <typename IntType, bool is_signed>
IntType checked_read_leb(const byte* base, int offset, int* length, IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length,
const char* msg) { const char* msg) {
if (!check(base, offset, 1, msg)) { if (!check(base, offset, 1, msg)) {
*length = 0; *length = 0;
...@@ -370,7 +373,7 @@ class Decoder { ...@@ -370,7 +373,7 @@ class Decoder {
shift += 7; shift += 7;
} }
DCHECK_LE(ptr - (base + offset), kMaxLength); DCHECK_LE(ptr - (base + offset), kMaxLength);
*length = static_cast<int>(ptr - (base + offset)); *length = static_cast<unsigned>(ptr - (base + offset));
if (ptr == end) { if (ptr == end) {
// Check there are no bits set beyond the bitwidth of {IntType}. // Check there are no bits set beyond the bitwidth of {IntType}.
const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8); const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8);
......
...@@ -23,7 +23,7 @@ class DecoderTest : public TestWithZone { ...@@ -23,7 +23,7 @@ class DecoderTest : public TestWithZone {
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
int length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, \
decoder.checked_read_u32v(decoder.start(), 0, &length)); \ decoder.checked_read_u32v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \ EXPECT_EQ(expected_length, length); \
...@@ -33,7 +33,7 @@ class DecoderTest : public TestWithZone { ...@@ -33,7 +33,7 @@ class DecoderTest : public TestWithZone {
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
int length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, \
decoder.checked_read_i32v(decoder.start(), 0, &length)); \ decoder.checked_read_i32v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \ EXPECT_EQ(expected_length, length); \
...@@ -43,7 +43,7 @@ class DecoderTest : public TestWithZone { ...@@ -43,7 +43,7 @@ class DecoderTest : public TestWithZone {
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
int length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, \
decoder.checked_read_u64v(decoder.start(), 0, &length)); \ decoder.checked_read_u64v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \ EXPECT_EQ(expected_length, length); \
...@@ -53,7 +53,7 @@ class DecoderTest : public TestWithZone { ...@@ -53,7 +53,7 @@ class DecoderTest : public TestWithZone {
do { \ do { \
const byte data[] = {__VA_ARGS__}; \ const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \ decoder.Reset(data, data + sizeof(data)); \
int length; \ unsigned length; \
EXPECT_EQ(expected, \ EXPECT_EQ(expected, \
decoder.checked_read_i64v(decoder.start(), 0, &length)); \ decoder.checked_read_i64v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \ EXPECT_EQ(expected_length, length); \
...@@ -366,7 +366,7 @@ TEST_F(DecoderTest, ReadI32v_FiveByte) { ...@@ -366,7 +366,7 @@ TEST_F(DecoderTest, ReadI32v_FiveByte) {
TEST_F(DecoderTest, ReadU32v_off_end1) { TEST_F(DecoderTest, ReadU32v_off_end1) {
static const byte data[] = {U32V_1(11)}; static const byte data[] = {U32V_1(11)};
int 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(), 0, &length);
EXPECT_EQ(0, length); EXPECT_EQ(0, length);
...@@ -376,7 +376,7 @@ TEST_F(DecoderTest, ReadU32v_off_end1) { ...@@ -376,7 +376,7 @@ TEST_F(DecoderTest, ReadU32v_off_end1) {
TEST_F(DecoderTest, ReadU32v_off_end2) { TEST_F(DecoderTest, ReadU32v_off_end2) {
static const byte data[] = {U32V_2(1111)}; static const byte data[] = {U32V_2(1111)};
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
int 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(), 0, &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
...@@ -387,7 +387,7 @@ TEST_F(DecoderTest, ReadU32v_off_end2) { ...@@ -387,7 +387,7 @@ TEST_F(DecoderTest, ReadU32v_off_end2) {
TEST_F(DecoderTest, ReadU32v_off_end3) { TEST_F(DecoderTest, ReadU32v_off_end3) {
static const byte data[] = {U32V_3(111111)}; static const byte data[] = {U32V_3(111111)};
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
int 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(), 0, &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
...@@ -398,7 +398,7 @@ TEST_F(DecoderTest, ReadU32v_off_end3) { ...@@ -398,7 +398,7 @@ TEST_F(DecoderTest, ReadU32v_off_end3) {
TEST_F(DecoderTest, ReadU32v_off_end4) { TEST_F(DecoderTest, ReadU32v_off_end4) {
static const byte data[] = {U32V_4(11111111)}; static const byte data[] = {U32V_4(11111111)};
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
int 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(), 0, &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
...@@ -409,7 +409,7 @@ TEST_F(DecoderTest, ReadU32v_off_end4) { ...@@ -409,7 +409,7 @@ TEST_F(DecoderTest, ReadU32v_off_end4) {
TEST_F(DecoderTest, ReadU32v_off_end5) { TEST_F(DecoderTest, ReadU32v_off_end5) {
static const byte data[] = {U32V_5(111111111)}; static const byte data[] = {U32V_5(111111111)};
for (size_t i = 0; i < sizeof(data); i++) { for (size_t i = 0; i < sizeof(data); i++) {
int 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(), 0, &length);
EXPECT_EQ(i, length); EXPECT_EQ(i, length);
...@@ -421,7 +421,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) { ...@@ -421,7 +421,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) {
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x00}; byte data[] = {0x80, 0x80, 0x80, 0x80, 0x00};
for (int i = 1; i < 16; i++) { for (int i = 1; i < 16; i++) {
data[4] = static_cast<byte>(i << 4); data[4] = static_cast<byte>(i << 4);
int 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(), 0, &length);
EXPECT_EQ(5, length); EXPECT_EQ(5, length);
...@@ -431,7 +431,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) { ...@@ -431,7 +431,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) {
TEST_F(DecoderTest, ReadI32v_extra_bits_negative) { TEST_F(DecoderTest, ReadI32v_extra_bits_negative) {
// OK for negative signed values to have extra ones. // OK for negative signed values to have extra ones.
int 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(), 0, &length);
...@@ -441,7 +441,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_negative) { ...@@ -441,7 +441,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_negative) {
TEST_F(DecoderTest, ReadI32v_extra_bits_positive) { TEST_F(DecoderTest, ReadI32v_extra_bits_positive) {
// Not OK for positive signed values to have extra ones. // Not OK for positive signed values to have extra ones.
int 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(), 0, &length);
...@@ -478,7 +478,7 @@ TEST_F(DecoderTest, ReadU32v_Bits) { ...@@ -478,7 +478,7 @@ TEST_F(DecoderTest, ReadU32v_Bits) {
// foreach buffer size 0...5 // foreach buffer size 0...5
for (int limit = 0; limit <= kMaxSize; limit++) { for (int limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
int rlen; unsigned rlen;
uint32_t result = decoder.checked_read_u32v(data, 0, &rlen); uint32_t result = decoder.checked_read_u32v(data, 0, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
...@@ -534,7 +534,7 @@ TEST_F(DecoderTest, ReadU64v_PowerOf2) { ...@@ -534,7 +534,7 @@ TEST_F(DecoderTest, ReadU64v_PowerOf2) {
for (int limit = 0; limit <= kMaxSize; limit++) { for (int limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
int length; unsigned length;
uint64_t result = decoder.checked_read_u64v(data, 0, &length); uint64_t result = decoder.checked_read_u64v(data, 0, &length);
if (limit <= index) { if (limit <= index) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
...@@ -575,7 +575,7 @@ TEST_F(DecoderTest, ReadU64v_Bits) { ...@@ -575,7 +575,7 @@ TEST_F(DecoderTest, ReadU64v_Bits) {
// foreach buffer size 0...10 // foreach buffer size 0...10
for (int limit = 0; limit <= kMaxSize; limit++) { for (int limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
int rlen; unsigned rlen;
uint64_t result = decoder.checked_read_u64v(data, 0, &rlen); uint64_t result = decoder.checked_read_u64v(data, 0, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
...@@ -617,7 +617,7 @@ TEST_F(DecoderTest, ReadI64v_Bits) { ...@@ -617,7 +617,7 @@ TEST_F(DecoderTest, ReadI64v_Bits) {
// foreach buffer size 0...10 // foreach buffer size 0...10
for (int limit = 0; limit <= kMaxSize; limit++) { for (int limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit); decoder.Reset(data, data + limit);
int rlen; unsigned rlen;
int64_t result = decoder.checked_read_i64v(data, 0, &rlen); int64_t result = decoder.checked_read_i64v(data, 0, &rlen);
if (limit < length) { if (limit < length) {
EXPECT_FALSE(decoder.ok()); EXPECT_FALSE(decoder.ok());
...@@ -635,7 +635,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) { ...@@ -635,7 +635,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) {
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00}; byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00};
for (int i = 1; i < 128; i++) { for (int i = 1; i < 128; i++) {
data[9] = static_cast<byte>(i << 1); data[9] = static_cast<byte>(i << 1);
int 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(), 0, &length);
EXPECT_EQ(10, length); EXPECT_EQ(10, length);
...@@ -645,7 +645,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) { ...@@ -645,7 +645,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) {
TEST_F(DecoderTest, ReadI64v_extra_bits_negative) { TEST_F(DecoderTest, ReadI64v_extra_bits_negative) {
// OK for negative signed values to have extra ones. // OK for negative signed values to have extra ones.
int 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(), 0, &length);
...@@ -655,7 +655,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_negative) { ...@@ -655,7 +655,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_negative) {
TEST_F(DecoderTest, ReadI64v_extra_bits_positive) { TEST_F(DecoderTest, ReadI64v_extra_bits_positive) {
// Not OK for positive signed values to have extra ones. // Not OK for positive signed values to have extra ones.
int 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(), 0, &length);
......
...@@ -97,7 +97,7 @@ TEST_F(LEBHelperTest, sizeof_i32v) { ...@@ -97,7 +97,7 @@ TEST_F(LEBHelperTest, sizeof_i32v) {
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); \
int length = 0; \ unsigned length = 0; \
ctype result = decoder.checked_read_##name(buffer, 0, &length); \ ctype result = decoder.checked_read_##name(buffer, 0, &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)); \
......
...@@ -180,6 +180,14 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) { ...@@ -180,6 +180,14 @@ TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
} }
} }
TEST_F(WasmLoopAssignmentAnalyzerTest, Malformed) {
byte code[] = {kExprLoop, kExprF32Neg, kExprBrTable, 0x0e, 'h', 'e',
'l', 'l', 'o', ',', ' ', 'w',
'o', 'r', 'l', 'd', '!'};
BitVector* assigned = Analyze(code, code + arraysize(code));
CHECK_NULL(assigned);
}
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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