From 8600c5149b9fc9d090d846b5b6fc44eb214127b9 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 21 Jul 2025 07:31:33 -0400 Subject: [PATCH] LibCrypto: Allow moving SignedBigInteger / UnsignedBigInteger We defined copy operations but not move operations, so every existing move() resulted in a copy. --- .../LibCrypto/BigInt/SignedBigInteger.cpp | 23 +++++++++++++++++++ Libraries/LibCrypto/BigInt/SignedBigInteger.h | 3 +++ .../LibCrypto/BigInt/UnsignedBigInteger.cpp | 23 +++++++++++++++++++ .../LibCrypto/BigInt/UnsignedBigInteger.h | 3 +++ Tests/LibCrypto/TestBigInteger.cpp | 17 ++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp index 32e43317a10..c6998ca980e 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.cpp @@ -52,6 +52,14 @@ SignedBigInteger::SignedBigInteger(SignedBigInteger const& other) MP_MUST(mp_init_copy(&m_mp, &other.m_mp)); } +SignedBigInteger::SignedBigInteger(SignedBigInteger&& other) + : m_mp(other.m_mp) + , m_hash(other.m_hash) +{ + other.m_mp = {}; + other.m_hash.clear(); +} + SignedBigInteger& SignedBigInteger::operator=(SignedBigInteger const& other) { if (this == &other) @@ -64,6 +72,21 @@ SignedBigInteger& SignedBigInteger::operator=(SignedBigInteger const& other) return *this; } +SignedBigInteger& SignedBigInteger::operator=(SignedBigInteger&& other) +{ + if (this == &other) + return *this; + + mp_clear(&m_mp); + m_mp = other.m_mp; + m_hash = other.m_hash; + + other.m_mp = {}; + other.m_hash.clear(); + + return *this; +} + SignedBigInteger::SignedBigInteger() { MP_MUST(mp_init(&m_mp)); diff --git a/Libraries/LibCrypto/BigInt/SignedBigInteger.h b/Libraries/LibCrypto/BigInt/SignedBigInteger.h index 6db09b3aa73..0cce9529531 100644 --- a/Libraries/LibCrypto/BigInt/SignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/SignedBigInteger.h @@ -29,7 +29,10 @@ public: explicit SignedBigInteger(i64 value); SignedBigInteger(SignedBigInteger const&); + SignedBigInteger(SignedBigInteger&&); + SignedBigInteger& operator=(SignedBigInteger const&); + SignedBigInteger& operator=(SignedBigInteger&&); SignedBigInteger(); ~SignedBigInteger(); diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp index bd697fe1473..b2b8f279da6 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp @@ -55,6 +55,14 @@ UnsignedBigInteger::UnsignedBigInteger(UnsignedBigInteger const& other) MP_MUST(mp_init_copy(&m_mp, &other.m_mp)); } +UnsignedBigInteger::UnsignedBigInteger(UnsignedBigInteger&& other) + : m_mp(other.m_mp) + , m_hash(other.m_hash) +{ + other.m_mp = {}; + other.m_hash.clear(); +} + UnsignedBigInteger& UnsignedBigInteger::operator=(UnsignedBigInteger const& other) { if (this == &other) @@ -67,6 +75,21 @@ UnsignedBigInteger& UnsignedBigInteger::operator=(UnsignedBigInteger const& othe return *this; } +UnsignedBigInteger& UnsignedBigInteger::operator=(UnsignedBigInteger&& other) +{ + if (this == &other) + return *this; + + mp_clear(&m_mp); + m_mp = other.m_mp; + m_hash = other.m_hash; + + other.m_mp = {}; + other.m_hash.clear(); + + return *this; +} + UnsignedBigInteger::UnsignedBigInteger() { MP_MUST(mp_init(&m_mp)); diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h index 85d28261ac7..a0511838658 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.h @@ -31,7 +31,10 @@ public: explicit UnsignedBigInteger(u64 value); UnsignedBigInteger(UnsignedBigInteger const&); + UnsignedBigInteger(UnsignedBigInteger&&); + UnsignedBigInteger& operator=(UnsignedBigInteger const&); + UnsignedBigInteger& operator=(UnsignedBigInteger&&); UnsignedBigInteger(); ~UnsignedBigInteger(); diff --git a/Tests/LibCrypto/TestBigInteger.cpp b/Tests/LibCrypto/TestBigInteger.cpp index 169c79af207..aeab0d8c474 100644 --- a/Tests/LibCrypto/TestBigInteger.cpp +++ b/Tests/LibCrypto/TestBigInteger.cpp @@ -901,6 +901,23 @@ TEST_CASE(unsigned_bigint_double_comparisons) #undef EXPECT_EQUAL_TO } +TEST_CASE(moving_bigints) +{ + Crypto::UnsignedBigInteger bigint1; + { + auto bigint2 = "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789"_bigint; + bigint1 = move(bigint2); + EXPECT(bigint2.is_zero()); + } + + EXPECT_EQ(MUST(bigint1.to_base(10)), "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789"sv); + + Crypto::UnsignedBigInteger bigint3 { move(bigint1) }; + EXPECT(bigint1.is_zero()); + + EXPECT_EQ(MUST(bigint3.to_base(10)), "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789"sv); +} + namespace AK { template<>