Index: test/unittests/wasm/module-decoder-unittest.cc |
diff --git a/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc |
index 42353b8f8f36ba5e7b6b607252c4dfdbd5a1af25..c855cff7a682df7d6c9e721061a0fba29c4aafe5 100644 |
--- a/test/unittests/wasm/module-decoder-unittest.cc |
+++ b/test/unittests/wasm/module-decoder-unittest.cc |
@@ -5,36 +5,17 @@ |
#include "test/unittests/test-utils.h" |
#include "src/wasm/module-decoder.h" |
+#include "src/wasm/wasm-macro-gen.h" |
#include "src/wasm/wasm-opcodes.h" |
namespace v8 { |
namespace internal { |
namespace wasm { |
+#define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0) |
#define VOID_VOID_SIG 0, kLocalVoid |
#define INT_INT_SIG 1, kLocalI32, kLocalI32 |
-#define U32(v) \ |
- static_cast<byte>(v), static_cast<byte>(v >> 8), static_cast<byte>(v >> 16), \ |
- static_cast<byte>(v >> 24) |
-#define U16(v) static_cast<byte>(v), static_cast<byte>(v >> 8) |
-#define U8(v) static_cast<byte>(v) |
- |
-#define SIG_INDEX(v) U16(v) |
-#define FUNC_INDEX(v) U16(v) |
-#define NAME_OFFSET(v) U32(v) |
- |
-#define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16(0) |
- |
-class WasmModuleVerifyTest : public TestWithZone { |
- public: |
- ModuleResult DecodeModule(const byte* module_start, const byte* module_end) { |
- return DecodeWasmModule(nullptr, zone(), module_start, module_end, false, |
- kWasmOrigin); |
- } |
-}; |
- |
- |
#define EXPECT_VERIFIES(data) \ |
do { \ |
ModuleResult result = DecodeModule(data, data + arraysize(data)); \ |
@@ -42,14 +23,21 @@ class WasmModuleVerifyTest : public TestWithZone { |
if (result.val) delete result.val; \ |
} while (false) |
- |
-#define EXPECT_FAILURE(data) \ |
- do { \ |
- ModuleResult result = DecodeModule(data, data + arraysize(data)); \ |
- EXPECT_FALSE(result.ok()); \ |
- if (result.val) delete result.val; \ |
+#define EXPECT_FAILURE_LEN(data, length) \ |
+ do { \ |
+ ModuleResult result = DecodeModule(data, data + length); \ |
+ EXPECT_FALSE(result.ok()); \ |
+ if (result.val) delete result.val; \ |
} while (false) |
+#define EXPECT_FAILURE(data) EXPECT_FAILURE_LEN(data, sizeof(data)) |
+ |
+#define EXPECT_OFF_END_FAILURE(data, min, max) \ |
+ do { \ |
+ for (size_t length = min; length < max; length++) { \ |
+ EXPECT_FAILURE_LEN(data, length); \ |
+ } \ |
+ } while (false) |
struct LocalTypePair { |
uint8_t code; |
@@ -59,21 +47,52 @@ struct LocalTypePair { |
{kLocalF32, kAstF32}, |
{kLocalF64, kAstF64}}; |
+class WasmModuleVerifyTest : public TestWithZone { |
+ public: |
+ ModuleResult DecodeModule(const byte* module_start, const byte* module_end) { |
+ // Add the WASM magic and version number automatically. |
+ size_t size = static_cast<size_t>(module_end - module_start); |
+ byte header[] = {WASM_MODULE_HEADER}; |
+ size_t total = sizeof(header) + size; |
+ auto temp = new byte[total]; |
+ memcpy(temp, header, sizeof(header)); |
+ memcpy(temp + sizeof(header), module_start, size); |
+ ModuleResult result = DecodeWasmModule(nullptr, zone(), temp, temp + total, |
+ false, kWasmOrigin); |
+ delete[] temp; |
+ return result; |
+ } |
+ ModuleResult DecodeModuleNoHeader(const byte* module_start, |
+ const byte* module_end) { |
+ return DecodeWasmModule(nullptr, zone(), module_start, module_end, false, |
+ kWasmOrigin); |
+ } |
+}; |
-TEST_F(WasmModuleVerifyTest, DecodeEmpty) { |
- static const byte data[1]{kDeclEnd}; |
- { |
- ModuleResult result = DecodeModule(data, data); |
- EXPECT_TRUE(result.ok()); |
+TEST_F(WasmModuleVerifyTest, WrongMagic) { |
+ for (uint32_t x = 1; x; x <<= 1) { |
+ const byte data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion), |
+ kDeclEnd}; |
+ ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data)); |
+ EXPECT_FALSE(result.ok()); |
if (result.val) delete result.val; |
} |
- { |
- ModuleResult result = DecodeModule(data, data + 1); |
- EXPECT_TRUE(result.ok()); |
+} |
+ |
+TEST_F(WasmModuleVerifyTest, WrongVersion) { |
+ for (uint32_t x = 1; x; x <<= 1) { |
+ const byte data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion ^ x), |
+ kDeclEnd}; |
+ ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data)); |
+ EXPECT_FALSE(result.ok()); |
if (result.val) delete result.val; |
} |
} |
+TEST_F(WasmModuleVerifyTest, DecodeEmpty) { |
+ static const byte data[] = {kDeclEnd}; |
+ EXPECT_VERIFIES(data); |
+} |
TEST_F(WasmModuleVerifyTest, OneGlobal) { |
static const byte data[] = { |
@@ -102,12 +121,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) { |
if (result.val) delete result.val; |
} |
- for (size_t size = 1; size < arraysize(data); size++) { |
- // Should fall off end of module bytes. |
- ModuleResult result = DecodeModule(data, data + size); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 1, sizeof(data)); |
} |
@@ -142,12 +156,13 @@ TEST_F(WasmModuleVerifyTest, NGlobals) { |
kMemI32, // memory type |
0, // exported |
}; |
- for (uint32_t i = 0; i < 1000000; i = i * 7 + 1) { |
+ |
+ for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) { |
std::vector<byte> buffer; |
buffer.push_back(kDeclGlobals); |
AppendUint32v(buffer, i); |
for (uint32_t j = 0; j < i; j++) { |
- buffer.insert(buffer.end(), data, data + arraysize(data)); |
+ buffer.insert(buffer.end(), data, data + sizeof(data)); |
} |
ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size()); |
@@ -219,12 +234,7 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) { |
if (result.val) delete result.val; |
} |
- for (size_t size = 1; size < arraysize(data); size++) { |
- // Should fall off end of module bytes. |
- ModuleResult result = DecodeModule(data, data + size); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 1, sizeof(data)); |
} |
@@ -270,12 +280,7 @@ TEST_F(WasmModuleVerifyTest, MultipleSignatures) { |
} |
if (result.val) delete result.val; |
- for (size_t size = 1; size < arraysize(data); size++) { |
- ModuleResult result = DecodeModule(data, data + size); |
- // Should fall off the end of module bytes. |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 1, sizeof(data)); |
} |
@@ -285,12 +290,12 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) { |
// func#0 ------------------------------------------------------ |
SIG_INDEX(0), // signature index |
NAME_OFFSET(0), // name offset |
- U32(0), // code start offset |
- U32(0), // code end offset |
- U16(899), // local int32 count |
- U16(799), // local int64 count |
- U16(699), // local float32 count |
- U16(599), // local float64 count |
+ U32_LE(0), // code start offset |
+ U32_LE(0), // code end offset |
+ U16_LE(899), // local int32 count |
+ U16_LE(799), // local int64 count |
+ U16_LE(699), // local float32 count |
+ U16_LE(599), // local float64 count |
0, // exported |
1 // external |
}; |
@@ -302,7 +307,7 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) { |
TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { |
- const int kCodeStartOffset = 23; |
+ const int kCodeStartOffset = 31; |
const int kCodeEndOffset = kCodeStartOffset + 1; |
static const byte data[] = { |
@@ -314,10 +319,10 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { |
kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName, |
SIG_INDEX(0), // signature index |
NAME_OFFSET(9), // name offset |
- U16(1466), // local int32 count |
- U16(1355), // local int64 count |
- U16(1244), // local float32 count |
- U16(1133), // local float64 count |
+ U16_LE(1466), // local int32 count |
+ U16_LE(1355), // local int64 count |
+ U16_LE(1244), // local float32 count |
+ U16_LE(1133), // local float64 count |
1, 0, // size |
kExprNop, |
}; |
@@ -349,12 +354,7 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) { |
if (result.val) delete result.val; |
} |
- for (size_t size = 5; size < arraysize(data); size++) { |
- // Should fall off end of module bytes. |
- ModuleResult result = DecodeModule(data, data + size); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 5, sizeof(data)); |
} |
@@ -390,7 +390,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionImported) { |
TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) { |
- static const byte kCodeStartOffset = 11; |
+ static const byte kCodeStartOffset = 19; |
static const byte kCodeEndOffset = kCodeStartOffset + 1; |
static const byte data[] = { |
@@ -427,7 +427,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) { |
TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) { |
- static const byte kCodeStartOffset = 19; |
+ static const byte kCodeStartOffset = 27; |
static const byte kCodeEndOffset = kCodeStartOffset + 1; |
static const byte data[] = { |
@@ -469,7 +469,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) { |
TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) { |
static const byte kDeclMemorySize = 4; |
static const byte kCodeStartOffset = |
- 2 + kDeclMemorySize + kDeclGlobalSize + 4 + 2 + 17; |
+ 8 + 2 + kDeclMemorySize + kDeclGlobalSize + 4 + 2 + 17; |
static const byte kCodeEndOffset = kCodeStartOffset + 3; |
static const byte data[] = { |
@@ -565,12 +565,7 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) { |
if (result.val) delete result.val; |
} |
- for (size_t size = 5; size < arraysize(data); size++) { |
- // Should fall off end of module bytes. |
- ModuleResult result = DecodeModule(data, data + size); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 5, sizeof(data)); |
} |
@@ -615,19 +610,16 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) { |
if (result.val) delete result.val; |
} |
- for (size_t size = 5; size < arraysize(data); size++) { |
- // Should fall off end of module bytes. |
- ModuleResult result = DecodeModule(data, data + size); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 5, sizeof(data)); |
} |
TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidSource) { |
const int dest_addr = 0x100; |
const byte mem_size_log2 = 15; |
+ const int kHeaderSize = 8; |
const int kDataSize = 19; |
+ const int kTotalSize = kHeaderSize + kDataSize; |
for (int source_offset = 0; source_offset < 5 + kDataSize; source_offset++) { |
for (int source_size = -1; source_size < 5 + kDataSize; source_size += 3) { |
@@ -638,16 +630,16 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidSource) { |
1, |
kDeclDataSegments, |
1, |
- U32(dest_addr), |
- U32(source_offset), |
- U32(source_size), |
+ U32_LE(dest_addr), |
+ U32_LE(source_offset), |
+ U32_LE(source_size), |
1, // init |
}; |
STATIC_ASSERT(kDataSize == arraysize(data)); |
- if (source_offset < kDataSize && source_size >= 0 && |
- (source_offset + source_size) <= kDataSize) { |
+ if (source_offset < kTotalSize && source_size >= 0 && |
+ (source_offset + source_size) <= kTotalSize) { |
EXPECT_VERIFIES(data); |
} else { |
EXPECT_FAILURE(data); |
@@ -673,9 +665,9 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) { |
1, |
kDeclDataSegments, |
1, |
- U32(dest_addr), |
- U32(source_offset), |
- U32(source_size), |
+ U32_LE(dest_addr), |
+ U32_LE(source_offset), |
+ U32_LE(source_size), |
1, // init |
}; |
@@ -1043,11 +1035,7 @@ TEST_F(WasmModuleVerifyTest, ImportTable_off_end) { |
NAME_OFFSET(1), // function name |
}; |
- for (size_t length = 5; length < sizeof(data); length++) { |
- ModuleResult result = DecodeModule(data, data + length); |
- EXPECT_FALSE(result.ok()); |
- if (result.val) delete result.val; |
- } |
+ EXPECT_OFF_END_FAILURE(data, 5, sizeof(data)); |
} |
TEST_F(WasmModuleVerifyTest, ExportTable_empty) { |