// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "test/unittests/test-utils.h" #include "src/objects-inl.h" #include "src/wasm/module-decoder.h" #include "src/wasm/streaming-decoder.h" #include "src/objects/descriptor-array.h" #include "src/objects/dictionary.h" #include "test/common/wasm/wasm-macro-gen.h" namespace v8 { namespace internal { namespace wasm { class WasmStreamingDecoderTest : public ::testing::Test { public: void ExpectVerifies(Vector data) { for (int split = 0; split <= data.length(); ++split) { StreamingDecoder stream(nullptr); stream.OnBytesReceived(data.SubVector(0, split)); stream.OnBytesReceived(data.SubVector(split, data.length())); EXPECT_TRUE(stream.FinishForTesting()); } } void ExpectFailure(Vector data) { for (int split = 0; split <= data.length(); ++split) { StreamingDecoder stream(nullptr); stream.OnBytesReceived(data.SubVector(0, split)); stream.OnBytesReceived(data.SubVector(split, data.length())); EXPECT_FALSE(stream.FinishForTesting()); } } }; TEST_F(WasmStreamingDecoderTest, EmptyStream) { StreamingDecoder stream(nullptr); EXPECT_FALSE(stream.FinishForTesting()); } TEST_F(WasmStreamingDecoderTest, IncompleteModuleHeader) { const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)}; { StreamingDecoder stream(nullptr); stream.OnBytesReceived(Vector(data, 1)); EXPECT_FALSE(stream.FinishForTesting()); } for (int length = 1; length < static_cast(arraysize(data)); ++length) { ExpectFailure(Vector(data, length)); } } TEST_F(WasmStreamingDecoderTest, MagicAndVersion) { const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)}; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, BadMagic) { for (uint32_t x = 1; x; x <<= 1) { const uint8_t data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion)}; ExpectFailure(Vector(data, arraysize(data))); } } TEST_F(WasmStreamingDecoderTest, BadVersion) { for (uint32_t x = 1; x; x <<= 1) { const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion ^ x)}; ExpectFailure(Vector(data, arraysize(data))); } } TEST_F(WasmStreamingDecoderTest, OneSection) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x6, // Section Length 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0 // 6 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneSection_b) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x86, // Section Length = 6 (LEB) 0x0, // -- 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0 // 6 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneShortSection) { // Short section means that section length + payload is less than 5 bytes, // which is the maximum size of the length field. const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x2, // Section Length 0x0, // Payload 0x0 // 2 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneShortSection_b) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x82, // Section Length = 2 (LEB) 0x80, // -- 0x0, // -- 0x0, // Payload 0x0 // 2 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneEmptySection) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x0 // Section Length }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneSectionNotEnoughPayload1) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x6, // Section Length 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0 // 5 }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneSectionNotEnoughPayload2) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x6, // Section Length 0x0 // Payload }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneSectionInvalidLength) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x80, // Section Length (0 in LEB) 0x80, // -- 0x80, // -- 0x80, // -- 0x80, // -- }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoLongSections) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x6, // Section Length 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x2, // Section ID 0x7, // Section Length 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0 // 7 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoShortSections) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x1, // Section Length 0x0, // Payload 0x2, // Section ID 0x2, // Section Length 0x0, // Payload 0x0, // 2 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoSectionsShortLong) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x1, // Section Length 0x0, // Payload 0x2, // Section ID 0x7, // Section Length 0x0, // Payload 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0 // 7 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoEmptySections) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- 0x1, // Section ID 0x0, // Section Length 0x2, // Section ID 0x0 // Section Length }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, EmptyCodeSection) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x0, // Section Length 0xb, // Section ID 0x0 // Section Length }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneFunction) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x8, // Section Length 0x1, // Number of Functions 0x6, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, OneShortFunction) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x3, // Section Length 0x1, // Number of Functions 0x1, // Function Length 0x0, // Function }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, EmptyFunction) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x2, // Section Length 0x1, // Number of Functions 0x0, // Function Length }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoFunctions) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x10, // Section Length 0x2, // Number of Functions 0x6, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, TwoFunctions_b) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0xb, // Section Length 0x2, // Number of Functions 0x1, // Function Length 0x0, // Function 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 }; ExpectVerifies(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooHigh) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0xd, // Section Length 0x2, // Number of Functions 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 0x1, // Function Length 0x0, // Function }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLow) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x9, // Section Length 0x2, // Number of Functions 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 0x1, // Function Length 0x0, // Function }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLowEndsInNumFunctions) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x1, // Section Length 0x82, // Number of Functions 0x80, // -- 0x00, // -- 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 0x1, // Function Length 0x0, // Function }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLowEndsInFunctionLength) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0x5, // Section Length 0x82, // Number of Functions 0x80, // -- 0x00, // -- 0x87, // Function Length 0x80, // -- 0x00, // -- 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 0x1, // Function Length 0x0, // Function }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, NumberOfFunctionsTooHigh) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0xb, // Section Length 0x4, // Number of Functions 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 0x1, // Function Length 0x0, // Function }; ExpectFailure(Vector(data, arraysize(data))); } TEST_F(WasmStreamingDecoderTest, NumberOfFunctionsTooLow) { const uint8_t data[] = { U32_LE(kWasmMagic), // -- U32_LE(kWasmVersion), // -- kCodeSectionCode, // Section ID 0xe, // Section Length 0x2, // Number of Functions 0x1, // Function Length 0x0, // Function 0x2, // Function Length 0x0, // Function 0x0, // 2 0x7, // Function Length 0x0, // Function 0x0, // 2 0x0, // 3 0x0, // 4 0x0, // 5 0x0, // 6 0x0, // 7 }; ExpectFailure(Vector(data, arraysize(data))); } } // namespace wasm } // namespace internal } // namespace v8