mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibCrypto: Do not allow signed big integers to be negative zero
If a big integer were to become negative zero, set the sign to instead be positive. This prevents odd scenarios where users of signed big ints would falsely think the result of some big int arithmetic is negative.
This commit is contained in:
parent
4d785b9aa0
commit
b0d6399f60
Notes:
sideshowbarker
2024-07-17 19:42:54 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/b0d6399f607 Pull-request: https://github.com/SerenityOS/serenity/pull/12307 Reviewed-by: https://github.com/linusg ✅
4 changed files with 45 additions and 2 deletions
|
@ -642,3 +642,19 @@ TEST_CASE(test_signed_multiplication_with_two_big_numbers)
|
|||
EXPECT_EQ(result.unsigned_value().words(), expected_results);
|
||||
EXPECT(result.is_negative());
|
||||
}
|
||||
|
||||
TEST_CASE(test_negative_zero_is_not_allowed)
|
||||
{
|
||||
Crypto::SignedBigInteger zero(Crypto::UnsignedBigInteger(0), true);
|
||||
EXPECT(!zero.is_negative());
|
||||
|
||||
zero.negate();
|
||||
EXPECT(!zero.is_negative());
|
||||
|
||||
Crypto::SignedBigInteger positive_five(Crypto::UnsignedBigInteger(5), false);
|
||||
Crypto::SignedBigInteger negative_five(Crypto::UnsignedBigInteger(5), true);
|
||||
zero = positive_five.plus(negative_five);
|
||||
|
||||
EXPECT(zero.unsigned_value().is_zero());
|
||||
EXPECT(!zero.is_negative());
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
: m_sign(sign)
|
||||
, m_unsigned_data(move(unsigned_data))
|
||||
{
|
||||
ensure_sign_is_valid();
|
||||
}
|
||||
|
||||
explicit SignedBigInteger(UnsignedBigInteger unsigned_data)
|
||||
|
@ -72,9 +73,18 @@ public:
|
|||
const Vector<u32, STARTING_WORD_SIZE> words() const { return m_unsigned_data.words(); }
|
||||
bool is_negative() const { return m_sign; }
|
||||
|
||||
void negate() { m_sign = !m_sign; }
|
||||
void negate()
|
||||
{
|
||||
if (!m_unsigned_data.is_zero())
|
||||
m_sign = !m_sign;
|
||||
}
|
||||
|
||||
void set_to_0()
|
||||
{
|
||||
m_unsigned_data.set_to_0();
|
||||
m_sign = false;
|
||||
}
|
||||
|
||||
void set_to_0() { m_unsigned_data.set_to_0(); }
|
||||
void set_to(i32 other)
|
||||
{
|
||||
m_unsigned_data.set_to((u32)other);
|
||||
|
@ -129,6 +139,12 @@ public:
|
|||
bool operator>(const UnsignedBigInteger& other) const;
|
||||
|
||||
private:
|
||||
void ensure_sign_is_valid()
|
||||
{
|
||||
if (m_sign && m_unsigned_data.is_zero())
|
||||
m_sign = false;
|
||||
}
|
||||
|
||||
bool m_sign { false };
|
||||
UnsignedBigInteger m_unsigned_data;
|
||||
};
|
||||
|
|
|
@ -145,6 +145,16 @@ void UnsignedBigInteger::set_to(const UnsignedBigInteger& other)
|
|||
m_cached_hash = 0;
|
||||
}
|
||||
|
||||
bool UnsignedBigInteger::is_zero() const
|
||||
{
|
||||
for (size_t i = 0; i < length(); ++i) {
|
||||
if (m_words[i] != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t UnsignedBigInteger::trimmed_length() const
|
||||
{
|
||||
if (!m_cached_trimmed_length.has_value()) {
|
||||
|
|
|
@ -72,6 +72,7 @@ public:
|
|||
m_cached_hash = 0;
|
||||
}
|
||||
|
||||
bool is_zero() const;
|
||||
bool is_odd() const { return m_words.size() && (m_words[0] & 1); }
|
||||
bool is_invalid() const { return m_is_invalid; }
|
||||
|
||||
|
|
Loading…
Reference in a new issue