499 lines
17 KiB
C++
499 lines
17 KiB
C++
|
// 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<const uint8_t> 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<const uint8_t> 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<const uint8_t>(data, 1));
|
||
|
EXPECT_FALSE(stream.FinishForTesting());
|
||
|
}
|
||
|
for (int length = 1; length < static_cast<int>(arraysize(data)); ++length) {
|
||
|
ExpectFailure(Vector<const uint8_t>(data, length));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TEST_F(WasmStreamingDecoderTest, MagicAndVersion) {
|
||
|
const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)};
|
||
|
ExpectVerifies(Vector<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(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<const uint8_t>(data, arraysize(data)));
|
||
|
}
|
||
|
} // namespace wasm
|
||
|
} // namespace internal
|
||
|
} // namespace v8
|