v8/test/unittests/wasm/leb-helper-unittest.cc
ddchen fd2bf837a5 [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}
2016-06-27 20:37:28 +00:00

192 lines
5.6 KiB
C++

// Copyright 2016 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/decoder.h"
#include "src/wasm/leb-helper.h"
namespace v8 {
namespace internal {
namespace wasm {
class LEBHelperTest : public TestWithZone {};
TEST_F(LEBHelperTest, sizeof_u32v) {
EXPECT_EQ(1, LEBHelper::sizeof_u32v(0));
EXPECT_EQ(1, LEBHelper::sizeof_u32v(1));
EXPECT_EQ(1, LEBHelper::sizeof_u32v(3));
for (uint32_t i = 4; i < 128; i++) {
EXPECT_EQ(1, LEBHelper::sizeof_u32v(i));
}
for (uint32_t i = (1 << 7); i < (1 << 9); i++) {
EXPECT_EQ(2, LEBHelper::sizeof_u32v(i));
}
for (uint32_t i = (1 << 14); i < (1 << 16); i += 33) {
EXPECT_EQ(3, LEBHelper::sizeof_u32v(i));
}
for (uint32_t i = (1 << 21); i < (1 << 24); i += 33999) {
EXPECT_EQ(4, LEBHelper::sizeof_u32v(i));
}
for (uint32_t i = (1 << 28); i < (1 << 31); i += 33997779) {
EXPECT_EQ(5, LEBHelper::sizeof_u32v(i));
}
EXPECT_EQ(5, LEBHelper::sizeof_u32v(0xFFFFFFFF));
}
TEST_F(LEBHelperTest, sizeof_i32v) {
EXPECT_EQ(1, LEBHelper::sizeof_i32v(0));
EXPECT_EQ(1, LEBHelper::sizeof_i32v(1));
EXPECT_EQ(1, LEBHelper::sizeof_i32v(3));
for (int32_t i = 0; i < (1 << 6); i++) {
EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = (1 << 6); i < (1 << 8); i++) {
EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = (1 << 13); i < (1 << 15); i += 31) {
EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = (1 << 20); i < (1 << 22); i += 31991) {
EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = (1 << 27); i < (1 << 29); i += 3199893) {
EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = -(1 << 6); i <= 0; i++) {
EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = -(1 << 13); i < -(1 << 6); i++) {
EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = -(1 << 20); i < -(1 << 18); i += 11) {
EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = -(1 << 27); i < -(1 << 25); i += 11999) {
EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
}
for (int32_t i = -(1 << 30); i < -(1 << 28); i += 1199999) {
EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
}
}
#define DECLARE_ENCODE_DECODE_CHECKER(ctype, name) \
static void CheckEncodeDecode_##name(ctype val) { \
static const int kSize = 16; \
static byte buffer[kSize]; \
byte *ptr = buffer; \
LEBHelper::write_##name(&ptr, val); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), \
static_cast<size_t>(ptr - buffer)); \
Decoder decoder(buffer, buffer + kSize); \
unsigned length = 0; \
ctype result = decoder.checked_read_##name(buffer, 0, &length); \
EXPECT_EQ(val, result); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
}
DECLARE_ENCODE_DECODE_CHECKER(int32_t, i32v)
DECLARE_ENCODE_DECODE_CHECKER(uint32_t, u32v)
DECLARE_ENCODE_DECODE_CHECKER(int64_t, i64v)
DECLARE_ENCODE_DECODE_CHECKER(uint64_t, u64v)
TEST_F(LEBHelperTest, WriteAndDecode_u32v) {
CheckEncodeDecode_u32v(0);
CheckEncodeDecode_u32v(1);
CheckEncodeDecode_u32v(5);
CheckEncodeDecode_u32v(99);
CheckEncodeDecode_u32v(298);
CheckEncodeDecode_u32v(87348723);
CheckEncodeDecode_u32v(77777);
for (uint32_t val = 0x3a; val != 0; val = val << 1) {
CheckEncodeDecode_u32v(val);
}
}
TEST_F(LEBHelperTest, WriteAndDecode_i32v) {
CheckEncodeDecode_i32v(0);
CheckEncodeDecode_i32v(1);
CheckEncodeDecode_i32v(5);
CheckEncodeDecode_i32v(99);
CheckEncodeDecode_i32v(298);
CheckEncodeDecode_i32v(87348723);
CheckEncodeDecode_i32v(77777);
CheckEncodeDecode_i32v(-2);
CheckEncodeDecode_i32v(-4);
CheckEncodeDecode_i32v(-59);
CheckEncodeDecode_i32v(-288);
CheckEncodeDecode_i32v(-12608);
CheckEncodeDecode_i32v(-87328723);
CheckEncodeDecode_i32v(-77377);
for (uint32_t val = 0x3a; val != 0; val = val << 1) {
CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
}
for (uint32_t val = 0xFFFFFF3B; val != 0; val = val << 1) {
CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
}
}
TEST_F(LEBHelperTest, WriteAndDecode_u64v) {
CheckEncodeDecode_u64v(0);
CheckEncodeDecode_u64v(1);
CheckEncodeDecode_u64v(5);
CheckEncodeDecode_u64v(99);
CheckEncodeDecode_u64v(298);
CheckEncodeDecode_u64v(87348723);
CheckEncodeDecode_u64v(77777);
for (uint64_t val = 0x3a; val != 0; val = val << 1) {
CheckEncodeDecode_u64v(val);
}
}
TEST_F(LEBHelperTest, WriteAndDecode_i64v) {
CheckEncodeDecode_i64v(0);
CheckEncodeDecode_i64v(1);
CheckEncodeDecode_i64v(5);
CheckEncodeDecode_i64v(99);
CheckEncodeDecode_i64v(298);
CheckEncodeDecode_i64v(87348723);
CheckEncodeDecode_i64v(77777);
CheckEncodeDecode_i64v(-2);
CheckEncodeDecode_i64v(-4);
CheckEncodeDecode_i64v(-59);
CheckEncodeDecode_i64v(-288);
CheckEncodeDecode_i64v(-87648723);
CheckEncodeDecode_i64v(-77377);
for (uint64_t val = 0x3a; val != 0; val = val << 1) {
CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
}
for (uint64_t val = 0xFFFFFFFFFFFFFF3B; val != 0; val = val << 1) {
CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
}
}
} // namespace wasm
} // namespace internal
} // namespace v8