AK: Prevent overflow of the min when clamping unsigned values to signed

Also, add some tests for the cases that were broken before.
This commit is contained in:
Zaggy1024 2024-06-19 22:04:45 -05:00 committed by Andrew Kaster
parent 172f4588a7
commit bbd8a218a5
Notes: sideshowbarker 2024-07-17 03:19:14 +09:00
2 changed files with 12 additions and 4 deletions

View file

@ -1008,11 +1008,17 @@ constexpr T pow(T x, T y)
template<Integral I, typename T> template<Integral I, typename T>
constexpr I clamp_to(T value) constexpr I clamp_to(T value)
{ {
if (value >= static_cast<T>(NumericLimits<I>::max())) constexpr auto max = static_cast<T>(NumericLimits<I>::max());
return NumericLimits<I>::max(); if constexpr (max > 0) {
if (value >= static_cast<T>(NumericLimits<I>::max()))
return NumericLimits<I>::max();
}
if (value <= static_cast<T>(NumericLimits<I>::min())) constexpr auto min = static_cast<T>(NumericLimits<I>::min());
return NumericLimits<I>::min(); if constexpr (min <= 0) {
if (value <= static_cast<T>(NumericLimits<I>::min()))
return NumericLimits<I>::min();
}
if constexpr (IsFloatingPoint<T>) if constexpr (IsFloatingPoint<T>)
return round_to<I>(value); return round_to<I>(value);

View file

@ -119,9 +119,11 @@ TEST_CASE(ceil_log2)
TEST_CASE(clamp_to) TEST_CASE(clamp_to)
{ {
EXPECT_EQ((AK::clamp_to<i32>(1000000u)), 1000000);
EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<u64>::max())), NumericLimits<i32>::max()); EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<u64>::max())), NumericLimits<i32>::max());
EXPECT_EQ((AK::clamp_to<u32>(-10)), 0u); EXPECT_EQ((AK::clamp_to<u32>(-10)), 0u);
EXPECT_EQ((AK::clamp_to<u32>(10)), 10u);
EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<i64>::min())), NumericLimits<i32>::min()); EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<i64>::min())), NumericLimits<i32>::min());
EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<i64>::max())), NumericLimits<i32>::max()); EXPECT_EQ((AK::clamp_to<i32>(NumericLimits<i64>::max())), NumericLimits<i32>::max());