e68728a262
The IsInBounds function is used in a few different places, when used for bounds checks on 32-bit platforms, size_t for max_memory_size leads to incorrect out of bounds accesses as size_t is not guaranteed to be 64-bit on all platforms. Use specific uint32_t, uint64_t methods for Wasm bounds checking instead of size_t. Bug: chromium:1080902 Change-Id: I0e21f0a310382c8ed0703c8302200d3352495c13 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2256858 Commit-Queue: Deepti Gandluri <gdeepti@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#68500}
206 lines
7.3 KiB
C++
206 lines
7.3 KiB
C++
// Copyright 2014 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 <limits>
|
|
|
|
#include "src/base/bounds.h"
|
|
#include "src/utils/utils.h"
|
|
#include "testing/gtest-support.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
template <typename T>
|
|
class UtilsTest : public ::testing::Test {};
|
|
|
|
using IntegerTypes =
|
|
::testing::Types<signed char, unsigned char,
|
|
short, // NOLINT(runtime/int)
|
|
unsigned short, // NOLINT(runtime/int)
|
|
int, unsigned int, long, // NOLINT(runtime/int)
|
|
unsigned long, // NOLINT(runtime/int)
|
|
long long, // NOLINT(runtime/int)
|
|
unsigned long long, // NOLINT(runtime/int)
|
|
int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
|
int64_t, uint64_t>;
|
|
|
|
TYPED_TEST_SUITE(UtilsTest, IntegerTypes);
|
|
|
|
TYPED_TEST(UtilsTest, SaturateSub) {
|
|
TypeParam min = std::numeric_limits<TypeParam>::min();
|
|
TypeParam max = std::numeric_limits<TypeParam>::max();
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, 0), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max, 0), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max, min), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, max), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, max / 3), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min + 1, 2), min);
|
|
if (std::numeric_limits<TypeParam>::is_signed) {
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, min), static_cast<TypeParam>(0));
|
|
EXPECT_EQ(SaturateSub<TypeParam>(0, min), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max / 3, min), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max / 5, min), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min / 3, max), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min / 9, max), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max, min / 3), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, max / 3), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max / 3 * 2, min / 2), max);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min / 3 * 2, max / 2), min);
|
|
} else {
|
|
EXPECT_EQ(SaturateSub<TypeParam>(min, min), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(0, min), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(0, max), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max / 3, max), min);
|
|
EXPECT_EQ(SaturateSub<TypeParam>(max - 3, max), min);
|
|
}
|
|
TypeParam test_cases[] = {static_cast<TypeParam>(min / 23),
|
|
static_cast<TypeParam>(max / 3),
|
|
63,
|
|
static_cast<TypeParam>(min / 6),
|
|
static_cast<TypeParam>(max / 55),
|
|
static_cast<TypeParam>(min / 2),
|
|
static_cast<TypeParam>(max / 2),
|
|
0,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
42};
|
|
TRACED_FOREACH(TypeParam, x, test_cases) {
|
|
TRACED_FOREACH(TypeParam, y, test_cases) {
|
|
if (std::numeric_limits<TypeParam>::is_signed) {
|
|
EXPECT_EQ(SaturateSub<TypeParam>(x, y), x - y);
|
|
} else {
|
|
EXPECT_EQ(SaturateSub<TypeParam>(x, y), y > x ? min : x - y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UtilsTest, SaturateAdd) {
|
|
TypeParam min = std::numeric_limits<TypeParam>::min();
|
|
TypeParam max = std::numeric_limits<TypeParam>::max();
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(min, min), min);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(max, max), max);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(min, min / 3), min);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(max / 8 * 7, max / 3 * 2), max);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(min / 3 * 2, min / 8 * 7), min);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(max / 20 * 18, max / 25 * 18), max);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(min / 3 * 2, min / 3 * 2), min);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(max - 1, 2), max);
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(max - 100, 101), max);
|
|
TypeParam test_cases[] = {static_cast<TypeParam>(min / 23),
|
|
static_cast<TypeParam>(max / 3),
|
|
63,
|
|
static_cast<TypeParam>(min / 6),
|
|
static_cast<TypeParam>(max / 55),
|
|
static_cast<TypeParam>(min / 2),
|
|
static_cast<TypeParam>(max / 2),
|
|
0,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
42};
|
|
TRACED_FOREACH(TypeParam, x, test_cases) {
|
|
TRACED_FOREACH(TypeParam, y, test_cases) {
|
|
EXPECT_EQ(SaturateAdd<TypeParam>(x, y), x + y);
|
|
}
|
|
}
|
|
}
|
|
|
|
TYPED_TEST(UtilsTest, PassesFilterTest) {
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefg")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefg*")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abc*")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("*")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("-~")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefgh")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector("abdefg"), CStrVector("-")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefg")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefg*")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abc*")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-*")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("~")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefgh")));
|
|
|
|
EXPECT_TRUE(PassesFilter(CStrVector(""), CStrVector("")));
|
|
EXPECT_TRUE(PassesFilter(CStrVector(""), CStrVector("*")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("-")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("-*")));
|
|
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("a")));
|
|
}
|
|
|
|
TEST(UtilsTest, IsInBounds) {
|
|
// for column consistency and terseness
|
|
#define INB(x, y, z) EXPECT_TRUE(base::IsInBounds<size_t>(x, y, z))
|
|
#define OOB(x, y, z) EXPECT_FALSE(base::IsInBounds<size_t>(x, y, z))
|
|
INB(0, 0, 1);
|
|
INB(0, 1, 1);
|
|
INB(1, 0, 1);
|
|
|
|
OOB(0, 2, 1);
|
|
OOB(2, 0, 1);
|
|
|
|
INB(0, 0, 2);
|
|
INB(0, 1, 2);
|
|
INB(0, 2, 2);
|
|
|
|
INB(0, 0, 2);
|
|
INB(1, 0, 2);
|
|
INB(2, 0, 2);
|
|
|
|
OOB(0, 3, 2);
|
|
OOB(3, 0, 2);
|
|
|
|
INB(0, 1, 2);
|
|
INB(1, 1, 2);
|
|
|
|
OOB(1, 2, 2);
|
|
OOB(2, 1, 2);
|
|
|
|
const size_t max = std::numeric_limits<size_t>::max();
|
|
const size_t half = max / 2;
|
|
|
|
// limit cases.
|
|
INB(0, 0, max);
|
|
INB(0, 1, max);
|
|
INB(1, 0, max);
|
|
INB(max, 0, max);
|
|
INB(0, max, max);
|
|
INB(max - 1, 0, max);
|
|
INB(0, max - 1, max);
|
|
INB(max - 1, 1, max);
|
|
INB(1, max - 1, max);
|
|
|
|
INB(half, half, max);
|
|
INB(half + 1, half, max);
|
|
INB(half, half + 1, max);
|
|
|
|
OOB(max, 0, 0);
|
|
OOB(0, max, 0);
|
|
OOB(max, 0, 1);
|
|
OOB(0, max, 1);
|
|
OOB(max, 0, 2);
|
|
OOB(0, max, 2);
|
|
|
|
OOB(max, 0, max - 1);
|
|
OOB(0, max, max - 1);
|
|
|
|
// wraparound cases.
|
|
OOB(max, 1, max);
|
|
OOB(1, max, max);
|
|
OOB(max - 1, 2, max);
|
|
OOB(2, max - 1, max);
|
|
OOB(half + 1, half + 1, max);
|
|
OOB(half + 1, half + 1, max);
|
|
|
|
#undef INB
|
|
#undef OOB
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|