| // Copyright 2026 The Chromium 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 "quiche/common/quiche_checked_math.h" | |
| #include <cstdint> | |
| #include <limits> | |
| #include <optional> | |
| #include "quiche/common/platform/api/quiche_test.h" | |
| namespace quiche { | |
| namespace { | |
| template <typename Int> | |
| void RunAddTests() { | |
| constexpr Int kMax = std::numeric_limits<Int>::max(); | |
| EXPECT_EQ(SafeAdd<Int>(0, 0), 0); | |
| EXPECT_EQ(SafeAdd<Int>(2, 2), 4); | |
| EXPECT_EQ(SafeAdd<Int>(kMax - 1, 1), kMax); | |
| EXPECT_EQ(SafeAdd<Int>(kMax, 0), kMax); | |
| EXPECT_EQ(SafeAdd<Int>(kMax - 1, 2), std::nullopt); | |
| EXPECT_EQ(SafeAdd<Int>(kMax, 1), std::nullopt); | |
| EXPECT_EQ(SafeAdd<Int>(kMax, kMax), std::nullopt); | |
| } | |
| TEST(QuicheCheckedMathTest, Add) { | |
| // Spell out uint8_t tests explicitly to make them easier to follow. | |
| EXPECT_EQ(SafeAdd<uint8_t>(0, 0), 0); | |
| EXPECT_EQ(SafeAdd<uint8_t>(2, 2), 4); | |
| EXPECT_EQ(SafeAdd<uint8_t>(254, 1), 255); | |
| EXPECT_EQ(SafeAdd<uint8_t>(255, 0), 255); | |
| EXPECT_EQ(SafeAdd<uint8_t>(254, 2), std::nullopt); | |
| EXPECT_EQ(SafeAdd<uint8_t>(255, 1), std::nullopt); | |
| EXPECT_EQ(SafeAdd<uint8_t>(255, 255), std::nullopt); | |
| // Run the remainder of tests through a templated function. | |
| RunAddTests<uint16_t>(); | |
| RunAddTests<uint32_t>(); | |
| RunAddTests<uint64_t>(); | |
| } | |
| template <typename Int> | |
| void RunIncrementTests() { | |
| constexpr Int kMax = std::numeric_limits<Int>::max(); | |
| Int var = kMax - 5; | |
| EXPECT_TRUE(SafeIncrementBy<Int>(var, 0)); | |
| EXPECT_EQ(var, kMax - 5); | |
| EXPECT_TRUE(SafeIncrementBy<Int>(var, 5)); | |
| EXPECT_EQ(var, kMax); | |
| EXPECT_FALSE(SafeIncrementBy<Int>(var, 1)); | |
| EXPECT_EQ(var, kMax); | |
| } | |
| TEST(QuicheCheckedMathTest, IncrementBy) { | |
| // Spell out uint8_t tests explicitly to make them easier to follow. | |
| uint8_t var8 = 250; | |
| EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 0)); | |
| EXPECT_EQ(var8, 250); | |
| EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 2)); | |
| EXPECT_EQ(var8, 252); | |
| EXPECT_TRUE(SafeIncrementBy<uint8_t>(var8, 3)); | |
| EXPECT_EQ(var8, 255); | |
| EXPECT_FALSE(SafeIncrementBy<uint8_t>(var8, 1)); | |
| EXPECT_EQ(var8, 255); | |
| EXPECT_FALSE(SafeIncrementBy<uint8_t>(var8, 255)); | |
| EXPECT_EQ(var8, 255); | |
| // Run the remainder of tests through a templated function. | |
| RunIncrementTests<uint16_t>(); | |
| RunIncrementTests<uint32_t>(); | |
| RunIncrementTests<uint64_t>(); | |
| } | |
| TEST(QuicheCheckedMathTest, Sum) { | |
| EXPECT_EQ(SafeSum<uint8_t>({}), 0); | |
| EXPECT_EQ(SafeSum<uint8_t>({2, 2}), 4); | |
| EXPECT_EQ(SafeSum<uint8_t>({1, 2, 3}), 6); | |
| EXPECT_EQ(SafeSum<uint8_t>({200, 200}), std::nullopt); | |
| EXPECT_EQ(SafeSum<uint8_t>({200, 200, 200}), std::nullopt); | |
| EXPECT_EQ(SafeSum<uint8_t>({100, 100, 100}), std::nullopt); | |
| EXPECT_EQ(SafeSum<uint8_t>({128, 126, 1}), 255); | |
| EXPECT_EQ(SafeSum<uint8_t>({128, 126, 2}), std::nullopt); | |
| } | |
| } // namespace | |
| } // namespace quiche |