Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: base/numerics/safe_numerics_unittest.cc

Issue 2528243002: Fix silent truncations when extracting values from CheckedNumeric (Closed)
Patch Set: pointer math tests Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/numerics/safe_numerics_unittest.cc
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index 8ced4bdb7b244e0637dc18f8c2f296d84d49f671..9c767d24b518d18c08131106be1049b5d60f1595 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -22,6 +22,9 @@
using std::numeric_limits;
using base::CheckedNumeric;
+using base::IsValidForType;
+using base::ValueOrDieForType;
+using base::ValueOrDefaultForType;
using base::CheckNum;
using base::CheckAdd;
using base::CheckSub;
@@ -37,6 +40,7 @@ using base::SizeT;
using base::StrictNumeric;
using base::saturated_cast;
using base::strict_cast;
+using base::StrictNumeric;
using base::internal::MaxExponent;
using base::internal::RANGE_VALID;
using base::internal::RANGE_INVALID;
@@ -108,6 +112,20 @@ struct LogOnFailure {
<< "Result test: Value " << GetNumericValueForTest(actual) << " as " \
<< dst << " on line " << line
+// Test the simple pointer arithmetic overrides.
+template <typename Dst>
+void TestStrictPointerMath() {
+ Dst dummy_value = 0;
+ Dst* dummy_ptr = &dummy_value;
+ static const Dst kDummyOffset = 2; // Don't want to go too far.
+ EXPECT_EQ(dummy_ptr + kDummyOffset,
+ dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
+ EXPECT_EQ(dummy_ptr - kDummyOffset,
+ dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
+ EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
+ EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
+}
Tom Sepez 2016/11/30 23:58:27 Can we have a test that adding numeric_limits<uinp
jschuh 2016/12/01 00:58:55 Unfortunately, no, because I don't have have a way
danakj 2016/12/01 01:00:25 Death tests are a possibility if I'm understanding
+
// Signed integer arithmetic.
template <typename Dst>
static void TestSpecializedArithmetic(
@@ -170,6 +188,8 @@ static void TestSpecializedArithmetic(
TEST_EXPECTED_VALUE(0,
CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1));
TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
+
+ TestStrictPointerMath<Dst>();
}
// Unsigned integer arithmetic.
@@ -241,6 +261,8 @@ static void TestSpecializedArithmetic(
TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
+
+ TestStrictPointerMath<Dst>();
}
// Floating point arithmetic.
@@ -268,7 +290,6 @@ void TestSpecializedArithmetic(
TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
- EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
}
// Generic arithmetic tests.
@@ -411,6 +432,43 @@ struct TestNumericConversion {};
<< " on line " << line
template <typename Dst, typename Src>
+void TestStrictComparison() {
+ typedef numeric_limits<Dst> DstLimits;
+ typedef numeric_limits<Src> SrcLimits;
+ static_assert(StrictNumeric<Src>(SrcLimits::min()) < DstLimits::max(), "");
+ static_assert(StrictNumeric<Src>(SrcLimits::min()) < SrcLimits::max(), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= DstLimits::max()),
+ "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= SrcLimits::max()),
+ "");
+ static_assert(StrictNumeric<Src>(SrcLimits::min()) <= DstLimits::max(), "");
+ static_assert(StrictNumeric<Src>(SrcLimits::min()) <= SrcLimits::max(), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > DstLimits::max()), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > SrcLimits::max()), "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::min(), "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::min(), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::min()),
+ "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::min()),
+ "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::min(), "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::min(), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::min()), "");
+ static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::min()), "");
+ static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
+ "");
+ static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
+ "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
+ "");
+ static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::min(), "");
+ static_assert(
+ !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
+ static_assert(
+ !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
+}
+
+template <typename Dst, typename Src>
struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
static void Test(const char *dst, const char *src, int line) {
typedef numeric_limits<Src> SrcLimits;
@@ -426,6 +484,8 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
(DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
"Comparison must be sign preserving and value preserving");
+ TestStrictComparison<Dst, Src>();
+
const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
TEST_EXPECTED_SUCCESS(checked_dst);
if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
@@ -466,6 +526,8 @@ struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
(DstLimits::is_integer && SrcLimits::is_iec559),
"Destination must be narrower than source");
+ TestStrictComparison<Dst, Src>();
+
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
@@ -512,6 +574,8 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
static_assert(SrcLimits::is_signed, "Source must be signed");
static_assert(!DstLimits::is_signed, "Destination must be unsigned");
+ TestStrictComparison<Dst, Src>();
+
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
@@ -535,6 +599,8 @@ struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
static_assert(SrcLimits::is_signed, "Source must be signed.");
static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
+ TestStrictComparison<Dst, Src>();
+
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
@@ -577,6 +643,8 @@ struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
static_assert(DstLimits::is_signed, "Destination must be signed.");
+ TestStrictComparison<Dst, Src>();
+
const CheckedNumeric<Dst> checked_dst;
TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
@@ -754,22 +822,21 @@ TEST(SafeNumerics, CastTests) {
auto int8_max = CheckNum(numeric_limits<int8_t>::max());
auto double_max = CheckNum(numeric_limits<double>::max());
static_assert(
- std::is_same<int16_t, decltype(int8_min.ValueOrDie<int16_t>())>::value,
+ std::is_same<int16_t,
+ decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
"ValueOrDie returning incorrect type.");
static_assert(
std::is_same<int16_t,
- decltype(int8_min.ValueOrDefault<int16_t>(0))>::value,
+ decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
"ValueOrDefault returning incorrect type.");
- static_assert(
- std::is_same<float, decltype(double_max.ValueFloating<float>())>::value,
- "ValueFloating returning incorrect type.");
- EXPECT_FALSE(int8_min.template IsValid<uint8_t>());
- EXPECT_TRUE(int8_max.template IsValid<uint8_t>());
+ EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
+ EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()),
- int8_min.template ValueOrDie<int>());
- EXPECT_TRUE(int8_max.template IsValid<uint32_t>());
+ ValueOrDieForType<int>(int8_min));
+ EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
- int8_max.template ValueOrDie<int>());
+ ValueOrDieForType<int>(int8_max));
+ EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
uint8_t uint8_dest = 0;
int16_t int16_dest = 0;
double double_dest = 0;
@@ -896,19 +963,19 @@ TEST(SafeNumerics, CompoundNumericOperations) {
TEST(SafeNumerics, VariadicNumericOperations) {
auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(a)>(10), a);
+ EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(b)>(14.0), b);
+ EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(c)>(300.0), c);
+ EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(d)>(-.5), d);
+ EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
auto e = CheckMod(CheckNum(20), 3).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(e)>(2), e);
+ EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
auto f = CheckLsh(1, CheckNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(f)>(4), f);
+ EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
auto g = CheckRsh(4, CheckNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(g)>(1), g);
+ EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(h)>(1), h);
+ EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
}

Powered by Google App Engine
This is Rietveld 408576698