|  | // 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/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 { | 
|  |  | 
|  | struct MockStreamingResult { | 
|  | size_t num_sections = 0; | 
|  | size_t num_functions = 0; | 
|  | WasmError error; | 
|  | OwnedVector<uint8_t> received_bytes; | 
|  |  | 
|  | bool ok() const { return !error.has_error(); } | 
|  |  | 
|  | MockStreamingResult() = default; | 
|  | }; | 
|  |  | 
|  | class MockStreamingProcessor : public StreamingProcessor { | 
|  | public: | 
|  | explicit MockStreamingProcessor(MockStreamingResult* result) | 
|  | : result_(result) {} | 
|  |  | 
|  | bool ProcessModuleHeader(Vector<const uint8_t> bytes, | 
|  | uint32_t offset) override { | 
|  | Decoder decoder(bytes.begin(), bytes.end()); | 
|  | uint32_t magic_word = decoder.consume_u32("wasm magic"); | 
|  | if (decoder.failed() || magic_word != kWasmMagic) { | 
|  | result_->error = WasmError(0, "expected wasm magic"); | 
|  | return false; | 
|  | } | 
|  | uint32_t magic_version = decoder.consume_u32("wasm version"); | 
|  | if (decoder.failed() || magic_version != kWasmVersion) { | 
|  | result_->error = WasmError(4, "expected wasm version"); | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Process all sections but the code section. | 
|  | bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes, | 
|  | uint32_t offset) override { | 
|  | ++result_->num_sections; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ProcessCodeSectionHeader(int num_functions, uint32_t offset, | 
|  | std::shared_ptr<WireBytesStorage>, | 
|  | int code_section_length) override { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Process a function body. | 
|  | bool ProcessFunctionBody(Vector<const uint8_t> bytes, | 
|  | uint32_t offset) override { | 
|  | ++result_->num_functions; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void OnFinishedChunk() override {} | 
|  |  | 
|  | // Finish the processing of the stream. | 
|  | void OnFinishedStream(OwnedVector<uint8_t> bytes) override { | 
|  | result_->received_bytes = std::move(bytes); | 
|  | } | 
|  |  | 
|  | // Report an error detected in the StreamingDecoder. | 
|  | void OnError(const WasmError& error) override { | 
|  | result_->error = error; | 
|  | CHECK(!result_->ok()); | 
|  | } | 
|  |  | 
|  | void OnAbort() override {} | 
|  |  | 
|  | bool Deserialize(Vector<const uint8_t> module_bytes, | 
|  | Vector<const uint8_t> wire_bytes) override { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | private: | 
|  | MockStreamingResult* const result_; | 
|  | }; | 
|  |  | 
|  | class WasmStreamingDecoderTest : public ::testing::Test { | 
|  | public: | 
|  | void ExpectVerifies(Vector<const uint8_t> data, size_t expected_sections, | 
|  | size_t expected_functions) { | 
|  | for (int split = 0; split <= data.length(); ++split) { | 
|  | MockStreamingResult result; | 
|  | auto stream = StreamingDecoder::CreateAsyncStreamingDecoder( | 
|  | std::make_unique<MockStreamingProcessor>(&result)); | 
|  | stream->OnBytesReceived(data.SubVector(0, split)); | 
|  | stream->OnBytesReceived(data.SubVector(split, data.length())); | 
|  | stream->Finish(); | 
|  | EXPECT_TRUE(result.ok()); | 
|  | EXPECT_EQ(expected_sections, result.num_sections); | 
|  | EXPECT_EQ(expected_functions, result.num_functions); | 
|  | EXPECT_EQ(data, result.received_bytes.as_vector()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ExpectFailure(Vector<const uint8_t> data, uint32_t error_offset, | 
|  | const char* message) { | 
|  | for (int split = 0; split <= data.length(); ++split) { | 
|  | MockStreamingResult result; | 
|  | auto stream = StreamingDecoder::CreateAsyncStreamingDecoder( | 
|  | std::make_unique<MockStreamingProcessor>(&result)); | 
|  | stream->OnBytesReceived(data.SubVector(0, split)); | 
|  | stream->OnBytesReceived(data.SubVector(split, data.length())); | 
|  | stream->Finish(); | 
|  | EXPECT_FALSE(result.ok()); | 
|  | EXPECT_EQ(error_offset, result.error.offset()); | 
|  | EXPECT_EQ(message, result.error.message()); | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, EmptyStream) { | 
|  | MockStreamingResult result; | 
|  | auto stream = StreamingDecoder::CreateAsyncStreamingDecoder( | 
|  | std::make_unique<MockStreamingProcessor>(&result)); | 
|  | stream->Finish(); | 
|  | EXPECT_FALSE(result.ok()); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, IncompleteModuleHeader) { | 
|  | const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)}; | 
|  | { | 
|  | MockStreamingResult result; | 
|  | auto stream = StreamingDecoder::CreateAsyncStreamingDecoder( | 
|  | std::make_unique<MockStreamingProcessor>(&result)); | 
|  | stream->OnBytesReceived(VectorOf(data, 1)); | 
|  | stream->Finish(); | 
|  | EXPECT_FALSE(result.ok()); | 
|  | } | 
|  | for (uint32_t length = 1; length < sizeof(data); ++length) { | 
|  | ExpectFailure(VectorOf(data, length), length - 1, | 
|  | "unexpected end of stream"); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, MagicAndVersion) { | 
|  | const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)}; | 
|  | ExpectVerifies(ArrayVector(data), 0, 0); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, BadMagic) { | 
|  | for (uint32_t x = 1; x; x <<= 1) { | 
|  | const uint8_t data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion)}; | 
|  | ExpectFailure(ArrayVector(data), 0, "expected wasm magic"); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, BadVersion) { | 
|  | for (uint32_t x = 1; x; x <<= 1) { | 
|  | const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion ^ x)}; | 
|  | ExpectFailure(ArrayVector(data), 4, "expected wasm version"); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 1, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 1, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 1, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 1, 0); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, OneEmptySection) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | 0x1,                   // Section ID | 
|  | 0x0                    // Section Length | 
|  | }; | 
|  | ExpectVerifies(ArrayVector(data), 1, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), sizeof(data) - 1, | 
|  | "unexpected end of stream"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, OneSectionNotEnoughPayload2) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | 0x1,                   // Section ID | 
|  | 0x6,                   // Section Length | 
|  | 0x0                    // Payload | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 1, | 
|  | "unexpected end of stream"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, OneSectionInvalidLength) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | 0x1,                   // Section ID | 
|  | 0x80,                  // Section Length (invalid LEB) | 
|  | 0x80,                  // -- | 
|  | 0x80,                  // -- | 
|  | 0x80,                  // -- | 
|  | 0x80,                  // -- | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 1, "expected section length"); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 2, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 2, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 2, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 2, 0); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 0, 1); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 0, 1); | 
|  | } | 
|  |  | 
|  | 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  -- ERROR | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 1, | 
|  | "invalid function length (0)"); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 0, 2); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), 0, 2); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, CodeSectionLengthZero) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0x0,                   // Section Length | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 1, | 
|  | "code section cannot have size 0"); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), sizeof(data) - 1, | 
|  | "not all code section bytes were used"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooHighZeroFunctions) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0xD,                   // Section Length | 
|  | 0x0,                   // Number of Functions | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 1, | 
|  | "not all code section bytes were used"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLow) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0x9,                   // Section Length | 
|  | 0x2,                   // Number of Functions  <0> | 
|  | 0x7,                   // Function Length      <1> | 
|  | 0x0,                   // Function             <2> | 
|  | 0x0,                   // 2                    <3> | 
|  | 0x0,                   // 3                    <3> | 
|  | 0x0,                   // 4                    <4> | 
|  | 0x0,                   // 5                    <5> | 
|  | 0x0,                   // 6                    <6> | 
|  | 0x0,                   // 7                    <7> | 
|  | 0x1,                   // Function Length      <8> -- ERROR | 
|  | 0x0,                   // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 2, | 
|  | "read past code section end"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLowEndsInNumFunctions) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0x1,                   // Section Length | 
|  | 0x82,                  // Number of Functions  <0> | 
|  | 0x80,                  // --                   <1> -- ERROR | 
|  | 0x00,                  // -- | 
|  | 0x7,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | 0x0,                   // 2 | 
|  | 0x0,                   // 3 | 
|  | 0x0,                   // 4 | 
|  | 0x0,                   // 5 | 
|  | 0x0,                   // 6 | 
|  | 0x0,                   // 7 | 
|  | 0x1,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), 12, "invalid code section length"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, CodeSectionLengthTooLowEndsInFunctionLength) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0x5,                   // Section Length | 
|  | 0x82,                  // Number of Functions  <0> | 
|  | 0x80,                  // --                   <1> | 
|  | 0x00,                  // --                   <2> | 
|  | 0x87,                  // Function Length      <3> | 
|  | 0x80,                  // --                   <4> | 
|  | 0x00,                  // --                   <5> -- ERROR | 
|  | 0x0,                   // Function | 
|  | 0x0,                   // 2 | 
|  | 0x0,                   // 3 | 
|  | 0x0,                   // 4 | 
|  | 0x0,                   // 5 | 
|  | 0x0,                   // 6 | 
|  | 0x0,                   // 7 | 
|  | 0x1,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), 15, "read past code section end"); | 
|  | } | 
|  |  | 
|  | 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(ArrayVector(data), sizeof(data) - 1, | 
|  | "unexpected end of stream"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, NumberOfFunctionsTooLow) { | 
|  | const uint8_t data[] = { | 
|  | U32_LE(kWasmMagic),    // -- | 
|  | U32_LE(kWasmVersion),  // -- | 
|  | kCodeSectionCode,      // Section ID | 
|  | 0x8,                   // Section Length | 
|  | 0x2,                   // Number of Functions | 
|  | 0x1,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | 0x2,                   // Function Length | 
|  | 0x0,                   // Function byte#0 | 
|  | 0x0,                   // Function byte#1   -- ERROR | 
|  | 0x1,                   // Function Length | 
|  | 0x0                    // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 3, | 
|  | "not all code section bytes were used"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, TwoCodeSections) { | 
|  | 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 | 
|  | kCodeSectionCode,      // Section ID      -- ERROR | 
|  | 0x3,                   // Section Length | 
|  | 0x1,                   // Number of Functions | 
|  | 0x1,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 5, | 
|  | "code section can only appear once"); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, UnknownSection) { | 
|  | 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 | 
|  | kUnknownSectionCode,   // Section ID | 
|  | 0x3,                   // Section Length | 
|  | 0x1,                   // Name Length | 
|  | 0x1,                   // Name | 
|  | 0x0,                   // Content | 
|  | }; | 
|  | ExpectVerifies(ArrayVector(data), 1, 1); | 
|  | } | 
|  |  | 
|  | TEST_F(WasmStreamingDecoderTest, UnknownSectionSandwich) { | 
|  | 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 | 
|  | kUnknownSectionCode,   // Section ID | 
|  | 0x3,                   // Section Length | 
|  | 0x1,                   // Name Length | 
|  | 0x1,                   // Name | 
|  | 0x0,                   // Content | 
|  | kCodeSectionCode,      // Section ID     -- ERROR | 
|  | 0x3,                   // Section Length | 
|  | 0x1,                   // Number of Functions | 
|  | 0x1,                   // Function Length | 
|  | 0x0,                   // Function | 
|  | }; | 
|  | ExpectFailure(ArrayVector(data), sizeof(data) - 5, | 
|  | "code section can only appear once"); | 
|  | } | 
|  |  | 
|  | }  // namespace wasm | 
|  | }  // namespace internal | 
|  | }  // namespace v8 |