mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-08 05:27:14 +09:00
AK/Checked: Dont verify overflow bit in lvalue operations
Before, adding an overflow'n `Checked<T>` to another `Checked<T>` would cause a verification faliure when instead it should propogate m_overflow and allow the user to handle the overflow.
This commit is contained in:
parent
e5966eed08
commit
88c4f71114
Notes:
github-actions[bot]
2025-02-25 11:21:17 +00:00
Author: https://github.com/ttrssreal
Commit: 88c4f71114
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3630
Reviewed-by: https://github.com/gmta ✅
2 changed files with 53 additions and 10 deletions
20
AK/Checked.h
20
AK/Checked.h
|
@ -255,7 +255,7 @@ public:
|
|||
constexpr Checked& operator+=(Checked const& other)
|
||||
{
|
||||
m_overflow |= other.m_overflow;
|
||||
add(other.value());
|
||||
add(other.value_unchecked());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -268,7 +268,7 @@ public:
|
|||
constexpr Checked& operator-=(Checked const& other)
|
||||
{
|
||||
m_overflow |= other.m_overflow;
|
||||
sub(other.value());
|
||||
sub(other.value_unchecked());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ public:
|
|||
constexpr Checked& operator*=(Checked const& other)
|
||||
{
|
||||
m_overflow |= other.m_overflow;
|
||||
mul(other.value());
|
||||
mul(other.value_unchecked());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ public:
|
|||
constexpr Checked& operator/=(Checked const& other)
|
||||
{
|
||||
m_overflow |= other.m_overflow;
|
||||
div(other.value());
|
||||
div(other.value_unchecked());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ public:
|
|||
constexpr Checked& operator%=(Checked const& other)
|
||||
{
|
||||
m_overflow |= other.m_overflow;
|
||||
mod(other.value());
|
||||
mod(other.value_unchecked());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ template<typename T>
|
|||
constexpr Checked<T> operator+(Checked<T> const& a, Checked<T> const& b)
|
||||
{
|
||||
Checked<T> c { a };
|
||||
c.add(b.value());
|
||||
c += b;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -442,7 +442,7 @@ template<typename T>
|
|||
constexpr Checked<T> operator-(Checked<T> const& a, Checked<T> const& b)
|
||||
{
|
||||
Checked<T> c { a };
|
||||
c.sub(b.value());
|
||||
c -= b;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -450,7 +450,7 @@ template<typename T>
|
|||
constexpr Checked<T> operator*(Checked<T> const& a, Checked<T> const& b)
|
||||
{
|
||||
Checked<T> c { a };
|
||||
c.mul(b.value());
|
||||
c *= b;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -458,7 +458,7 @@ template<typename T>
|
|||
constexpr Checked<T> operator/(Checked<T> const& a, Checked<T> const& b)
|
||||
{
|
||||
Checked<T> c { a };
|
||||
c.div(b.value());
|
||||
c /= b;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -466,7 +466,7 @@ template<typename T>
|
|||
constexpr Checked<T> operator%(Checked<T> const& a, Checked<T> const& b)
|
||||
{
|
||||
Checked<T> c { a };
|
||||
c.mod(b.value());
|
||||
c %= b;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,49 @@ TEST_CASE(detects_unsigned_overflow)
|
|||
EXPECT((Checked<u64>(0x4000000000000000) - Checked<u64>(0x4000000000000001)).has_overflow());
|
||||
}
|
||||
|
||||
TEST_CASE(operations_with_overflowed)
|
||||
{
|
||||
{
|
||||
Checked<u32> overflowed(0x100000000);
|
||||
EXPECT((Checked<u32>(0x100000000) + Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((Checked<u32>(0xff) + Checked<u32>(0x100000000)).has_overflow());
|
||||
EXPECT((overflowed += Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((overflowed += Checked<u32>(0x100000000)).has_overflow());
|
||||
}
|
||||
|
||||
{
|
||||
Checked<u32> overflowed(0x100000000);
|
||||
EXPECT((Checked<u32>(0x100000000) - Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((Checked<u32>(0xff) - Checked<u32>(0x100000000)).has_overflow());
|
||||
EXPECT((overflowed -= Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((overflowed -= Checked<u32>(0x100000000)).has_overflow());
|
||||
}
|
||||
|
||||
{
|
||||
Checked<u32> overflowed(0x100000000);
|
||||
EXPECT((Checked<u32>(0x100000000) * Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((Checked<u32>(0xff) * Checked<u32>(0x100000000)).has_overflow());
|
||||
EXPECT((overflowed *= Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((overflowed *= Checked<u32>(0x100000000)).has_overflow());
|
||||
}
|
||||
|
||||
{
|
||||
Checked<u32> overflowed(0x100000000);
|
||||
EXPECT((Checked<u32>(0x100000000) / Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((Checked<u32>(0xff) / Checked<u32>(0x100000000)).has_overflow());
|
||||
EXPECT((overflowed /= Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((overflowed /= Checked<u32>(0x100000000)).has_overflow());
|
||||
}
|
||||
|
||||
{
|
||||
Checked<u32> overflowed(0x100000000);
|
||||
EXPECT((Checked<u32>(0x100000000) % Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((Checked<u32>(0xff) % Checked<u32>(0x100000000)).has_overflow());
|
||||
EXPECT((overflowed %= Checked<u32>(0xff)).has_overflow());
|
||||
EXPECT((overflowed %= Checked<u32>(0x100000000)).has_overflow());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(should_constexpr_default_construct)
|
||||
{
|
||||
constexpr Checked<int> checked_value {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue